From: Filipe Manana Date: Tue, 25 Mar 2025 12:24:40 +0000 (+0000) Subject: generic: test fsync of file with no more hard links X-Git-Tag: v2025.03.30~4 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=6542628fc958a0acc58f764659ee6680637a005f;p=xfstests-dev.git generic: test fsync of file with no more hard links Test that if we fsync a file that has no more hard links, power fail and then mount the filesystem, after the journal/log is replayed, the file doesn't exists anymore. This exercises a bug recently found and fixed by the following patch for the linux kernel: btrfs: fix fsync of files with no hard links not persisting deletion Signed-off-by: Filipe Manana Reviewed-by: "Darrick J. Wong" Reviewed-by: Zorro Lang Signed-off-by: Zorro Lang --- diff --git a/src/multi_open_unlink.c b/src/multi_open_unlink.c index c221d39e..fb054e87 100644 --- a/src/multi_open_unlink.c +++ b/src/multi_open_unlink.c @@ -28,7 +28,7 @@ void usage(char *prog) { - fprintf(stderr, "Usage: %s [-e num-eas] [-f path_prefix] [-n num_files] [-s sleep_time] [-v ea-valuesize] \n", prog); + fprintf(stderr, "Usage: %s [-e num-eas] [-f path_prefix] [-F] [-n num_files] [-s sleep_time] [-S] [-v ea-valuesize] \n", prog); exit(1); } @@ -44,8 +44,10 @@ main(int argc, char *argv[]) int value_size = MAX_VALUELEN; int fd = -1; int i,j,c; + int fsync_files = 0; + int sync_fs = 0; - while ((c = getopt(argc, argv, "e:f:n:s:v:")) != EOF) { + while ((c = getopt(argc, argv, "e:f:Fn:s:Sv:")) != EOF) { switch (c) { case 'e': /* create eas */ num_eas = atoi(optarg); @@ -53,12 +55,18 @@ main(int argc, char *argv[]) case 'f': /* file prefix */ given_path = optarg; break; + case 'F': /* fsync files after unlink */ + fsync_files = 1; + break; case 'n': /* number of files */ num_files = atoi(optarg); break; case 's': /* sleep time */ sleep_time = atoi(optarg); break; + case 'S': /* sync fs after creating files */ + sync_fs = 1; + break; case 'v': /* value size on eas */ value_size = atoi(optarg); break; @@ -83,6 +91,12 @@ main(int argc, char *argv[]) return 1; } + if (sync_fs && syncfs(fd) == -1) { + fprintf(stderr, "%s: failed to sync filesystem: %s\n", + prog, strerror(errno)); + return 1; + } + /* set the EAs */ for (j = 0; j < num_eas; j++) { int sts; @@ -111,6 +125,12 @@ main(int argc, char *argv[]) prog, path, strerror(errno)); return 1; } + + if (fsync_files && fsync(fd) == -1) { + fprintf(stderr, "%s: failed to fsync \"%s\": %s\n", + prog, path, strerror(errno)); + return 1; + } } sleep(sleep_time); diff --git a/tests/generic/764 b/tests/generic/764 new file mode 100755 index 00000000..1b21bc02 --- /dev/null +++ b/tests/generic/764 @@ -0,0 +1,50 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2025 SUSE Linux Products GmbH. All Rights Reserved. +# +# FS QA Test 764 +# +# Test that if we fsync a file that has no more hard links, power fail and then +# mount the filesystem, after the journal/log is replayed, the file doesn't +# exists anymore. +# +. ./common/preamble +_begin_fstest auto quick log + +_cleanup() +{ + _cleanup_flakey + cd / + rm -r -f $tmp.* +} + +. ./common/dmflakey + +[ "$FSTYP" = "btrfs" ] && _fixed_by_kernel_commit xxxxxxxxxxxx \ + "btrfs: fix fsync of files with no hard links not persisting deletion" + +_require_scratch +_require_dm_target flakey +_require_test_program "multi_open_unlink" + +_scratch_mkfs >>$seqres.full 2>&1 || _fail "mkfs failed" +_require_metadata_journaling $SCRATCH_DEV +_init_flakey +_mount_flakey + +mkdir $SCRATCH_MNT/testdir +$here/src/multi_open_unlink -f $SCRATCH_MNT/testdir/foo -F -S -n 1 -s 0 + +# Simulate a power failure and then mount again the filesystem to replay the +# journal/log. +_flakey_drop_and_remount + +# We don't expect the file to exist anymore, since it was fsynced when it had no +# more hard links. +ls $SCRATCH_MNT/testdir + +_unmount_flakey + +echo "Silence is golden" +status=0 +exit diff --git a/tests/generic/764.out b/tests/generic/764.out new file mode 100644 index 00000000..bb58e5b8 --- /dev/null +++ b/tests/generic/764.out @@ -0,0 +1,2 @@ +QA output created by 764 +Silence is golden