Message ID | 3f3d20ef0abcc05ebfb6bc4aaa97261598611e49.1652106518.git.fdmanana@suse.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v2] generic: test fsync of directory with renamed symlink | expand |
On Mon, May 09, 2022 at 03:31:02PM +0100, fdmanana@kernel.org wrote: > From: Filipe Manana <fdmanana@suse.com> > > Test that if we fsync a directory, create a symlink inside it, rename > the symlink, fsync again the directory and then power fail, after the > filesystem is mounted again, the symlink exists with the new name and > it has the correct content. > > This currently fails on btrfs, because the symlink ends up empty (which > is illegal on Linux), but it is fixed by kernel commit: > > d0e64a981fd841 ("btrfs: always log symlinks in full mode") > > Reviewed-by: David Disseldorp <ddiss@suse.de> > Signed-off-by: Filipe Manana <fdmanana@suse.com> > --- > > v2: Rebased on latest for-next, quoted $SCRATCH_MNT references (David Disseldorp) > and added David's review tag. This case is nearly copied from generic/066, so there's not debatable things from code format. It's in my local testing branch now, and will be pushed in next release, after regression test done. Thanks for this new test. Zorro > > tests/generic/690 | 90 +++++++++++++++++++++++++++++++++++++++++++ > tests/generic/690.out | 2 + > 2 files changed, 92 insertions(+) > create mode 100755 tests/generic/690 > create mode 100644 tests/generic/690.out > > diff --git a/tests/generic/690 b/tests/generic/690 > new file mode 100755 > index 00000000..f03295a5 > --- /dev/null > +++ b/tests/generic/690 > @@ -0,0 +1,90 @@ > +#! /bin/bash > +# SPDX-License-Identifier: GPL-2.0 > +# Copyright (c) 2022 SUSE Linux Products GmbH. All Rights Reserved. > +# > +# FS QA Test 690 > +# > +# Test that if we fsync a directory, create a symlink inside it, rename the > +# symlink, fsync again the directory and then power fail, after the filesystem > +# is mounted again, the symlink exists with the new name and it has the correct > +# content. > +# > +# On btrfs this used to result in the symlink being empty (i_size 0), and it was > +# fixed by kernel commit: > +# > +# d0e64a981fd841 ("btrfs: always log symlinks in full mode") > +# > +. ./common/preamble > +_begin_fstest auto quick log > + > +_cleanup() > +{ > + _cleanup_flakey > + cd / > + rm -r -f $tmp.* > +} > + > +. ./common/rc > +. ./common/filter > +. ./common/dmflakey > + > +# real QA test starts here > + > +_supported_fs generic > +_require_scratch > +_require_symlinks > +_require_dm_target flakey > + > +rm -f $seqres.full > + > +# f2fs doesn't support fs-op level transaction functionality, so it has no way > +# to persist all metadata updates in one transaction. We have to use its mount > +# option "fastboot" so that it triggers a metadata checkpoint to persist all > +# metadata updates that happen before a fsync call. Without this, after the > +# last fsync in the test, the symlink named "baz" will not exist. > +if [ $FSTYP = "f2fs" ]; then > + export MOUNT_OPTIONS="-o fastboot $MOUNT_OPTIONS" > +fi > + > +_scratch_mkfs >>$seqres.full 2>&1 > +_require_metadata_journaling $SCRATCH_DEV > +_init_flakey > +_mount_flakey > + > +# Create our test directory. > +mkdir "$SCRATCH_MNT"/testdir > + > +# Commit the current transaction and persist the directory. > +sync > + > +# Create a file in the test directory, so that the next fsync on the directory > +# actually does something (it logs the directory). > +echo -n > "$SCRATCH_MNT"/testdir/foo > + > +# Fsync the directory. > +$XFS_IO_PROG -c "fsync" "$SCRATCH_MNT"/testdir > + > +# Now create a symlink inside the test directory. > +ln -s "$SCRATCH_MNT"/testdir/foo "$SCRATCH_MNT"/testdir/bar > + > +# Rename the symlink. > +mv "$SCRATCH_MNT"/testdir/bar "$SCRATCH_MNT"/testdir/baz > + > +# Fsync again the directory. > +$XFS_IO_PROG -c "fsync" "$SCRATCH_MNT"/testdir > + > +# Simulate a power failure and then mount again the filesystem to replay the > +# journal/log. > +_flakey_drop_and_remount > + > +# The symlink should exist, with the name "baz" and its content must be > +# "$SCRATCH_MNT/testdir/foo". > +[ -L "$SCRATCH_MNT"/testdir/baz ] || echo "symlink 'baz' is missing" > +symlink_content=$(readlink "$SCRATCH_MNT"/testdir/baz | _filter_scratch) > +echo "symlink content: ${symlink_content}" > + > +_unmount_flakey > + > +# success, all done > +status=0 > +exit > diff --git a/tests/generic/690.out b/tests/generic/690.out > new file mode 100644 > index 00000000..84be1247 > --- /dev/null > +++ b/tests/generic/690.out > @@ -0,0 +1,2 @@ > +QA output created by 690 > +symlink content: SCRATCH_MNT/testdir/foo > -- > 2.35.1 >
On Mon, May 09, 2022 at 11:31:58PM +0800, Zorro Lang wrote: > On Mon, May 09, 2022 at 03:31:02PM +0100, fdmanana@kernel.org wrote: > > From: Filipe Manana <fdmanana@suse.com> > > > > Test that if we fsync a directory, create a symlink inside it, rename > > the symlink, fsync again the directory and then power fail, after the > > filesystem is mounted again, the symlink exists with the new name and > > it has the correct content. > > > > This currently fails on btrfs, because the symlink ends up empty (which > > is illegal on Linux), but it is fixed by kernel commit: > > > > d0e64a981fd841 ("btrfs: always log symlinks in full mode") > > > > Reviewed-by: David Disseldorp <ddiss@suse.de> > > Signed-off-by: Filipe Manana <fdmanana@suse.com> > > --- > > > > v2: Rebased on latest for-next, quoted $SCRATCH_MNT references (David Disseldorp) > > and added David's review tag. > > This case is nearly copied from generic/066, so there's not debatable things I think you mean the part of setting the special mount option for f2fs, right? Because otherwise 066 is very different (testing xattrs and not symlink stuff). > from code format. It's in my local testing branch now, and will be pushed in > next release, after regression test done. Thanks for this new test. Thanks! > > Zorro > > > > > tests/generic/690 | 90 +++++++++++++++++++++++++++++++++++++++++++ > > tests/generic/690.out | 2 + > > 2 files changed, 92 insertions(+) > > create mode 100755 tests/generic/690 > > create mode 100644 tests/generic/690.out > > > > diff --git a/tests/generic/690 b/tests/generic/690 > > new file mode 100755 > > index 00000000..f03295a5 > > --- /dev/null > > +++ b/tests/generic/690 > > @@ -0,0 +1,90 @@ > > +#! /bin/bash > > +# SPDX-License-Identifier: GPL-2.0 > > +# Copyright (c) 2022 SUSE Linux Products GmbH. All Rights Reserved. > > +# > > +# FS QA Test 690 > > +# > > +# Test that if we fsync a directory, create a symlink inside it, rename the > > +# symlink, fsync again the directory and then power fail, after the filesystem > > +# is mounted again, the symlink exists with the new name and it has the correct > > +# content. > > +# > > +# On btrfs this used to result in the symlink being empty (i_size 0), and it was > > +# fixed by kernel commit: > > +# > > +# d0e64a981fd841 ("btrfs: always log symlinks in full mode") > > +# > > +. ./common/preamble > > +_begin_fstest auto quick log > > + > > +_cleanup() > > +{ > > + _cleanup_flakey > > + cd / > > + rm -r -f $tmp.* > > +} > > + > > +. ./common/rc > > +. ./common/filter > > +. ./common/dmflakey > > + > > +# real QA test starts here > > + > > +_supported_fs generic > > +_require_scratch > > +_require_symlinks > > +_require_dm_target flakey > > + > > +rm -f $seqres.full > > + > > +# f2fs doesn't support fs-op level transaction functionality, so it has no way > > +# to persist all metadata updates in one transaction. We have to use its mount > > +# option "fastboot" so that it triggers a metadata checkpoint to persist all > > +# metadata updates that happen before a fsync call. Without this, after the > > +# last fsync in the test, the symlink named "baz" will not exist. > > +if [ $FSTYP = "f2fs" ]; then > > + export MOUNT_OPTIONS="-o fastboot $MOUNT_OPTIONS" > > +fi > > + > > +_scratch_mkfs >>$seqres.full 2>&1 > > +_require_metadata_journaling $SCRATCH_DEV > > +_init_flakey > > +_mount_flakey > > + > > +# Create our test directory. > > +mkdir "$SCRATCH_MNT"/testdir > > + > > +# Commit the current transaction and persist the directory. > > +sync > > + > > +# Create a file in the test directory, so that the next fsync on the directory > > +# actually does something (it logs the directory). > > +echo -n > "$SCRATCH_MNT"/testdir/foo > > + > > +# Fsync the directory. > > +$XFS_IO_PROG -c "fsync" "$SCRATCH_MNT"/testdir > > + > > +# Now create a symlink inside the test directory. > > +ln -s "$SCRATCH_MNT"/testdir/foo "$SCRATCH_MNT"/testdir/bar > > + > > +# Rename the symlink. > > +mv "$SCRATCH_MNT"/testdir/bar "$SCRATCH_MNT"/testdir/baz > > + > > +# Fsync again the directory. > > +$XFS_IO_PROG -c "fsync" "$SCRATCH_MNT"/testdir > > + > > +# Simulate a power failure and then mount again the filesystem to replay the > > +# journal/log. > > +_flakey_drop_and_remount > > + > > +# The symlink should exist, with the name "baz" and its content must be > > +# "$SCRATCH_MNT/testdir/foo". > > +[ -L "$SCRATCH_MNT"/testdir/baz ] || echo "symlink 'baz' is missing" > > +symlink_content=$(readlink "$SCRATCH_MNT"/testdir/baz | _filter_scratch) > > +echo "symlink content: ${symlink_content}" > > + > > +_unmount_flakey > > + > > +# success, all done > > +status=0 > > +exit > > diff --git a/tests/generic/690.out b/tests/generic/690.out > > new file mode 100644 > > index 00000000..84be1247 > > --- /dev/null > > +++ b/tests/generic/690.out > > @@ -0,0 +1,2 @@ > > +QA output created by 690 > > +symlink content: SCRATCH_MNT/testdir/foo > > -- > > 2.35.1 > >
diff --git a/tests/generic/690 b/tests/generic/690 new file mode 100755 index 00000000..f03295a5 --- /dev/null +++ b/tests/generic/690 @@ -0,0 +1,90 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2022 SUSE Linux Products GmbH. All Rights Reserved. +# +# FS QA Test 690 +# +# Test that if we fsync a directory, create a symlink inside it, rename the +# symlink, fsync again the directory and then power fail, after the filesystem +# is mounted again, the symlink exists with the new name and it has the correct +# content. +# +# On btrfs this used to result in the symlink being empty (i_size 0), and it was +# fixed by kernel commit: +# +# d0e64a981fd841 ("btrfs: always log symlinks in full mode") +# +. ./common/preamble +_begin_fstest auto quick log + +_cleanup() +{ + _cleanup_flakey + cd / + rm -r -f $tmp.* +} + +. ./common/rc +. ./common/filter +. ./common/dmflakey + +# real QA test starts here + +_supported_fs generic +_require_scratch +_require_symlinks +_require_dm_target flakey + +rm -f $seqres.full + +# f2fs doesn't support fs-op level transaction functionality, so it has no way +# to persist all metadata updates in one transaction. We have to use its mount +# option "fastboot" so that it triggers a metadata checkpoint to persist all +# metadata updates that happen before a fsync call. Without this, after the +# last fsync in the test, the symlink named "baz" will not exist. +if [ $FSTYP = "f2fs" ]; then + export MOUNT_OPTIONS="-o fastboot $MOUNT_OPTIONS" +fi + +_scratch_mkfs >>$seqres.full 2>&1 +_require_metadata_journaling $SCRATCH_DEV +_init_flakey +_mount_flakey + +# Create our test directory. +mkdir "$SCRATCH_MNT"/testdir + +# Commit the current transaction and persist the directory. +sync + +# Create a file in the test directory, so that the next fsync on the directory +# actually does something (it logs the directory). +echo -n > "$SCRATCH_MNT"/testdir/foo + +# Fsync the directory. +$XFS_IO_PROG -c "fsync" "$SCRATCH_MNT"/testdir + +# Now create a symlink inside the test directory. +ln -s "$SCRATCH_MNT"/testdir/foo "$SCRATCH_MNT"/testdir/bar + +# Rename the symlink. +mv "$SCRATCH_MNT"/testdir/bar "$SCRATCH_MNT"/testdir/baz + +# Fsync again the directory. +$XFS_IO_PROG -c "fsync" "$SCRATCH_MNT"/testdir + +# Simulate a power failure and then mount again the filesystem to replay the +# journal/log. +_flakey_drop_and_remount + +# The symlink should exist, with the name "baz" and its content must be +# "$SCRATCH_MNT/testdir/foo". +[ -L "$SCRATCH_MNT"/testdir/baz ] || echo "symlink 'baz' is missing" +symlink_content=$(readlink "$SCRATCH_MNT"/testdir/baz | _filter_scratch) +echo "symlink content: ${symlink_content}" + +_unmount_flakey + +# success, all done +status=0 +exit diff --git a/tests/generic/690.out b/tests/generic/690.out new file mode 100644 index 00000000..84be1247 --- /dev/null +++ b/tests/generic/690.out @@ -0,0 +1,2 @@ +QA output created by 690 +symlink content: SCRATCH_MNT/testdir/foo