fstest: CrashMonkey 'hard link' tests ported to xfstest
authorJayashree <jaya@cs.utexas.edu>
Tue, 20 Nov 2018 23:51:04 +0000 (17:51 -0600)
committerEryu Guan <guaneryu@gmail.com>
Fri, 30 Nov 2018 08:57:14 +0000 (16:57 +0800)
This patch aims to add more tests to the xfstest suite to check
whether the target file system recovers correctly after a crash.
These test cases are generated by CrashMonkey, a
crash-consistency testing framework built at the SASLab at UT Austin.

This patch batches 37 crash-consistency tests into a xfstest test,
each of which checks the hard link behavior under different scenarios.
This test creates hard-links between files in the same directory or
across directories, while allowing fsync of either the files involved,
their parent directories, or unrelated sibling files. After each sub
test, the metadata of the persisted file is checked for the correct
link count. Additionally, each sub test is followed by fsck to check
for inconsistencies. The tests run on a 256MB file system, and
the working directory is cleaned up after every sub test.

Signed-off-by: Jayashree Mohan <jaya@cs.utexas.edu>
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Eryu Guan <guaneryu@gmail.com>
tests/generic/520 [new file with mode: 0755]
tests/generic/520.out [new file with mode: 0644]
tests/generic/group

diff --git a/tests/generic/520 b/tests/generic/520
new file mode 100755 (executable)
index 0000000..4058262
--- /dev/null
@@ -0,0 +1,184 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2018 The University of Texas at Austin.  All Rights Reserved.
+#
+# FS QA Test 520
+#
+# Test case created by CrashMonkey
+#
+# Test if we create a hard link to a file and persist either of the files, all
+# the names persist.
+#
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+       _cleanup_flakey
+       cd /
+       rm -f $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/dmflakey
+
+# 256MB in byte
+fssize=$((2**20 * 256))
+
+# remove previous $seqres.full before test
+rm -f $seqres.full
+
+# real QA test starts here
+_supported_fs generic
+_supported_os Linux
+_require_scratch_nocheck
+_require_dm_target flakey
+
+# initialize scratch device
+_scratch_mkfs_sized $fssize >> $seqres.full 2>&1
+_require_metadata_journaling $SCRATCH_DEV
+_init_flakey
+
+stat_opt='-c "blocks: %b size: %s inode: %i links: %h"'
+before=""
+after=""
+
+
+# Using _scratch_mkfs instead of cleaning up the  working directory,
+# adds about 10 seconds of delay in total for the 37 tests.
+clean_dir()
+{
+       _mount_flakey
+       rm -rf $SCRATCH_MNT/*
+       sync
+       _unmount_flakey
+}
+
+check_consistency()
+{
+       _flakey_drop_and_remount
+
+       if [ -f $1 ]; then
+               after=`stat "$stat_opt" $1`
+       fi
+
+       if [ "$before" != "$after" ] && [ $2 -ne 1 ]; then
+               echo "Before: $before"
+               echo "After: $after"
+       fi
+
+       _unmount_flakey
+       _check_scratch_fs $FLAKEY_DEV
+}
+
+# create a hard link $2 to file $1, and fsync $3, followed by power-cut
+test_link_fsync()
+{
+       local sibling=0
+       local src=$SCRATCH_MNT/$1
+       local dest=$SCRATCH_MNT/$2
+       before=""
+       after=""
+
+       if [ "$3" == "./" ]; then
+               fsync=$SCRATCH_MNT
+       else
+               fsync=$SCRATCH_MNT/$3
+       fi
+
+       echo -ne "\n=== link $src $dest  with fsync $fsync ===\n" | \
+               _filter_scratch
+       _mount_flakey
+
+       # Now execute the workload
+       # Create the directory in which the source and destination files
+       # will be created
+       mkdir -p "${src%/*}"
+       mkdir -p "${dest%/*}"
+       touch $src
+       ln $src $dest
+
+       # If the file being persisted is a sibling, create it first
+       if [ ! -f $fsync ]; then
+               sibling=1
+               touch $fsync
+       fi
+
+       $XFS_IO_PROG -c "fsync" $fsync
+
+       if [ $sibling -ne 1 ]; then
+               before=`stat "$stat_opt" $src`
+       fi
+
+       check_consistency $src $sibling
+       clean_dir
+}
+
+# create a hard link $2 to file $1, and sync, followed by power-cut
+test_link_sync()
+{
+       local src=$SCRATCH_MNT/$1
+       local dest=$SCRATCH_MNT/$2
+       before=""
+       after=""
+       echo -ne "\n=== link $src $dest  with sync ===\n" | _filter_scratch
+       _mount_flakey
+
+       # now execute the workload
+       # Create the directory in which the source and destination files
+       # will be created
+       mkdir -p "${src%/*}"
+       mkdir -p "${dest%/*}"
+       touch $src
+       ln $src $dest
+       sync
+       before=`stat "$stat_opt" $src`
+
+       check_consistency $src 0
+       clean_dir
+}
+
+
+# Create different combinations to run the link test
+# Group 0: Both files within root directory
+file_names[0]="foo bar"
+fsync_names[0]="./ foo bar"
+
+# Group 1: Create hard link in a sub directory
+file_names[1]="foo A/bar"
+fsync_names[1]="./ foo bar A A/bar A/foo"
+
+# Group 2: Create hard link in parent directory
+file_names[2]="A/foo bar"
+fsync_names[2]="./ foo bar A A/bar A/foo"
+
+# Group 3: Both files within a directory other than root
+file_names[3]="A/foo A/bar"
+fsync_names[3]="./ A A/bar A/foo"
+
+#Group 4: Exercise name reuse : Link file in sub-directory
+file_names[4]="bar A/bar"
+fsync_names[4]="./ foo bar A A/bar A/foo"
+
+#Group 5: Exercise name reuse : Link file in parent directory
+file_names[5]="A/bar bar"
+fsync_names[5]="./ foo bar A A/bar A/foo"
+
+for ((test_group = 0; test_group < 6; test_group++)); do
+       for file in ${fsync_names[$test_group]}; do
+               test_link_fsync ${file_names[$test_group]} $file
+       done
+       test_link_sync ${file_names[$test_group]}
+done
+
+# success, all done
+status=0
+exit
diff --git a/tests/generic/520.out b/tests/generic/520.out
new file mode 100644 (file)
index 0000000..ed82e80
--- /dev/null
@@ -0,0 +1,75 @@
+QA output created by 520
+
+=== link SCRATCH_MNT/foo SCRATCH_MNT/bar  with fsync SCRATCH_MNT ===
+
+=== link SCRATCH_MNT/foo SCRATCH_MNT/bar  with fsync SCRATCH_MNT/foo ===
+
+=== link SCRATCH_MNT/foo SCRATCH_MNT/bar  with fsync SCRATCH_MNT/bar ===
+
+=== link SCRATCH_MNT/foo SCRATCH_MNT/bar  with sync ===
+
+=== link SCRATCH_MNT/foo SCRATCH_MNT/A/bar  with fsync SCRATCH_MNT ===
+
+=== link SCRATCH_MNT/foo SCRATCH_MNT/A/bar  with fsync SCRATCH_MNT/foo ===
+
+=== link SCRATCH_MNT/foo SCRATCH_MNT/A/bar  with fsync SCRATCH_MNT/bar ===
+
+=== link SCRATCH_MNT/foo SCRATCH_MNT/A/bar  with fsync SCRATCH_MNT/A ===
+
+=== link SCRATCH_MNT/foo SCRATCH_MNT/A/bar  with fsync SCRATCH_MNT/A/bar ===
+
+=== link SCRATCH_MNT/foo SCRATCH_MNT/A/bar  with fsync SCRATCH_MNT/A/foo ===
+
+=== link SCRATCH_MNT/foo SCRATCH_MNT/A/bar  with sync ===
+
+=== link SCRATCH_MNT/A/foo SCRATCH_MNT/bar  with fsync SCRATCH_MNT ===
+
+=== link SCRATCH_MNT/A/foo SCRATCH_MNT/bar  with fsync SCRATCH_MNT/foo ===
+
+=== link SCRATCH_MNT/A/foo SCRATCH_MNT/bar  with fsync SCRATCH_MNT/bar ===
+
+=== link SCRATCH_MNT/A/foo SCRATCH_MNT/bar  with fsync SCRATCH_MNT/A ===
+
+=== link SCRATCH_MNT/A/foo SCRATCH_MNT/bar  with fsync SCRATCH_MNT/A/bar ===
+
+=== link SCRATCH_MNT/A/foo SCRATCH_MNT/bar  with fsync SCRATCH_MNT/A/foo ===
+
+=== link SCRATCH_MNT/A/foo SCRATCH_MNT/bar  with sync ===
+
+=== link SCRATCH_MNT/A/foo SCRATCH_MNT/A/bar  with fsync SCRATCH_MNT ===
+
+=== link SCRATCH_MNT/A/foo SCRATCH_MNT/A/bar  with fsync SCRATCH_MNT/A ===
+
+=== link SCRATCH_MNT/A/foo SCRATCH_MNT/A/bar  with fsync SCRATCH_MNT/A/bar ===
+
+=== link SCRATCH_MNT/A/foo SCRATCH_MNT/A/bar  with fsync SCRATCH_MNT/A/foo ===
+
+=== link SCRATCH_MNT/A/foo SCRATCH_MNT/A/bar  with sync ===
+
+=== link SCRATCH_MNT/bar SCRATCH_MNT/A/bar  with fsync SCRATCH_MNT ===
+
+=== link SCRATCH_MNT/bar SCRATCH_MNT/A/bar  with fsync SCRATCH_MNT/foo ===
+
+=== link SCRATCH_MNT/bar SCRATCH_MNT/A/bar  with fsync SCRATCH_MNT/bar ===
+
+=== link SCRATCH_MNT/bar SCRATCH_MNT/A/bar  with fsync SCRATCH_MNT/A ===
+
+=== link SCRATCH_MNT/bar SCRATCH_MNT/A/bar  with fsync SCRATCH_MNT/A/bar ===
+
+=== link SCRATCH_MNT/bar SCRATCH_MNT/A/bar  with fsync SCRATCH_MNT/A/foo ===
+
+=== link SCRATCH_MNT/bar SCRATCH_MNT/A/bar  with sync ===
+
+=== link SCRATCH_MNT/A/bar SCRATCH_MNT/bar  with fsync SCRATCH_MNT ===
+
+=== link SCRATCH_MNT/A/bar SCRATCH_MNT/bar  with fsync SCRATCH_MNT/foo ===
+
+=== link SCRATCH_MNT/A/bar SCRATCH_MNT/bar  with fsync SCRATCH_MNT/bar ===
+
+=== link SCRATCH_MNT/A/bar SCRATCH_MNT/bar  with fsync SCRATCH_MNT/A ===
+
+=== link SCRATCH_MNT/A/bar SCRATCH_MNT/bar  with fsync SCRATCH_MNT/A/bar ===
+
+=== link SCRATCH_MNT/A/bar SCRATCH_MNT/bar  with fsync SCRATCH_MNT/A/foo ===
+
+=== link SCRATCH_MNT/A/bar SCRATCH_MNT/bar  with sync ===
index 92330b52edddd0750e6db53628bca8084b1d6e46..eb5e4ce91575edb90015a931f46b4cd90efe9cfe 100644 (file)
 517 auto quick dedupe clone
 518 auto quick clone
 519 auto quick
 517 auto quick dedupe clone
 518 auto quick clone
 519 auto quick
+520 auto quick log