fstests: add _require_hardlinks for all necessary tests
[xfstests-dev.git] / tests / generic / 065
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (C) 2015 SUSE Linux Products GmbH. All Rights Reserved.
4 #
5 # FS QA Test No. 065
6 #
7 # Test fsync on directories that got new hardlinks added to them and that point
8 # to existing inodes. The goal is to verify that after the fsync log is replayed
9 # the new hardlinks exist and the inodes have a correct link count.
10 # Also test that new hardlinks pointing to new inodes are logged and exist as
11 # well after the fsync log is replayed.
12 #
13 # This test is motivated by an issue discovered in btrfs, where the inode link
14 # counts were incorrect after the fsync log was replayed and the hardlinks for
15 # new inodes were not logged.
16 #
17 seq=`basename $0`
18 seqres=$RESULT_DIR/$seq
19 echo "QA output created by $seq"
20
21 here=`pwd`
22 tmp=/tmp/$$
23 status=1        # failure is the default!
24
25 _cleanup()
26 {
27         _cleanup_flakey
28         rm -f $tmp.*
29 }
30 trap "_cleanup; exit \$status" 0 1 2 3 15
31
32 # get standard environment, filters and checks
33 . ./common/rc
34 . ./common/filter
35 . ./common/dmflakey
36
37 # real QA test starts here
38 _supported_fs generic
39 _supported_os Linux
40 _require_scratch
41 _require_hardlinks
42 _require_dm_target flakey
43
44 rm -f $seqres.full
45
46 _scratch_mkfs >> $seqres.full 2>&1
47 _require_metadata_journaling $SCRATCH_DEV
48 _init_flakey
49 _mount_flakey
50
51 # Create our main test file and directory.
52 $XFS_IO_PROG -f -c "pwrite -S 0xaa 0 8K" $SCRATCH_MNT/foo | _filter_xfs_io
53 mkdir $SCRATCH_MNT/mydir
54
55 # Make sure all metadata and data are durably persisted.
56 sync
57
58 # Add a hard link to 'foo' inside our test directory and fsync only the
59 # directory. The btrfs fsync implementation had a bug that caused the new
60 # directory entry to be visible after the fsync log replay but, the inode
61 # of our file remained with a link count of 1.
62 ln $SCRATCH_MNT/foo $SCRATCH_MNT/mydir/foo_2
63
64 # Add a few more links and new files.
65 # This is just to verify nothing breaks or gives incorrect results after the
66 # fsync log is replayed.
67 ln $SCRATCH_MNT/foo $SCRATCH_MNT/mydir/foo_3
68 $XFS_IO_PROG -f -c "pwrite -S 0xff 0 64K" $SCRATCH_MNT/hello | _filter_xfs_io
69 ln $SCRATCH_MNT/hello $SCRATCH_MNT/mydir/hello_2
70
71 # Add some subdirectories and new files and links to them. This is to verify
72 # that after fsyncing our top level directory 'mydir', all the subdirectories
73 # and their files/links are registered in the fsync log and exist after the
74 # fsync log is replayed.
75 mkdir -p $SCRATCH_MNT/mydir/x/y/z
76 ln $SCRATCH_MNT/foo $SCRATCH_MNT/mydir/x/y/foo_y_link
77 ln $SCRATCH_MNT/foo $SCRATCH_MNT/mydir/x/y/z/foo_z_link
78 touch $SCRATCH_MNT/mydir/x/y/z/qwerty
79
80 # Now fsync only our top directory.
81 $XFS_IO_PROG -c "fsync" $SCRATCH_MNT/mydir
82
83 # And fsync now our new file named 'hello', just to verify later that it has
84 # the expected content and that the previous fsync on the directory 'mydir' had
85 # no bad influence on this fsync.
86 $XFS_IO_PROG -c "fsync" $SCRATCH_MNT/hello
87
88 _flakey_drop_and_remount
89
90 # Verify the content of our file 'foo' remains the same as before, 8192 bytes,
91 # all with the value 0xaa.
92 echo "File 'foo' content after log replay:"
93 od -t x1 $SCRATCH_MNT/foo
94
95 # Remove the first name of our inode. Because of the directory fsync bug, the
96 # inode's link count was 1 instead of 5, so removing the 'foo' name ended up
97 # deleting the inode and the other names became stale directory entries (still
98 # visible to applications). Attempting to remove or access the remaining
99 # dentries pointing to that inode resulted in stale file handle errors and
100 # made it impossible to remove the parent directories since it was impossible
101 # for them to become empty.
102 echo "file 'foo' link count after log replay: $(stat -c %h $SCRATCH_MNT/foo)"
103 rm -f $SCRATCH_MNT/foo
104
105 # Now verify that all files, links and directories created before fsyncing our
106 # directory exist after the fsync log was replayed.
107 [ -f $SCRATCH_MNT/mydir/foo_2 ] || echo "Link mydir/foo_2 is missing"
108 [ -f $SCRATCH_MNT/mydir/foo_3 ] || echo "Link mydir/foo_3 is missing"
109 [ -f $SCRATCH_MNT/hello ] || echo "File hello is missing"
110 [ -f $SCRATCH_MNT/mydir/hello_2 ] || echo "Link mydir/hello_2 is missing"
111 [ -f $SCRATCH_MNT/mydir/x/y/foo_y_link ] || \
112         echo "Link mydir/x/y/foo_y_link is missing"
113 [ -f $SCRATCH_MNT/mydir/x/y/z/foo_z_link ] || \
114         echo "Link mydir/x/y/z/foo_z_link is missing"
115 [ -f $SCRATCH_MNT/mydir/x/y/z/qwerty ] || \
116         echo "File mydir/x/y/z/qwerty is missing"
117
118 # We expect our file here to have a size of 64Kb and all the bytes having the
119 # value 0xff.
120 echo "file 'hello' content after log replay:"
121 od -t x1 $SCRATCH_MNT/hello
122
123 # Now remove all files/links, under our test directory 'mydir', and verify we
124 # can remove all the directories.
125 rm -f $SCRATCH_MNT/mydir/x/y/z/*
126 rmdir $SCRATCH_MNT/mydir/x/y/z
127 rm -f $SCRATCH_MNT/mydir/x/y/*
128 rmdir $SCRATCH_MNT/mydir/x/y
129 rmdir $SCRATCH_MNT/mydir/x
130 rm -f $SCRATCH_MNT/mydir/*
131 rmdir $SCRATCH_MNT/mydir
132
133 # An fsck, run by the fstests framework everytime a test finishes, also detected
134 # the inconsistency and printed the following error message:
135 #
136 # root 5 inode 257 errors 2001, no inode item, link count wrong
137 #    unresolved ref dir 258 index 2 namelen 5 name foo_2 filetype 1 errors 4, no inode ref
138 #    unresolved ref dir 258 index 3 namelen 5 name foo_3 filetype 1 errors 4, no inode ref
139
140 status=0
141 exit