blob: 72eb6fa775acefc823a51e7e954d31e8120a2e35 [file] [log] [blame]
#! /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
#
. ./common/preamble
_begin_fstest metadata auto quick log
# Override the default cleanup function.
_cleanup()
{
_cleanup_flakey
}
# Import common functions.
. ./common/filter
. ./common/dmflakey
# real QA test starts here
_supported_fs generic
_require_scratch
_require_hardlinks
_require_dm_target flakey
_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