21c04d25fdbe895a69675ef6b6733761fdb6efd4
[xfstests-dev.git] / tests / generic / 039
1 #! /bin/bash
2 # FS QA Test No. 039
3 #
4 # This test is motivated by an fsync issue discovered in btrfs.
5 # The issue was that after fsyncing an inode that got its link count
6 # decremented, and the new link count is greater than zero, after the
7 # fsync log replay the inode's parent directory metadata became
8 # inconsistent - it had a wrong i_size and dangling index entries which
9 # prevented the directory from ever being removed (rmdir always failed
10 # with -ENOTEMPTY, even if the directory had no more child inodes).
11 #
12 # The btrfs issue was fixed by the following linux kernel patch:
13 #
14 #    Btrfs: fix directory inconsistency after fsync log replay
15 #
16 #-----------------------------------------------------------------------
17 # Copyright (C) 2015 SUSE Linux Products GmbH. All Rights Reserved.
18 # Author: Filipe Manana <fdmanana@suse.com>
19 #
20 # This program is free software; you can redistribute it and/or
21 # modify it under the terms of the GNU General Public License as
22 # published by the Free Software Foundation.
23 #
24 # This program is distributed in the hope that it would be useful,
25 # but WITHOUT ANY WARRANTY; without even the implied warranty of
26 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27 # GNU General Public License for more details.
28 #
29 # You should have received a copy of the GNU General Public License
30 # along with this program; if not, write the Free Software Foundation,
31 # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
32 #-----------------------------------------------------------------------
33 #
34
35 seq=`basename $0`
36 seqres=$RESULT_DIR/$seq
37 echo "QA output created by $seq"
38
39 here=`pwd`
40 tmp=/tmp/$$
41 status=1        # failure is the default!
42
43 _cleanup()
44 {
45         _cleanup_flakey
46 }
47 trap "_cleanup; exit \$status" 0 1 2 3 15
48
49 # get standard environment, filters and checks
50 . ./common/rc
51 . ./common/filter
52 . ./common/dmflakey
53
54 # real QA test starts here
55 _supported_fs generic
56 _supported_os Linux
57 _need_to_be_root
58 _require_scratch
59 _require_dm_target flakey
60 _require_metadata_journaling $SCRATCH_DEV
61
62 rm -f $seqres.full
63
64 _scratch_mkfs >> $seqres.full 2>&1
65
66 _init_flakey
67 _mount_flakey
68
69 # Create a test file with 2 hard links in the same directory.
70 mkdir -p $SCRATCH_MNT/a/b
71 echo "hello world" > $SCRATCH_MNT/a/b/foo
72 ln $SCRATCH_MNT/a/b/foo $SCRATCH_MNT/a/b/bar
73
74 # Make sure all metadata and data are durably persisted.
75 sync
76
77 # Now remove one of the hard links and fsync the inode.
78 rm -f $SCRATCH_MNT/a/b/bar
79 $XFS_IO_PROG -c "fsync" $SCRATCH_MNT/a/b/foo
80
81 _flakey_drop_and_remount
82
83 # Remove the last hard link of the file and attempt to remove its parent
84 # directory - this failed in btrfs because the fsync log and replay code
85 # didn't decrement the parent directory's i_size and left dangling directory
86 # index entries - this made the btrfs rmdir implementation always fail with
87 # the error -ENOTEMPTY.
88 #
89 # The dangling directory index entries were visible to user space, but it was
90 # impossible to do anything on them (unlink, open, read, write, stat, etc)
91 # because the inode they pointed to did not exist anymore.
92 #
93 # The parent directory's metadata inconsistency (stale index entries) was
94 # also detected by btrfs' fsck tool, which is run automatically by the fstests
95 # framework when the test finishes. The error message reported by fsck was:
96 #
97 # root 5 inode 259 errors 2001, no inode item, link count wrong
98 #   unresolved ref dir 258 index 3 namelen 3 name bar filetype 1 errors 4, no inode ref
99 #
100 rm -f $SCRATCH_MNT/a/b/*
101 rmdir $SCRATCH_MNT/a/b
102 rmdir $SCRATCH_MNT/a
103
104 echo "Silence is golden"
105 status=0
106 exit