Re: [PATCH v2] generic: test fsync of file with no more hard links

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]



On Tue, Mar 25, 2025 at 12:24:40PM +0000, fdmanana@xxxxxxxxxx wrote:
> From: Filipe Manana <fdmanana@xxxxxxxx>
> 
> 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 <fdmanana@xxxxxxxx>
> ---
> 
> V2: Use the src/multi_open_unlink.c program with added options to sync
>     filesystem after creating files and fsync files after the unlink.

This version is good to me,

Reviewed-by: Zorro Lang <zlang@xxxxxxxxxx>

If no more review points this week, I'll merge it this week.

Thanks,
Zorro

> 
>  src/multi_open_unlink.c | 24 ++++++++++++++++++--
>  tests/generic/764       | 50 +++++++++++++++++++++++++++++++++++++++++
>  tests/generic/764.out   |  2 ++
>  3 files changed, 74 insertions(+), 2 deletions(-)
>  create mode 100755 tests/generic/764
>  create mode 100644 tests/generic/764.out
> 
> 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
> -- 
> 2.45.2
> 
> 





[Index of Archives]     [Linux Filesystems Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux