#! /bin/bash # SPDX-License-Identifier: GPL-2.0 # Copyright (C) 2015 SUSE Linux Products GmbH. All Rights Reserved. # # FS QA Test No. 039 # # This test is motivated by an fsync issue discovered in btrfs. # The issue was that after fsyncing an inode that got its link count # decremented, and the new link count is greater than zero, after the # fsync log replay the inode's parent directory metadata became # inconsistent - it had a wrong i_size and dangling index entries which # prevented the directory from ever being removed (rmdir always failed # with -ENOTEMPTY, even if the directory had no more child inodes). # # The btrfs issue was fixed by the following linux kernel patch: # # Btrfs: fix directory inconsistency after fsync log replay # seq=`basename $0` seqres=$RESULT_DIR/$seq echo "QA output created by $seq" here=`pwd` tmp=/tmp/$$ status=1 # failure is the default! _cleanup() { _cleanup_flakey } trap "_cleanup; exit \$status" 0 1 2 3 15 # get standard environment, filters and checks . ./common/rc . ./common/filter . ./common/dmflakey # real QA test starts here _supported_fs generic _supported_os Linux _require_scratch _require_hardlinks _require_dm_target flakey rm -f $seqres.full _scratch_mkfs >> $seqres.full 2>&1 _require_metadata_journaling $SCRATCH_DEV _init_flakey _mount_flakey # Create a test file with 2 hard links in the same directory. mkdir -p $SCRATCH_MNT/a/b echo "hello world" > $SCRATCH_MNT/a/b/foo ln $SCRATCH_MNT/a/b/foo $SCRATCH_MNT/a/b/bar # Make sure all metadata and data are durably persisted. sync # Now remove one of the hard links and fsync the inode. rm -f $SCRATCH_MNT/a/b/bar $XFS_IO_PROG -c "fsync" $SCRATCH_MNT/a/b/foo _flakey_drop_and_remount # Remove the last hard link of the file and attempt to remove its parent # directory - this failed in btrfs because the fsync log and replay code # didn't decrement the parent directory's i_size and left dangling directory # index entries - this made the btrfs rmdir implementation always fail with # the error -ENOTEMPTY. # # The dangling directory index entries were visible to user space, but it was # impossible to do anything on them (unlink, open, read, write, stat, etc) # because the inode they pointed to did not exist anymore. # # The parent directory's metadata inconsistency (stale index entries) was # also detected by btrfs' fsck tool, which is run automatically by the fstests # framework when the test finishes. The error message reported by fsck was: # # root 5 inode 259 errors 2001, no inode item, link count wrong # unresolved ref dir 258 index 3 namelen 3 name bar filetype 1 errors 4, no inode ref # rm -f $SCRATCH_MNT/a/b/* rmdir $SCRATCH_MNT/a/b rmdir $SCRATCH_MNT/a echo "Silence is golden" status=0 exit