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);
}
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);
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;
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;
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);
--- /dev/null
+#! /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