Files
apfstests/common/punch
T
Qu Wenruo 6df776bae8 generic: extent map search on dedupe file
For fully deduped file, which means all its file exntents are
pointing to the same bytenr, btrfs can cause soft lockup when
calling fiemap ioctl on that file, like the following output:
------
CPU: 1 PID: 7500 Comm: xfs_io Not tainted 4.5.0-rc6+ #2
Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox
12/01/2006
task: ffff880027681b40 ti: ffff8800276e0000 task.ti: ffff8800276e0000
RIP: 0010:[<ffffffffa02583e4>]  [<ffffffffa02583e4>]
__merge_refs+0x34/0x120 [btrfs]
RSP: 0018:ffff8800276e3c08  EFLAGS: 00000202
RAX: ffff8800269cc330 RBX: ffff8800269cdb18 RCX: 0000000000000007
RDX: 00000000000061b0 RSI: ffff8800269cc4c8 RDI: ffff8800276e3c88
RBP: ffff8800276e3c20 R08: 0000000000000000 R09: 0000000000000001
R10: 0000000000000000 R11: 0000000000000000 R12: ffff880026ea3cb0
R13: ffff8800276e3c88 R14: ffff880027132a50 R15: ffff880027430000
FS:  00007f10201df700(0000) GS:ffff88003fa00000(0000)
knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f10201ec000 CR3: 0000000027603000 CR4: 00000000000406e0
Stack:
 0000000000000000 0000000000000000 0000000000000000 ffff8800276e3ce8
 ffffffffa0259f38 0000000000000005 ffff8800274c6870 ffff8800274c7d88
 0000000000c10000 0000000000000000 0000000000000001 0000000027431190
Call Trace:
 [<ffffffffa0259f38>] find_parent_nodes+0x448/0x740 [btrfs]
 [<ffffffffa025a4f2>] btrfs_check_shared+0x102/0x1b0 [btrfs]
 [<ffffffff811fdcad>] ? __might_fault+0x4d/0xa0
 [<ffffffffa021899c>] extent_fiemap+0x2ac/0x550 [btrfs]
 [<ffffffff811ce156>] ? __filemap_fdatawait_range+0x96/0x160
 [<ffffffffa01f8ee0>] ? btrfs_get_extent+0xb30/0xb30 [btrfs]
 [<ffffffffa01f5da5>] btrfs_fiemap+0x45/0x50 [btrfs]
 [<ffffffff81246bb8>] do_vfs_ioctl+0x498/0x670
 [<ffffffff81246e09>] SyS_ioctl+0x79/0x90
 [<ffffffff8184e997>] entry_SYSCALL_64_fastpath+0x12/0x6f
Code: 41 55 41 54 53 4c 8b 27 4c 39 e7 0f 84 e9 00 00 00 49 89 fd 49 8b
34 24 49 39 f5 48 8b 1e 75 17 e9 d5 00 00 00 49 39 dd 48 8b 03 <48> 89
de 0f 84 b9 00 00 00 48 89 c3 8b 46 2c 41 39 44 24 2c 75
------

Also btrfs will return wrong flag for all these extents, they should
have SHARED(0x2000) flags, while btrfs still consider them as
exclusive extents.

On the other hand, with unmerged xfs reflink patches, xfs can handle
it without problem, and for patched btrfs, it can also handle it.

This test case will create a large fully deduped file to check if
the fs can handle the fiemap ioctl and return correct SHARED flag
for any fs which support reflink.

Reported-by: Tsutomu Itoh <t-itoh@jp.fujitsu.com>
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Reviewed-by: Eryu Guan <eguan@redhat.com>
Signed-off-by: Eryu Guan <eguan@redhat.com>
2016-06-15 15:09:17 +08:00

702 lines
17 KiB
Plaintext

##/bin/bash
#
# Copyright (c) 2007 Silicon Graphics, Inc. All Rights Reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it would be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
#
# common functions for excersizing hole punches with extent size hints etc.
# source dmap_scratch_mount etc.
. ./common/dmapi
_spawn_test_file() {
echo "# spawning test file with $*"
local blksize=$1
local file_size=`expr $2 \* $blksize`
local extent_size_hint=`expr $3 \* $blksize`
local test_file=$4
local reserve_space=$5
if [ $extent_size_hint -ne 0 ]; then
echo "+ setting extent size hint to $extent_size_hint"
$XFS_IO_PROG -f \
-c "extsize $extent_size_hint" \
$test_file
fi
# print extent size hint for $test_file
$XFS_IO_PROG -f \
-c "extsize" \
$test_file
if [ "$reserve_space" == "noresv" ]; then
echo "+ not using resvsp at file creation"
$XFS_IO_PROG -f \
-c "truncate $file_size" \
$test_file
else
$XFS_IO_PROG -f \
-c "truncate $file_size" \
-c "resvsp 0 $file_size" \
$test_file
fi
}
_do_punch() {
echo "# punching with $*"
# punch or bite the ear off $test_file to create a hole
local blksize=$1
local punch_offset=`expr $2 \* $blksize`
local punch_size=`expr $3 \* $blksize`
local punch_type=$4 # u for unresvsp, d for dm_punch
local test_file=$5
if [ "$punch_type" == "u" ]; then
echo "+ hole punch using unresvsp"
$XFS_IO_PROG -f \
-c "unresvsp $punch_offset $punch_size" \
$test_file
fi
if [ "$punch_type" == "d" ]; then
echo "+ hole punch using dmapi punch_hole"
${DMAPI_QASUITE1_DIR}cmd/punch_hole -o $punch_offset -l $punch_size \
${SCRATCH_MNT}/$test_file
fi
}
_do_write() {
echo "# writing with $*"
local blksize=$1
local write_offset=`expr $2 \* $blksize`
local write_size=`expr $3 \* $blksize`
local test_file=$4
$XFS_IO_PROG -f \
-c "pwrite $write_offset $write_size" \
$test_file >/dev/null
}
_do_bmap() {
echo "# showing file state $*"
local test_file=$1
$XFS_IO_PROG -f \
-c "bmap -vvp" \
$test_file
}
_test_punch() {
echo "# testing $* ..."
local blksize=$1
# all points and sizes below are in terms of filesystem blocks
local extsize_hint_blks=$2 # extent size hint in FS blocks, 0=do not set
local file_size_blks=$3 # the file size in blocks
local punch_points_blks=( $4 ) # array of places to punch holes in the file
local punch_sizes_blks=( $5 ) # array of size of each punch in blocks
local punch_types=( $6 ) # array of u=unresvsp or d=dm_punch
local write_points_blks=( $7 ) # array of places to pwrite in the file
local write_sizes_blks=( $8 ) # array of size of each write
local punch_write_order=( $9 ) # array of punch/write operation order
# e.g. "w p w w p" means: do 1st write...
# then 1st punch, 2nd & 3rd write, 2nd punch
local resvsp=${10} # if "noresv" then don't resvsp on file create
local filename=punch_test_file
cd /
_scratch_unmount >/dev/null 2>&1
_scratch_mkfs_xfs -bsize=$blksize >/dev/null 2>&1 \
|| _fail "mkfs failed"
local this_punch_type=""
local dmap_punch_used=0
for this_punch_type in "${punch_types[@]}"; do
[ "$this_punch_type" == "d" ] && dmap_punch_used=1
done
if [ $dmap_punch_used -ne 0 ]; then
# a punch type of dm_punch has been specified, do a dmapi mount
echo "+ mounting with dmapi enabled"
_dmapi_scratch_mount
else
# only unresvsp punch type is used, just do a normal mount
_scratch_mount || _fail "mount failed"
fi
cd $SCRATCH_MNT
# check a size is specified for each punch
[ ${#punch_points_blks[*]} -eq ${#punch_sizes_blks[*]} ] \
|| _fail "num punch points given does not equal num punch sizes"
# check a type is specified for each punch
[ ${#punch_points_blks[*]} -eq ${#punch_types[*]} ] \
|| _fail "num punch points given does not equal num punch types"
# check a size is specified for each write
[ ${#write_points_blks[*]} -eq ${#write_sizes_blks[*]} ] \
|| _fail "num write points given does not equal num write sizes"
# check punch_write_order operations match number of punches + writes
local total_pw_operations=`expr ${#punch_points_blks[*]} + ${#write_points_blks[*]}`
[ $total_pw_operations -eq ${#punch_write_order[*]} ] \
|| _fail "punch_write_order ops doesn't match number of punches + writes"
# create the file and setup extent size hint
_spawn_test_file $blksize $file_size_blks $extsize_hint_blks $filename $resvsp
# do the writes and punches
local operation=""
local punch_index=0
local write_index=0
for operation in "${punch_write_order[@]}"; do
if [ "$operation" == "p" ]; then
_do_punch $blksize ${punch_points_blks[$punch_index]} \
${punch_sizes_blks[$punch_index]} ${punch_types[$punch_index]} \
$filename
punch_index=`expr $punch_index + 1`
fi
if [ "$operation" == "w" ]; then
_do_write $blksize ${write_points_blks[$write_index]} \
${write_sizes_blks[$write_index]} $filename
write_index=`expr $write_index + 1`
fi
sync
_do_bmap $filename # print out the state of the file
done
}
_coalesce_extents()
{
awk -F: '
{
range = $2;
type = $3;
split(range, bounds, "[\\[ \\.\\]]");
low = bounds[3];
high = bounds[5];
if (type != prev_type) {
if (prev_type != "")
printf("%u]:%s\n", low - 1, prev_type);
printf("%u: [%u..", out_count++, low);
prev_type = type;
}
}
END {
if (prev_type != "")
printf("%u]:%s\n", high, prev_type);
}'
}
_filter_fiemap()
{
$AWK_PROG '
$3 ~ /hole/ {
print $1, $2, $3;
next;
}
$5 ~ /0x[[:xdigit:]]*8[[:xdigit:]][[:xdigit:]]/ {
print $1, $2, "unwritten";
next;
}
$5 ~ /0x[[:xdigit:]]+/ {
print $1, $2, "data";
}' |
_coalesce_extents
}
_filter_fiemap_flags()
{
$AWK_PROG '
$3 ~ /hole/ {
print $1, $2, $3;
next;
}
$5 ~ /0x[[:xdigit:]]*8[[:xdigit:]][[:xdigit:]]/ {
print $1, $2, "unwritten";
next;
}
$5 ~ /0x[[:xdigit:]]+/ {
print $1, $2, $5;
}' |
_coalesce_extents
}
# Filters fiemap output to only print the
# file offset column and whether or not
# it is an extent or a hole
_filter_hole_fiemap()
{
$AWK_PROG '
$3 ~ /hole/ {
print $1, $2, $3;
next;
}
$5 ~ /0x[[:xdigit:]]+/ {
print $1, $2, "extent";
}' |
_coalesce_extents
}
# 10000 Unwritten preallocated extent
# 01000 Doesn't begin on stripe unit
# 00100 Doesn't end on stripe unit
# 00010 Doesn't begin on stripe width
# 00001 Doesn't end on stripe width
_filter_bmap()
{
awk '
$3 ~ /hole/ {
print $1, $2, $3;
next;
}
$7 ~ /1[01][01][01][01]/ {
print $1, $2, "unwritten";
next;
}
$7 ~ /0[01][01][01][01]/ {
print $1, $2, "data"
}' |
_coalesce_extents
}
die_now()
{
status=1
exit
}
# test the different corner cases for zeroing a range:
#
# 1. into a hole
# 2. into allocated space
# 3. into unwritten space
# 4. hole -> data
# 5. hole -> unwritten
# 6. data -> hole
# 7. data -> unwritten
# 8. unwritten -> hole
# 9. unwritten -> data
# 10. hole -> data -> hole
# 11. data -> hole -> data
# 12. unwritten -> data -> unwritten
# 13. data -> unwritten -> data
# 14. data -> hole @ EOF
# 15. data -> hole @ 0
# 16. data -> cache cold ->hole
# 17. data -> hole in single block file
#
# Test file is removed, created and sync'd between tests.
#
# Use -k flag to keep the file between tests. This will
# test the handling of pre-existing holes.
#
# Use the -d flag to not sync the file between tests.
# This will test the handling of delayed extents
#
# Use the -u flag to not run unwritten tests.
# This will eliminate some unnecessary information.
#
_test_generic_punch()
{
remove_testfile=1
sync_cmd="-c fsync"
unwritten_tests=1
OPTIND=1
while getopts 'dku' OPTION
do
case $OPTION in
k) remove_testfile=
;;
d) sync_cmd=
;;
u) unwritten_tests=
;;
?) echo Invalid flag
exit 1
;;
esac
done
shift $(($OPTIND - 1))
alloc_cmd=$1
punch_cmd=$2
zero_cmd=$3 #if not testing zero just set to punch
map_cmd=$4
filter_cmd=$5
testfile=$6
multiple=1
#
# If we are testing collapse range, we increare all the offsets of this
# test by a factor of 4. We do this because unlike punch, collapse
# range also decreases the size of file hence require bigger offsets.
#
if [ "$zero_cmd" == "fcollapse" ]; then
multiple=4
fi
_4k="$((multiple * 4))k"
_8k="$((multiple * 8))k"
_12k="$((multiple * 12))k"
_20k="$((multiple * 20))k"
# initial test state must be defined, otherwise the first test can fail
# due ot stale file state left from previous tests.
rm -f $testfile
echo " 1. into a hole"
$XFS_IO_PROG -f -c "truncate $_20k" \
-c "$zero_cmd $_4k $_8k" \
-c "$map_cmd -v" $testfile | $filter_cmd
[ $? -ne 0 ] && die_now
_md5_checksum $testfile
echo " 2. into allocated space"
if [ "$remove_testfile" ]; then
rm -f $testfile
fi
$XFS_IO_PROG -f -c "truncate $_20k" \
-c "pwrite 0 $_20k" $sync_cmd \
-c "$zero_cmd $_4k $_8k" \
-c "$map_cmd -v" $testfile | $filter_cmd
[ $? -ne 0 ] && die_now
_md5_checksum $testfile
if [ "$unwritten_tests" ]; then
echo " 3. into unwritten space"
if [ "$remove_testfile" ]; then
rm -f $testfile
fi
$XFS_IO_PROG -f -c "truncate $_20k" \
-c "$alloc_cmd 0 $_20k" \
-c "$zero_cmd $_4k $_8k" \
-c "$map_cmd -v" $testfile | $filter_cmd
[ $? -ne 0 ] && die_now
_md5_checksum $testfile
fi
echo " 4. hole -> data"
if [ "$remove_testfile" ]; then
rm -f $testfile
fi
$XFS_IO_PROG -f -c "truncate $_20k" \
-c "pwrite $_8k $_8k" $sync_cmd \
-c "$zero_cmd $_4k $_8k" \
-c "$map_cmd -v" $testfile | $filter_cmd
[ $? -ne 0 ] && die_now
_md5_checksum $testfile
if [ "$unwritten_tests" ]; then
echo " 5. hole -> unwritten"
if [ "$remove_testfile" ]; then
rm -f $testfile
fi
$XFS_IO_PROG -f -c "truncate $_20k" \
-c "$alloc_cmd $_8k $_8k" \
-c "$zero_cmd $_4k $_8k" \
-c "$map_cmd -v" $testfile | $filter_cmd
[ $? -ne 0 ] && die_now
_md5_checksum $testfile
fi
echo " 6. data -> hole"
if [ "$remove_testfile" ]; then
rm -f $testfile
fi
$XFS_IO_PROG -f -c "truncate $_20k" \
-c "pwrite 0 $_8k" $sync_cmd \
-c "$zero_cmd $_4k $_8k" \
-c "$map_cmd -v" $testfile | $filter_cmd
[ $? -ne 0 ] && die_now
_md5_checksum $testfile
if [ "$unwritten_tests" ]; then
echo " 7. data -> unwritten"
if [ "$remove_testfile" ]; then
rm -f $testfile
fi
$XFS_IO_PROG -f -c "truncate $_20k" \
-c "pwrite 0 $_8k" $sync_cmd \
-c "$alloc_cmd $_8k $_8k" \
-c "$zero_cmd $_4k $_8k" \
-c "$map_cmd -v" $testfile | $filter_cmd
[ $? -ne 0 ] && die_now
_md5_checksum $testfile
echo " 8. unwritten -> hole"
if [ "$remove_testfile" ]; then
rm -f $testfile
fi
$XFS_IO_PROG -f -c "truncate $_20k" \
-c "$alloc_cmd 0 $_8k" \
-c "$zero_cmd $_4k $_8k" \
-c "$map_cmd -v" $testfile | $filter_cmd
[ $? -ne 0 ] && die_now
_md5_checksum $testfile
echo " 9. unwritten -> data"
if [ "$remove_testfile" ]; then
rm -f $testfile
fi
$XFS_IO_PROG -f -c "truncate $_20k" \
-c "$alloc_cmd 0 $_8k" \
-c "pwrite $_8k $_8k" $sync_cmd \
-c "$zero_cmd $_4k $_8k" \
-c "$map_cmd -v" $testfile | $filter_cmd
[ $? -ne 0 ] && die_now
_md5_checksum $testfile
fi
echo " 10. hole -> data -> hole"
if [ "$remove_testfile" ]; then
rm -f $testfile
fi
$XFS_IO_PROG -f -c "truncate $_20k" \
-c "pwrite $_8k $_4k" $sync_cmd \
-c "$zero_cmd $_4k $_12k" \
-c "$map_cmd -v" $testfile | $filter_cmd
[ $? -ne 0 ] && die_now
_md5_checksum $testfile
echo " 11. data -> hole -> data"
if [ "$remove_testfile" ]; then
rm -f $testfile
fi
$XFS_IO_PROG -f -c "truncate $_20k" \
-c "$alloc_cmd 0 $_20k" \
-c "pwrite 0 $_8k" \
-c "pwrite $_12k $_8k" $sync_cmd \
-c "$punch_cmd $_8k $_4k" \
-c "$zero_cmd $_4k $_12k" \
-c "$map_cmd -v" $testfile | $filter_cmd
[ $? -ne 0 ] && die_now
_md5_checksum $testfile
if [ "$unwritten_tests" ]; then
echo " 12. unwritten -> data -> unwritten"
if [ "$remove_testfile" ]; then
rm -f $testfile
fi
$XFS_IO_PROG -f -c "truncate $_20k" \
-c "$alloc_cmd 0 $_20k" \
-c "pwrite $_8k $_4k" $sync_cmd \
-c "$zero_cmd $_4k $_12k" \
-c "$map_cmd -v" $testfile | $filter_cmd
[ $? -ne 0 ] && die_now
_md5_checksum $testfile
echo " 13. data -> unwritten -> data"
if [ "$remove_testfile" ]; then
rm -f $testfile
fi
$XFS_IO_PROG -f -c "truncate $_20k" \
-c "$alloc_cmd 0 $_20k" \
-c "pwrite 0k $_4k" $sync_cmd \
-c "pwrite $_12k $_8k" -c "fsync" \
-c "$zero_cmd $_4k $_12k" \
-c "$map_cmd -v" $testfile | $filter_cmd
[ $? -ne 0 ] && die_now
_md5_checksum $testfile
fi
# Don't need to check EOF case for collapse range.
# VFS layer return invalid error in this case,
# So it is not a proper case for collapse range test of each local fs.
if [ "$zero_cmd" != "fcollapse" ]; then
echo " 14. data -> hole @ EOF"
rm -f $testfile
$XFS_IO_PROG -f -c "truncate $_20k" \
-c "pwrite 0 $_20k" $sync_cmd \
-c "$zero_cmd $_12k $_8k" \
-c "$map_cmd -v" $testfile | $filter_cmd
[ $? -ne 0 ] && die_now
_md5_checksum $testfile
fi
if [ "$zero_cmd" == "fcollapse" ]; then
echo " 14. data -> hole @ 0"
else
echo " 15. data -> hole @ 0"
fi
if [ "$remove_testfile" ]; then
rm -f $testfile
fi
$XFS_IO_PROG -f -c "truncate $_20k" \
-c "pwrite 0 $_20k" $sync_cmd \
-c "$zero_cmd 0 $_8k" \
-c "$map_cmd -v" $testfile | $filter_cmd
[ $? -ne 0 ] && die_now
_md5_checksum $testfile
# If zero_cmd is fcollpase, don't check unaligned offsets
if [ "$zero_cmd" == "fcollapse" ]; then
return
fi
# If zero_cmd is finsert, don't check unaligned offsets
if [ "$zero_cmd" == "finsert" ]; then
return
fi
echo " 16. data -> cache cold ->hole"
if [ "$remove_testfile" ]; then
rm -f $testfile
rm -f $testfile.2
else
cp $testfile $testfile.2
fi
$XFS_IO_PROG -f -c "truncate $_20k" \
-c "pwrite $_8k $_12k" -c "fsync" $testfile.2 \
> /dev/null
$XFS_IO_PROG -f -c "truncate $_20k" \
-c "pwrite 0 $_20k" $sync_cmd \
-c "$zero_cmd 0k $_8k" \
-c "fadvise -d" \
-c "$map_cmd -v" $testfile | $filter_cmd
diff $testfile $testfile.2
[ $? -ne 0 ] && die_now
rm -f $testfile.2
_md5_checksum $testfile
# different file sizes mean we can't use md5sum to check the hole is
# valid. Hence use hexdump to dump the contents and chop off the last
# line of output that indicates the file size. We also have to fudge
# the extent size as that will change with file size, too - that's what
# the sed line noise does - it will always result in an output of [0..7]
# so it matches 4k block size...
echo " 17. data -> hole in single block file"
if [ "$remove_testfile" ]; then
rm -f $testfile
fi
block_size=`get_block_size $TEST_DIR`
$XFS_IO_PROG -f -c "truncate $block_size" \
-c "pwrite 0 $block_size" $sync_cmd \
-c "$zero_cmd 128 128" \
-c "$map_cmd -v" $testfile | $filter_cmd | \
sed -e "s/\.\.[0-9]*\]/..7\]/"
[ $? -ne 0 ] && die_now
od -x $testfile | head -n -1
}
_test_block_boundaries()
{
remove_testfile=1
sync_cmd="-c fsync"
unwritten_tests=1
OPTIND=1
while getopts 'dk' OPTION
do
case $OPTION in
k) remove_testfile=
;;
d) sync_cmd=
;;
?) echo Invalid flag
exit 1
;;
esac
done
shift $(($OPTIND - 1))
bs=$1
zero_cmd=$2
filter_cmd=$3
testfile=$4
# Block size plus 1
bs_p1=$(($bs + 1))
# Block size plus 2
bs_p2=$(($bs + 2))
# Block size minus 1
bs_m1=$(($bs - 1))
# Block size multiplied by 2
bs_t2=$(($bs * 2))
# Block size divided by 2
bs_d2=$(($bs / 2))
echo "zero 0, 1"
$XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
-c "pwrite -S 0x42 $bs $bs" \
-c "$zero_cmd 0 1" \
-c "pread -v 0 $bs_t2" \
$testfile | $filter_cmd
echo "zero 0, $bs_m1"
$XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
-c "pwrite -S 0x42 $bs $bs" \
-c "$zero_cmd 0 $bs_m1" \
-c "pread -v 0 $bs_t2" \
$testfile | $filter_cmd
echo "zero 0, $bs"
$XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
-c "pwrite -S 0x42 $bs $bs" \
-c "$zero_cmd 0 $bs" \
-c "pread -v 0 $bs_t2" \
$testfile | $filter_cmd
echo "zero 0, $bs_p1"
$XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
-c "pwrite -S 0x42 $bs $bs" \
-c "$zero_cmd 0 $bs_p1" \
-c "pread -v 0 $bs_t2" \
$testfile | $filter_cmd
echo "zero $bs_m1, $bs"
$XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
-c "pwrite -S 0x42 $bs $bs" \
-c "$zero_cmd $bs_m1 $bs" \
-c "pread -v 0 $bs_t2" \
$testfile | $filter_cmd
echo "zero $bs_m1, $bs_p1"
$XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
-c "pwrite -S 0x42 $bs $bs" \
-c "$zero_cmd $bs_m1 $bs_p1" \
-c "pread -v 0 $bs_t2" \
$testfile | $filter_cmd
echo "zero $bs_m1, $bs_p2"
$XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
-c "pwrite -S 0x42 $bs $bs" \
-c "$zero_cmd $bs_m1 $bs_p2" \
-c "pread -v 0 $bs_t2" \
$testfile | $filter_cmd
echo "zero $bs, $bs"
$XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
-c "pwrite -S 0x42 $bs $bs" \
-c "$zero_cmd $bs $bs" \
-c "pread -v 0 $bs_t2" \
$testfile | $filter_cmd
echo "zero $bs_d2 , $bs"
$XFS_IO_PROG -f -t -c "pwrite -S 0x41 0 $bs" \
-c "pwrite -S 0x42 $bs $bs" \
-c "$zero_cmd $bs_d2 $bs" \
-c "pread -v 0 $bs_t2" \
$testfile | $filter_cmd
}