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).
12 # The btrfs issue was fixed by the following linux kernel patch:
14 # Btrfs: fix directory inconsistency after fsync log replay
16 #-----------------------------------------------------------------------
17 # Copyright (C) 2015 SUSE Linux Products GmbH. All Rights Reserved.
18 # Author: Filipe Manana <fdmanana@suse.com>
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.
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.
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 #-----------------------------------------------------------------------
36 seqres=$RESULT_DIR/$seq
37 echo "QA output created by $seq"
41 status=1 # failure is the default!
47 trap "_cleanup; exit \$status" 0 1 2 3 15
49 # get standard environment, filters and checks
54 # real QA test starts here
60 _require_metadata_journaling $SCRATCH_DEV
64 _scratch_mkfs >> $seqres.full 2>&1
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
74 # Make sure all metadata and data are durably persisted.
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
81 # Simulate a crash/power loss. This makes sure the next mount
82 # will see an fsync log and will replay that log.
84 _load_flakey_table $FLAKEY_DROP_WRITES
87 _load_flakey_table $FLAKEY_ALLOW_WRITES
90 # Remove the last hard link of the file and attempt to remove its parent
91 # directory - this failed in btrfs because the fsync log and replay code
92 # didn't decrement the parent directory's i_size and left dangling directory
93 # index entries - this made the btrfs rmdir implementation always fail with
94 # the error -ENOTEMPTY.
96 # The dangling directory index entries were visible to user space, but it was
97 # impossible to do anything on them (unlink, open, read, write, stat, etc)
98 # because the inode they pointed to did not exist anymore.
100 # The parent directory's metadata inconsistency (stale index entries) was
101 # also detected by btrfs' fsck tool, which is run automatically by the fstests
102 # framework when the test finishes. The error message reported by fsck was:
104 # root 5 inode 259 errors 2001, no inode item, link count wrong
105 # unresolved ref dir 258 index 3 namelen 3 name bar filetype 1 errors 4, no inode ref
107 rm -f $SCRATCH_MNT/a/b/*
108 rmdir $SCRATCH_MNT/a/b
111 echo "Silence is golden"