common/fuzzy: if the fuzz verb is random, keep fuzzing until we get a new value
[xfstests-dev.git] / common / punch
index 7b3c00991989f5d136456632f84af2a605c35604..c4ed26192a2219e232202ecda9486e55a432f90d 100644 (file)
@@ -115,7 +115,7 @@ _test_punch() {
        local filename=punch_test_file
 
        cd /
-       umount $SCRATCH_MNT >/dev/null 2>&1
+       _scratch_unmount >/dev/null 2>&1
 
        _scratch_mkfs_xfs -bsize=$blksize >/dev/null 2>&1 \
                || _fail "mkfs failed"
@@ -203,12 +203,12 @@ _coalesce_extents()
 
 _filter_fiemap()
 {
-       awk --posix '
+       $AWK_PROG '
                $3 ~ /hole/ {
                        print $1, $2, $3;
                        next;
                }
-               $5 ~ /0x[[:xdigit:]]*8[[:xdigit:]]{2}/ {
+               $5 ~ /0x[[:xdigit:]]*8[[:xdigit:]][[:xdigit:]]/ {
                        print $1, $2, "unwritten";
                        next;
                }
@@ -218,12 +218,29 @@ _filter_fiemap()
        _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 --posix '
+       $AWK_PROG '
                $3 ~ /hole/ {
                        print $1, $2, $3; 
                        next;
@@ -234,6 +251,11 @@ _filter_hole_fiemap()
        _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 '
@@ -241,11 +263,11 @@ _filter_bmap()
                        print $1, $2, $3;
                        next;
                }
-               $7 ~ /10000/ {
+               $7 ~ /1[01][01][01][01]/ {
                        print $1, $2, "unwritten";
                        next;
                }
-               $7 ~ /00000/ {
+               $7 ~ /0[01][01][01][01]/ {
                        print $1, $2, "data"
                }' |
        _coalesce_extents
@@ -317,13 +339,29 @@ _test_generic_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"
-       if [ "$remove_testfile" ]; then
-               rm -f $testfile
-       fi
-       $XFS_IO_PROG -f -c "truncate 20k" \
-               -c "$zero_cmd 4k 8k" \
+       $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
@@ -332,9 +370,9 @@ _test_generic_punch()
        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" \
+       $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
@@ -344,9 +382,9 @@ _test_generic_punch()
                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" \
+               $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
@@ -356,9 +394,9 @@ _test_generic_punch()
        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" \
+       $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
@@ -368,9 +406,9 @@ _test_generic_punch()
                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" \
+               $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
@@ -380,9 +418,9 @@ _test_generic_punch()
        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" \
+       $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
@@ -392,10 +430,10 @@ _test_generic_punch()
                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" \
+               $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
@@ -404,9 +442,9 @@ _test_generic_punch()
                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" \
+               $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
@@ -415,10 +453,10 @@ _test_generic_punch()
                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" \
+               $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
@@ -428,9 +466,9 @@ _test_generic_punch()
        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" \
+       $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
@@ -439,12 +477,12 @@ _test_generic_punch()
        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" \
+       $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
@@ -454,10 +492,10 @@ _test_generic_punch()
                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" \
+               $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
@@ -466,36 +504,56 @@ _test_generic_punch()
                if [ "$remove_testfile" ]; then
                        rm -f $testfile
                fi
-               $XFS_IO_PROG -f -c "truncate 20k" \
-                       -c "$alloc_cmd 0 20k" \
-                       -c "pwrite 0k 8k" $sync_cmd \
-                       -c "pwrite 12k 8k" -c "fsync" \
-                       -c "$zero_cmd 4k 12k" \
+               $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
 
-       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
+       # 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
 
-       echo "  15. data -> hole @ 0"
        if [ "$remove_testfile" ]; then
                rm -f $testfile
        fi
-       $XFS_IO_PROG -f -c "truncate 20k" \
-               -c "pwrite 0 20k" $sync_cmd \
-               -c "$zero_cmd 08k" \
+       $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
@@ -503,12 +561,12 @@ _test_generic_punch()
        else
                cp $testfile $testfile.2
        fi
-       $XFS_IO_PROG -f -c "truncate 20k" \
-               -c "pwrite 8k 12k" -c "fsync" $testfile.2 \
+       $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" \
+       $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
@@ -516,16 +574,128 @@ _test_generic_punch()
        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=`stat -f $TEST_DEV | grep "Block size" | cut -d " " -f3`
+       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
+               -c "$map_cmd -v" $testfile | $filter_cmd | \
+                        sed -e "s/\.\.[0-9]*\]/..7\]/"
        [ $? -ne 0 ] && die_now
-       _md5_checksum $testfile
+       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
 }