summaryrefslogtreecommitdiff
path: root/common/punch
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2013-03-15 12:28:04 +0000
committerRich Johnston <rjohnston@sgi.com>2013-03-26 21:44:05 -0500
commit8c4905a42e10650a75c0e3966ecc044e1a9616d0 (patch)
tree1830ea2b6307fcd138dcc58ec2605c27b0a25004 /common/punch
parent401680a11c4fb08d749d1d75598c7705273e5860 (diff)
xfstests: introduce a common directory
Introduce a top level common directory and move all the common.* files into it. Because there is now a directory named common, the prefix can be dropped from all the files. Convert all the tests to use this new directory for including common files. for f in common.*; do \ git mv `echo -n "$f " ; echo $f | sed -e 's;n\.;n/;'` \ done Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Phil White <pwhite@sgi.com> [rjohnston@sgi.com reworked for TOT changes] Signed-off-by: Rich Johnston <rjohnston@sgi.com>
Diffstat (limited to 'common/punch')
-rw-r--r--common/punch525
1 files changed, 525 insertions, 0 deletions
diff --git a/common/punch b/common/punch
new file mode 100644
index 00000000..cfbe5769
--- /dev/null
+++ b/common/punch
@@ -0,0 +1,525 @@
+##/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 /
+ umount $SCRATCH_MNT >/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 --posix '
+ $3 ~ /hole/ {
+ print $1, $2, $3;
+ next;
+ }
+ $5 ~ /0x[[:xdigit:]]*8[[:xdigit:]]{2}/ {
+ print $1, $2, "unwritten";
+ next;
+ }
+ $5 ~ /0x[[:xdigit:]]+/ {
+ print $1, $2, "data";
+ }' |
+ _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 '
+ $3 ~ /hole/ {
+ print $1, $2, $3;
+ next;
+ }
+ $5 ~ /0x[[:xdigit:]]+/ {
+ print $1, $2, "extent";
+ }' |
+ _coalesce_extents
+}
+
+
+# Prints the md5 checksum of a given file
+_md5_checksum()
+{
+ md5sum $1 | cut -d ' ' -f1
+}
+
+_filter_bmap()
+{
+ awk '
+ $3 ~ /hole/ {
+ print $1, $2, $3;
+ next;
+ }
+ $7 ~ /10000/ {
+ print $1, $2, "unwritten";
+ next;
+ }
+ $7 ~ /00000/ {
+ 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
+#
+_test_generic_punch()
+{
+
+ remove_testfile=1
+ sync_cmd="-c fsync"
+ 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))
+
+ 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
+ xfs_io_opt=$7 #needs to be -F if not testing xfs
+
+ echo " 1. into a hole"
+ if [ "$remove_testfile" ]; then
+ rm -f $testfile
+ fi
+ $XFS_IO_PROG $xfs_io_opt -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 $xfs_io_opt -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
+
+ echo " 3. into unwritten space"
+ if [ "$remove_testfile" ]; then
+ rm -f $testfile
+ fi
+ $XFS_IO_PROG $xfs_io_opt -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
+
+ echo " 4. hole -> data"
+ if [ "$remove_testfile" ]; then
+ rm -f $testfile
+ fi
+ $XFS_IO_PROG $xfs_io_opt -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
+
+ echo " 5. hole -> unwritten"
+ if [ "$remove_testfile" ]; then
+ rm -f $testfile
+ fi
+ $XFS_IO_PROG $xfs_io_opt -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
+
+ echo " 6. data -> hole"
+ if [ "$remove_testfile" ]; then
+ rm -f $testfile
+ fi
+ $XFS_IO_PROG $xfs_io_opt -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
+
+ echo " 7. data -> unwritten"
+ if [ "$remove_testfile" ]; then
+ rm -f $testfile
+ fi
+ $XFS_IO_PROG $xfs_io_opt -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 $xfs_io_opt -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 $xfs_io_opt -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
+
+ echo " 10. hole -> data -> hole"
+ if [ "$remove_testfile" ]; then
+ rm -f $testfile
+ fi
+ $XFS_IO_PROG $xfs_io_opt -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 $xfs_io_opt -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
+
+ echo " 12. unwritten -> data -> unwritten"
+ if [ "$remove_testfile" ]; then
+ rm -f $testfile
+ fi
+ $XFS_IO_PROG $xfs_io_opt -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 $xfs_io_opt -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" \
+ -c "$map_cmd -v" $testfile | $filter_cmd
+ [ $? -ne 0 ] && die_now
+ _md5_checksum $testfile
+
+ echo " 14. data -> hole @ EOF"
+ rm -f $testfile
+ $XFS_IO_PROG $xfs_io_opt -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
+
+ echo " 15. data -> hole @ 0"
+ if [ "$remove_testfile" ]; then
+ rm -f $testfile
+ fi
+ $XFS_IO_PROG $xfs_io_opt -f -c "truncate 20k" \
+ -c "pwrite 0 20k" $sync_cmd \
+ -c "$zero_cmd 0k 8k" \
+ -c "$map_cmd -v" $testfile | $filter_cmd
+ [ $? -ne 0 ] && die_now
+ _md5_checksum $testfile
+
+ 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 $xfs_io_opt -f -c "truncate 20k" \
+ -c "pwrite 8k 12k" -c "fsync" $testfile.2 \
+ > /dev/null
+ $XFS_IO_PROG $xfs_io_opt -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
+
+ 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`
+ $XFS_IO_PROG $xfs_io_opt -f -c "truncate $block_size" \
+ -c "pwrite 0 $block_size" $sync_cmd \
+ -c "$zero_cmd 128 128" \
+ -c "$map_cmd -v" $testfile | $filter_cmd
+ [ $? -ne 0 ] && die_now
+ _md5_checksum $testfile
+
+}