Skip to contentSkip to conversation

fstests: add test coverage for cloned filesystem ids

PATCH Superseded Anand Jain 5 participants 19 messages Feb 26 – Mar 21 Btrfs file system

v1 of 8 Superseded Latest is v8 →

lore
Share & tools
lore

Anand Jain

author
#0 lore raw

cover fstests: add test coverage for cloned filesystem ids

This series adds fstests infrastructure and test cases to verify correct filesystem identity behaviour when a filesystem is cloned (e.g. via block-level copy), covering inotify, fanotify, f_fsid, libblkid, IMA, and exportfs file handles.

- SCRATCH_DEV_POOL support extended to non-Btrfs filesystems
- _mkfs_scratch_sized_clone() helper to create a cloned filesystem
- _clone_mount_option() helper to apply per-filesystem clone mount options

New tests verify:
- inotify and fanotify events are isolated between cloned filesystems
- f_fsid is unique across cloned filesystem instances
- libblkid correctly resolves duplicate UUIDs to distinct devices
- IMA distinct identity for each cloned filesystem
- exportfs file handles resolve correctly on cloned filesystems

Testing:
Requires kernel patches [1] for all tests to pass.
[1] https://lore.kernel.org/linux-btrfs/[email protected]/

Anand Jain (9):
fstests: allow SCRATCH_DEV_POOL for non-Btrfs filesystems
fstests: add _mkfs_scratch_clone() helper
fstests: add _clone_mount_option() helper
fstests: add test for inotify isolation on cloned devices
fstests: verify fanotify isolation on cloned filesystems
fstests: verify f_fsid for cloned filesystems
fstests: verify libblkid resolution of duplicate UUIDs
fstests: verify IMA isolation on cloned filesystems
fstests: verify exportfs file handles on cloned filesystems

 .gitignore            |   1 +
 common/config         |   1 +
 common/rc             |  55 ++++++++++++++++++-----
 src/Makefile          |   2 +-
 src/fanotify.c        |  66 +++++++++++++++++++++++++++
 tests/generic/790     |  78 ++++++++++++++++++++++++++++++++
 tests/generic/790.out |   7 +++
 tests/generic/791     |  86 +++++++++++++++++++++++++++++++++++
 tests/generic/791.out |   7 +++
 tests/generic/792     |  57 ++++++++++++++++++++++++
 tests/generic/792.out |   7 +++
 tests/generic/793     |  73 ++++++++++++++++++++++++++++++
 tests/generic/793.out |  22 +++++++++
 tests/generic/794     | 101 ++++++++++++++++++++++++++++++++++++++++++
 tests/generic/794.out |  10 +++++
 tests/generic/795     |  67 ++++++++++++++++++++++++++++
 tests/generic/795.out |   2 +
 17 files changed, 629 insertions(+), 13 deletions(-)
 create mode 100644 src/fanotify.c
 create mode 100644 tests/generic/790
 create mode 100644 tests/generic/790.out
 create mode 100644 tests/generic/791
 create mode 100644 tests/generic/791.out
 create mode 100644 tests/generic/792
 create mode 100644 tests/generic/792.out
 create mode 100644 tests/generic/793
 create mode 100644 tests/generic/793.out
 create mode 100644 tests/generic/794
 create mode 100644 tests/generic/794.out
 create mode 100644 tests/generic/795
 create mode 100644 tests/generic/795.out
Signature · 1 line
2.43.0
author
#1 lore raw

PATCH 1/9 fstests: allow SCRATCH_DEV_POOL for non-Btrfs filesystems

Tests for cloned device verification should pass on Btrfs, XFS, and ext4. We need 2 scratch devices, allow SCRATCH_DEV_POOL for other FSs.

---
 common/rc | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)
common/rc +3 -12
index 92cb69820311..9db8b3e88996 100644
@@ -3990,18 +3990,9 @@ _require_scratch_dev_pool()
 		ndevs=$1
 	fi
 
-	# btrfs test case needs ndevs or more scratch_dev_pool; other FS not sure
-	# so fail it
-	case $FSTYP in
-	btrfs)
-		if [ "`echo $SCRATCH_DEV_POOL|wc -w`" -lt $ndevs ]; then
-			_notrun "btrfs and this test needs $ndevs or more disks in SCRATCH_DEV_POOL"
-		fi
-	;;
-	*)
-		_notrun "dev_pool is not supported by fstype \"$FSTYP\""
-	;;
-	esac
+	if [ "`echo $SCRATCH_DEV_POOL|wc -w`" -lt $ndevs ]; then
+		_notrun "This test needs $ndevs or more disks in SCRATCH_DEV_POOL"
+	fi
 
 	for i in $SCRATCH_DEV_POOL; do
 		if [ "`_is_block_dev "$i"`" = "" ]; then
Signature · 1 line
2.43.0
author
#2 lore raw

PATCH 2/9 fstests: add _mkfs_scratch_clone() helper

In reply to Anand Jain

Introduce _mkfs_scratch_clone() to mkfs the scratch device and clone it to the next device in SCRATCH_DEV_POOL.

---
 common/rc | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)
common/rc +32 -0
index 9db8b3e88996..2253438ef0f6 100644
@@ -1503,6 +1503,38 @@ _scratch_resvblks()
 	esac
 }
 
+_scratch_mkfs_sized_clone()
+{
+	local devs=($SCRATCH_DEV_POOL)
+	local scratch_data="$1"
+	local size=$(_small_fs_size_mb 128) # Smallest possible
+
+	size=$((size * 1024 * 1024))
+
+	# make sure there are two devices
+	if [ "${#devs[@]}" -ne 2 ]; then
+		_notrun "Test requires exactly 2 devices"
+	fi
+
+	case "$FSTYP" in
+	"btrfs")
+		_scratch_mkfs_sized $size
+		_scratch_mount
+		$BTRFS_UTIL_PROG subvolume create $SCRATCH_MNT/sv1
+		_scratch_unmount
+		;;
+	"xfs"|"ext4")
+		_scratch_mkfs_sized $size
+		;;
+	*)
+		_notrun "fstests clone op unsupported for FS $FSTYP"
+		;;
+	esac
+
+	# clone SCRATCH_DEV devs[0] to devs[1].
+	dd if=$SCRATCH_DEV of=${devs[1]} bs=$size status=none count=1 || \
+							_fail "Clone failed"
+}
 
 # Repair scratch filesystem.  Returns 0 if the FS is good to go (either no
 # errors found or errors were fixed) and nonzero otherwise; also spits out
Signature · 1 line
2.43.0
#3 lore raw

Re: [PATCH 2/9] fstests: add _mkfs_scratch_clone() helper

Quoted 16 lines · Anand Jain

Introduce _mkfs_scratch_clone() to mkfs the scratch device and clone it to the next device in SCRATCH_DEV_POOL.

---
 common/rc | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)
common/rc +0 -0
index 9db8b3e88996..2253438ef0f6 100644
@@ -1503,6 +1503,38 @@ _scratch_resvblks()
 	esac
 }
 

common/rc _scratch_resvblks() · line 1515

Quoted 10 lines
common/rc +10 -0
+_scratch_mkfs_sized_clone()
+{
+	local devs=($SCRATCH_DEV_POOL)
+	local scratch_data="$1"
+	local size=$(_small_fs_size_mb 128) # Smallest possible
+
+	size=$((size * 1024 * 1024))
+
+	# make sure there are two devices
+	if [ "${#devs[@]}" -ne 2 ]; then

What about if ${#devs[@]} > 2 ?

Quoted 11 lines
common/rc +11 -0
+		_notrun "Test requires exactly 2 devices"
+	fi
+
+	case "$FSTYP" in
+	"btrfs")
+		_scratch_mkfs_sized $size
+		_scratch_mount
+		$BTRFS_UTIL_PROG subvolume create $SCRATCH_MNT/sv1
+		_scratch_unmount
+		;;
+	"xfs"|"ext4")

common/rc _scratch_resvblks() · line 1536

Quoted 10 lines
common/rc +10 -0
+		_scratch_mkfs_sized $size
+		;;
+	*)
+		_notrun "fstests clone op unsupported for FS $FSTYP"
+		;;
+	esac
+
+	# clone SCRATCH_DEV devs[0] to devs[1].
+	dd if=$SCRATCH_DEV of=${devs[1]} bs=$size status=none count=1 || \
+							_fail "Clone failed"

I'm wondering if we absolutely need to use SCRATCH_DEV_POOL for this test. Could we clone SCRATCH_DEV to an image file instead? Or would it be feasible to simply run the test using two image files?

Thanks,
Zorro

Quoted 8 lines
common/rc +1 -0
+}
 
 # Repair scratch filesystem.  Returns 0 if the FS is good to go (either no
 # errors found or errors were fixed) and nonzero otherwise; also spits out
Signature · 1 line
2.43.0
#4 lore raw

Re: [PATCH 2/9] fstests: add _mkfs_scratch_clone() helper

Quoted 2 lines

What about if ${#devs[@]} > 2 ?

On purpose- so tests using _scratch_mkfs_sized_clone() don't pick a random higher number. If a test needs more than two devices, opens an opportunity to critically review this function.

Quoted 15 lines
Quoted 15 lines
common/rc +15 -0
+	fi
+
+	case "$FSTYP" in
+	"btrfs")
+		_scratch_mkfs_sized $size
+		_scratch_mount
+		$BTRFS_UTIL_PROG subvolume create $SCRATCH_MNT/sv1
+		_scratch_unmount
+		;;
+	"xfs"|"ext4")
+		_scratch_mkfs_sized $size
+		;;
+	*)
+		_notrun "fstests clone op unsupported for FS $FSTYP"
+		;;
Quoted 8 lines

common/rc _scratch_resvblks() · line 1536

Quoted 5 lines
common/rc +5 -0
+	esac
+
+	# clone SCRATCH_DEV devs[0] to devs[1].
+	dd if=$SCRATCH_DEV of=${devs[1]} bs=$size status=none count=1 || \
+							_fail "Clone failed"

I'm wondering if we absolutely need to use SCRATCH_DEV_POOL for this test. Could we clone SCRATCH_DEV to an image file instead? Or would it be feasible to simply run the test using two image files?

Using a config file and testing directly on block devices lets us cover a wider range of devices.

When I wrote this test case, I was also considering whether a serial-number–based mount without extra mount option, would be better in the kernel.

The downside is that xfs/ext4 testers now need to use SCRATCH_DEV_POOL. Let me know what you prefer.

#5 lore raw

Re: [PATCH 2/9] fstests: add _mkfs_scratch_clone() helper

Quoted 33 lines · Anand Jain
Quoted 2 lines

What about if ${#devs[@]} > 2 ?

On purpose- so tests using _scratch_mkfs_sized_clone() don't pick a random higher number. If a test needs more than two devices, opens an opportunity to critically review this function.

Quoted 15 lines
Quoted 15 lines
common/rc +15 -0
+	fi
+
+	case "$FSTYP" in
+	"btrfs")
+		_scratch_mkfs_sized $size
+		_scratch_mount
+		$BTRFS_UTIL_PROG subvolume create $SCRATCH_MNT/sv1
+		_scratch_unmount
+		;;
+	"xfs"|"ext4")
+		_scratch_mkfs_sized $size
+		;;
+	*)
+		_notrun "fstests clone op unsupported for FS $FSTYP"
+		;;
Quoted 8 lines

common/rc _scratch_resvblks() · line 1536

Quoted 5 lines
common/rc +5 -0
+	esac
+
+	# clone SCRATCH_DEV devs[0] to devs[1].
+	dd if=$SCRATCH_DEV of=${devs[1]} bs=$size status=none count=1 || \
+							_fail "Clone failed"

I'm wondering if we absolutely need to use SCRATCH_DEV_POOL for this test. Could we clone SCRATCH_DEV to an image file instead? Or would it be feasible to simply run the test using two image files?

Using a config file and testing directly on block devices lets us cover a wider range of devices.

Quoted 6 lines

When I wrote this test case, I was also considering whether a serial-number–based mount without extra mount option, would be better in the kernel.

The downside is that xfs/ext4 testers now need to use SCRATCH_DEV_POOL. Let me know what you prefer.

I'm concerned that testers from other filesystems might not be familiar with SCRATCH_DEV_POOL, as it's typically not a requirement for their testing. I'm not sure if they would be willing to configure and switch to SCRATCH_DEV_POOL, just for these few test cases. If we can avoid making the pool to be a hard requirement, it might be more user-friendly for other fs list. Welcome feedback and review points from other filesystem mailing lists :)

Thanks,
Zorro

Quoted 4 lines
#6 lore raw

Re: [PATCH 2/9] fstests: add _mkfs_scratch_clone() helper

Quoted 7 lines · Zorro Lang

I'm concerned that testers from other filesystems might not be familiar with SCRATCH_DEV_POOL, as it's typically not a requirement for their testing. I'm not sure if they would be willing to configure and switch to SCRATCH_DEV_POOL, just for these few test cases. If we can avoid making the pool to be a hard requirement, it might be more user-friendly for other fs list. Welcome feedback and review points from other filesystem mailing lists :)

Yes, doing this using loop devices or ramdisk is going to get us much better coverage.

#7 lore raw

Re: [PATCH 2/9] fstests: add _mkfs_scratch_clone() helper

Quoted 11 lines · Christoph Hellwig
Quoted 7 lines · Zorro Lang

I'm concerned that testers from other filesystems might not be familiar with SCRATCH_DEV_POOL, as it's typically not a requirement for their testing. I'm not sure if they would be willing to configure and switch to SCRATCH_DEV_POOL, just for these few test cases. If we can avoid making the pool to be a hard requirement, it might be more user-friendly for other fs list. Welcome feedback and review points from other filesystem mailing lists :)

Yes, doing this using loop devices or ramdisk is going to get us much better coverage.

Agreed. Let's stick with SCRATCH_DEV compatibility for now. v2 is in the ML.

Thanks.

author
#8 lore raw

PATCH 3/9 fstests: add _clone_mount_option() helper

In reply to Anand Jain

Adds _clone_mount_option() helper function to handle filesystem-specific requirements for mounting cloned devices. Abstract the need for -o nouuid on XFS.

---
 common/rc | 8 ++++++++
 1 file changed, 8 insertions(+)
common/rc +8 -0
index 2253438ef0f6..438de54a467b 100644
@@ -397,6 +397,14 @@ _scratch_mount_options()
 					$SCRATCH_DEV $SCRATCH_MNT
 }
 
+_clone_mount_option()
+{
+	local mount_opts=""
+	[[ "$FSTYP" == "xfs" ]] && mount_opts="-o nouuid"
+
+	echo $mount_opts
+}
+
 _supports_filetype()
 {
 	local dir=$1
Signature · 1 line
2.43.0
author
#9 lore raw

PATCH 4/9 fstests: add test for inotify isolation on cloned devices

In reply to Anand Jain

Add a new test, to verify that the kernel correctly differentiates between two block devices sharing the same FSID/UUID.

---
 common/config         |  1 +
 tests/generic/790     | 78 +++++++++++++++++++++++++++++++++++++++++++
 tests/generic/790.out |  7 ++++
 3 files changed, 86 insertions(+)
 create mode 100644 tests/generic/790
 create mode 100644 tests/generic/790.out
common/config +1 -0
index 1420e35ddfee..c08f828575a2 100644
@@ -228,6 +228,7 @@ export BTRFS_MAP_LOGICAL_PROG=$(type -P btrfs-map-logical)
 export PARTED_PROG="$(type -P parted)"
 export XFS_PROPERTY_PROG="$(type -P xfs_property)"
 export FSCRYPTCTL_PROG="$(type -P fscryptctl)"
+export INOTIFYWAIT_PROG="$(type -P inotifywait)"
 
 # udev wait functions.
 #
tests/generic/790 new file +78 -0

78 lines not on this page · raw message

tests/generic/790.out new file +7 -0
new file mode 100644
index 000000000000..3c92c34ffbda
@@ -0,0 +1,7 @@
+QA output created by 790
+Setup inotify watchers on both SCRATCH_MNT and mnt2
+Trigger file creation on SCRATCH_MNT
+Trigger file creation on mnt2
+Verify inotify isolation
+SUCCESS: SCRATCH_MNT events isolated.
+SUCCESS: mnt2 events isolated.
Signature · 1 line
2.43.0
#10 lore raw

Re: [PATCH 4/9] fstests: add test for inotify isolation on cloned devices

Quoted 79 lines · Anand Jain

Add a new test, to verify that the kernel correctly differentiates between two block devices sharing the same FSID/UUID.

---
 common/config         |  1 +
 tests/generic/790     | 78 +++++++++++++++++++++++++++++++++++++++++++
 tests/generic/790.out |  7 ++++
 3 files changed, 86 insertions(+)
 create mode 100644 tests/generic/790
 create mode 100644 tests/generic/790.out
common/config +1 -0
index 1420e35ddfee..c08f828575a2 100644
@@ -228,6 +228,7 @@ export BTRFS_MAP_LOGICAL_PROG=$(type -P btrfs-map-logical)
 export PARTED_PROG="$(type -P parted)"
 export XFS_PROPERTY_PROG="$(type -P xfs_property)"
 export FSCRYPTCTL_PROG="$(type -P fscryptctl)"
+export INOTIFYWAIT_PROG="$(type -P inotifywait)"
 
 # udev wait functions.
 #
tests/generic/790 new file +49 -0
new file mode 100644
index 000000000000..3809fced622d
@@ -0,0 +1,78 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2026 Anand Jain <[email protected]>.  All Rights Reserved.
+#
+# FS QA Test 790
+#
+# Verify if the kernel or userspace becomes confused when two block devices
+# share the same fid/fsid/uuid. Create inotify on both original and cloned
+# filesystem. Monitor the notification in the respective logs.
+
+. ./common/preamble
+
+_begin_fstest auto quick mount clone
+
+_require_test
+_require_scratch_dev_pool 2
+_require_command "$INOTIFYWAIT_PROG" inotifywait
+
+_cleanup()
+{
+	cd /
+	rm -r -f $tmp.*
+	umount $mnt1 $mnt2 2>/dev/null
+	_scratch_dev_pool_put
+}
+
+_scratch_dev_pool_get 2
+_scratch_mkfs_sized_clone >$seqres.full 2>&1
+devs=($SCRATCH_DEV_POOL)
+mnt2=$TEST_DIR/mnt2
+mkdir -p $mnt2
+
+_scratch_mount $(_clone_mount_option)
+_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[1]} $mnt2 || \
+						_fail "Failed to mount dev2"
+
+log1=$tmp.inotify1
+log2=$tmp.inotify2
+
+echo "Setup inotify watchers on both SCRATCH_MNT and mnt2"
+$INOTIFYWAIT_PROG -m -e create --format '%f' $SCRATCH_MNT > $log1 2>&1 &
+pid1=$!
+$INOTIFYWAIT_PROG -m -e create --format '%f' $mnt2 > $log2 2>&1 &
+pid2=$!
+sleep 2
+
+echo "Trigger file creation on SCRATCH_MNT"
+touch $SCRATCH_MNT/file_on_scratch_mnt
+sync

tests/generic/790 line 59

Quoted 10 lines
tests/generic/790 new file +10 -0
+sleep 1
+
+echo "Trigger file creation on mnt2"
+touch $mnt2/file_on_mnt2
+sync
+sleep 1
+
+echo "Verify inotify isolation"
+kill $pid1 $pid2
+wait $pid1 $pid2 2>/dev/null

I think you also need to take care of killing the bg process in _cleanup() so that the test could be cleanly aborted.

Thanks,
Amir.

Quoted 35 lines
tests/generic/790 new file +19 -0
+
+if grep -q "file_on_scratch_mnt" $log1 && ! grep -q "file_on_mnt2" $log1; then
+	echo "SUCCESS: SCRATCH_MNT events isolated."
+else
+	echo "FAIL: SCRATCH_MNT inotify confusion!"
+	[ ! -s $log1 ] && echo "  - SCRATCH_MNT received no events."
+	grep -q "file_on_mnt2" $log1 && echo "  - SCRATCH_MNT received event from mnt2."
+fi
+
+if grep -q "file_on_mnt2" $log2 && ! grep -q "file_on_scratch_mnt" $log2; then
+	echo "SUCCESS: mnt2 events isolated."
+else
+	echo "FAIL: mnt2 inotify confusion!"
+	[ ! -s $log2 ] && echo "  - mnt2 received no events."
+	grep -q "file_on_scratch_mnt" $log2 && echo "  - mnt2 received event from SCRATCH_MNT."
+fi
+
+status=0
+exit
tests/generic/790.out new file +7 -0
new file mode 100644
index 000000000000..3c92c34ffbda
@@ -0,0 +1,7 @@
+QA output created by 790
+Setup inotify watchers on both SCRATCH_MNT and mnt2
+Trigger file creation on SCRATCH_MNT
+Trigger file creation on mnt2
+Verify inotify isolation
+SUCCESS: SCRATCH_MNT events isolated.
+SUCCESS: mnt2 events isolated.
Signature · 1 line
2.43.0
#11 lore raw

Re: [PATCH 4/9] fstests: add test for inotify isolation on cloned devices

Quoted 37 lines
Quoted 37 lines
tests/generic/790 new file +36 -0
+_cleanup()
+{
+	cd /
+	rm -r -f $tmp.*
+	umount $mnt1 $mnt2 2>/dev/null
+	_scratch_dev_pool_put
+}
+
+_scratch_dev_pool_get 2
+_scratch_mkfs_sized_clone >$seqres.full 2>&1
+devs=($SCRATCH_DEV_POOL)
+mnt2=$TEST_DIR/mnt2
+mkdir -p $mnt2
+
+_scratch_mount $(_clone_mount_option)
+_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[1]} $mnt2 || \
+						_fail "Failed to mount dev2"
+
+log1=$tmp.inotify1
+log2=$tmp.inotify2
+
+echo "Setup inotify watchers on both SCRATCH_MNT and mnt2"
+$INOTIFYWAIT_PROG -m -e create --format '%f' $SCRATCH_MNT > $log1 2>&1 &
+pid1=$!
+$INOTIFYWAIT_PROG -m -e create --format '%f' $mnt2 > $log2 2>&1 &
+pid2=$!
+sleep 2
+
+echo "Trigger file creation on SCRATCH_MNT"
+touch $SCRATCH_MNT/file_on_scratch_mnt
+sync
+sleep 1
+
+echo "Trigger file creation on mnt2"
+touch $mnt2/file_on_mnt2
+sync
Quoted 8 lines

tests/generic/790 line 59

Quoted 5 lines
tests/generic/790 new file +5 -0
+sleep 1
+
+echo "Verify inotify isolation"
+kill $pid1 $pid2
+wait $pid1 $pid2 2>/dev/null

I think you also need to take care of killing the bg process in _cleanup() so that the test could be cleanly aborted.

You are right, SIGINT can terminate the testcase at any point, we need kill(1) in _cleanup().

I'll fix this in v2.

Thanks, Anand

author
#12 lore raw

PATCH 5/9 fstests: verify fanotify isolation on cloned filesystems

In reply to Anand Jain

Verify that fanotify events are correctly routed to the appropriate watcher when cloned filesystems are mounted.
Helps verify kernel's event notification distinguishes between devices sharing the same FSID/UUID.

---
 .gitignore            |  1 +
 src/Makefile          |  2 +-
 src/fanotify.c        | 66 +++++++++++++++++++++++++++++++++
 tests/generic/791     | 86 +++++++++++++++++++++++++++++++++++++++++++
 tests/generic/791.out |  7 ++++
 5 files changed, 161 insertions(+), 1 deletion(-)
 create mode 100644 src/fanotify.c
 create mode 100644 tests/generic/791
 create mode 100644 tests/generic/791.out
.gitignore +1 -0
index 82c57f415301..7f91310ce58b 100644
@@ -212,6 +212,7 @@ tags
 /src/dio-writeback-race
 /src/unlink-fsync
 /src/file_attr
+/src/fanotify
 
 # Symlinked files
 /tests/generic/035.out
src/Makefile +1 -1
index d0a4106e6be8..ff71cde936a7 100644
@@ -36,7 +36,7 @@ LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
 	fscrypt-crypt-util bulkstat_null_ocount splice-test chprojid_fail \
 	detached_mounts_propagation ext4_resize t_readdir_3 splice2pipe \
 	uuid_ioctl t_snapshot_deleted_subvolume fiemap-fault min_dio_alignment \
-	rw_hint
+	rw_hint fanotify
 
 EXTRA_EXECS = dmerror fill2attr fill2fs fill2fs_check scaleread.sh \
 	      btrfs_crc32c_forged_name.py popdir.pl popattr.py \
src/fanotify.c new file +66 -0

66 lines not on this page · raw message

tests/generic/791 new file +86 -0

86 lines not on this page · raw message

tests/generic/791.out new file +7 -0
new file mode 100644
index 000000000000..9725c99bcb4b
@@ -0,0 +1,7 @@
+QA output created by 791
+Setup FID fanotify watchers on both SCRATCH_MNT and mnt2
+Trigger file creation on SCRATCH_MNT
+Trigger file creation on mnt2
+Verify fsid in the fanotify
+SUCCESS: SCRATCH_MNT events found
+SUCCESS: mnt2 events found
Signature · 1 line
2.43.0
#13 lore raw

Re: [PATCH 5/9] fstests: verify fanotify isolation on cloned filesystems

Quoted 34 lines · Anand Jain

Verify that fanotify events are correctly routed to the appropriate watcher when cloned filesystems are mounted.
Helps verify kernel's event notification distinguishes between devices sharing the same FSID/UUID.

---
 .gitignore            |  1 +
 src/Makefile          |  2 +-
 src/fanotify.c        | 66 +++++++++++++++++++++++++++++++++
 tests/generic/791     | 86 +++++++++++++++++++++++++++++++++++++++++++
 tests/generic/791.out |  7 ++++
 5 files changed, 161 insertions(+), 1 deletion(-)
 create mode 100644 src/fanotify.c
 create mode 100644 tests/generic/791
 create mode 100644 tests/generic/791.out
.gitignore +1 -0
index 82c57f415301..7f91310ce58b 100644
@@ -212,6 +212,7 @@ tags
 /src/dio-writeback-race
 /src/unlink-fsync
 /src/file_attr
+/src/fanotify
 
 # Symlinked files
 /tests/generic/035.out
src/Makefile +0 -0
index d0a4106e6be8..ff71cde936a7 100644

src/Makefile LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \ · line 39

Quoted 5 lines
src/Makefile +1 -1
@@ -36,7 +36,7 @@ LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
 	fscrypt-crypt-util bulkstat_null_ocount splice-test chprojid_fail \
 	detached_mounts_propagation ext4_resize t_readdir_3 splice2pipe \
 	uuid_ioctl t_snapshot_deleted_subvolume fiemap-fault min_dio_alignment \
-	rw_hint
+	rw_hint fanotify

Check if you already have fsnotifywait installed on your system most likely you do. It was added to inotify-tools quite some time ago. Could save you from adding a custom prog.
Not 100% sure about fsnotifywait, but quite sure that fsnotifywatch --verbose prints the FSID of events.

Thanks,
Amir.

Quoted 183 lines
src/Makefile +0 -0
 EXTRA_EXECS = dmerror fill2attr fill2fs fill2fs_check scaleread.sh \
 	      btrfs_crc32c_forged_name.py popdir.pl popattr.py \
src/fanotify.c new file +66 -0
new file mode 100644
index 000000000000..e30c48dc0e52
@@ -0,0 +1,66 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0
+ * Copyright (c) 2026 Anand Jain <[email protected]>.  All Rights Reserved.
+ *
+ * Simple fanotify monitor to verify mount-point event isolation.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/fanotify.h>
+
+int main(int argc, char *argv[])
+{
+	int fd;
+	char buf[4096] __attribute__((aligned(8)));
+	setlinebuf(stdout);
+
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s <path>\n", argv[0]);
+		return 1;
+	}
+
+	// Initialize with FID reporting
+	fd = fanotify_init(FAN_CLASS_NOTIF | FAN_REPORT_FID, O_RDONLY);
+	if (fd < 0) {
+		perror("fanotify_init");
+		return 1;
+	}
+
+	if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_FILESYSTEM,
+			  FAN_CREATE, AT_FDCWD, argv[1]) < 0) {
+		perror("fanotify_mark");
+		return 1;
+	}
+
+	printf("Listening for events on %s...\n", argv[1]);
+	while (1) {
+		struct fanotify_event_metadata *metadata = (struct fanotify_event_metadata *)buf;
+		ssize_t len = read(fd, buf, sizeof(buf));
+
+		if (len <= 0) break;
+
+		while (FAN_EVENT_OK(metadata, len)) {
+			// metadata_len is the offset to the first info record
+			if (metadata->event_len > metadata->metadata_len) {
+				struct fanotify_event_info_header *hdr =
+(struct fanotify_event_info_header *)((char *)metadata + metadata->metadata_len);
+
+				if (hdr->info_type == FAN_EVENT_INFO_TYPE_FID) {
+					struct fanotify_event_info_fid *fid = (struct fanotify_event_info_fid *)hdr;
+					printf("FSID: %08x%08x\n",
+						fid->fsid.val[0], fid->fsid.val[1]);
+				}
+			}
+			metadata = FAN_EVENT_NEXT(metadata, len);
+		}
+	}
+
+	fflush(stdout);
+	close(fd);
+	return 0;
+}
tests/generic/791 new file +86 -0
new file mode 100644
index 000000000000..fe8109083732
@@ -0,0 +1,86 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2026 Anand Jain <[email protected]>.  All Rights Reserved.
+#
+# FS QA Test 791
+# Verify fanotify FID functionality on cloned filesystems by setting up
+# watchers and making sure notifications are in the correct logs files.
+
+. ./common/preamble
+
+_begin_fstest auto quick mount clone
+
+_require_test
+_require_scratch_dev_pool 2
+
+[ "$FSTYP" = "ext4" ] && _fixed_by_kernel_commit xxxxxxxxxxxx \
+	"ext4: derive f_fsid from block device to avoid collisions"
+
+_cleanup()
+{
+	cd /
+	rm -r -f $tmp.*
+	umount $mnt1 $mnt2 2>/dev/null
+	_scratch_dev_pool_put
+}
+
+_scratch_dev_pool_get 2
+_scratch_mkfs_sized_clone >$seqres.full 2>&1
+devs=($SCRATCH_DEV_POOL)
+mnt2=$TEST_DIR/mnt2
+mkdir -p $mnt2
+
+_scratch_mount $(_clone_mount_option)
+_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[1]} $mnt2 || \
+						_fail "Failed to mount dev2"
+
+fsid1=$(stat -f -c "%i" $SCRATCH_MNT)
+fsid2=$(stat -f -c "%i" $mnt2)
+
+[[ "$fsid1" == "$fsid2" ]] && \
+	_notrun "Require clone filesystem with unique f_fsid"
+
+log1=$tmp.fanotify1
+log2=$tmp.fanotify2
+
+echo "Setup FID fanotify watchers on both SCRATCH_MNT and mnt2"
+$here/src/fanotify $SCRATCH_MNT > $log1 2>&1 &
+pid1=$!
+$here/src/fanotify $mnt2 > $log2 2>&1 &
+pid2=$!
+sleep 2
+
+echo "Trigger file creation on SCRATCH_MNT"
+touch $SCRATCH_MNT/file_on_scratch_mnt
+sync
+sleep 1
+
+echo "Trigger file creation on mnt2"
+touch $mnt2/file_on_mnt2
+sync
+sleep 1
+
+echo "Verify fsid in the fanotify"
+kill $pid1 $pid2
+wait $pid1 $pid2 2>/dev/null
+
+echo fsid1=$fsid1 fsid2=$fsid2 >> $seqres.full
+cat $log1 >> $seqres.full
+cat $log2 >> $seqres.full
+
+if grep -q "${fsid1}" $log1 && ! grep -q "${fsid2}" $log1; then
+	echo "SUCCESS: SCRATCH_MNT events found"
+else
+	[ ! -s $log1 ] && echo "  - SCRATCH_MNT received no events."
+	grep -q "${fsid2}" $log1 && echo "  - SCRATCH_MNT received event from mnt2."
+fi
+
+if grep -q "${fsid2}" $log2 && ! grep -q "${fsid1}" $log2; then
+	echo "SUCCESS: mnt2 events found"
+else
+	[ ! -s $log2 ] && echo "  - mnt2 received no events."
+	grep -q "${fsid1}" $log2 && echo "  - mnt2 received event from SCRATCH_MNT."
+fi
+
+status=0
+exit
tests/generic/791.out new file +7 -0
new file mode 100644
index 000000000000..9725c99bcb4b
@@ -0,0 +1,7 @@
+QA output created by 791
+Setup FID fanotify watchers on both SCRATCH_MNT and mnt2
+Trigger file creation on SCRATCH_MNT
+Trigger file creation on mnt2
+Verify fsid in the fanotify
+SUCCESS: SCRATCH_MNT events found
+SUCCESS: mnt2 events found
Signature · 1 line
2.43.0
#14 lore raw

Re: [PATCH 5/9] fstests: verify fanotify isolation on cloned filesystems

Quoted 18 lines

src/Makefile LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \ · line 39

Quoted 11 lines
src/Makefile +1 -1
index d0a4106e6be8..ff71cde936a7 100644
@@ -36,7 +36,7 @@ LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
 	fscrypt-crypt-util bulkstat_null_ocount splice-test chprojid_fail \
 	detached_mounts_propagation ext4_resize t_readdir_3 splice2pipe \
 	uuid_ioctl t_snapshot_deleted_subvolume fiemap-fault min_dio_alignment \
-	rw_hint
+	rw_hint fanotify

Check if you already have fsnotifywait installed on your system most likely you do. It was added to inotify-tools quite some time ago. Could save you from adding a custom prog.
Not 100% sure about fsnotifywait, but quite sure that fsnotifywatch --verbose prints the FSID of events.

I missed that command. V2 switched to using fsnotifywait. V2 is not sent yet, I'll wait for any further comments.

Thanks for the review.

Anand

Quoted 2 lines

Thanks,
Amir.

author
#15 lore raw

PATCH 6/9 fstests: verify f_fsid for cloned filesystems

In reply to Anand Jain

Verify that the cloned filesystem provides an f_fsid that is persistent across mount cycles, yet unique from the original filesystem's f_fsid.

---
 tests/generic/792     | 57 +++++++++++++++++++++++++++++++++++++++++++
 tests/generic/792.out |  7 ++++++
 2 files changed, 64 insertions(+)
 create mode 100644 tests/generic/792
 create mode 100644 tests/generic/792.out
tests/generic/792 new file +57 -0
new file mode 100644
index 000000000000..3a2f463dc76e
@@ -0,0 +1,57 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2026 Anand Jain <[email protected]>.  All Rights Reserved.
+#
+# FS QA Test 792
+# Verify f_fsid and s_uuid of cloned filesystems across mount cycle.
+
+. ./common/preamble
+
+_begin_fstest auto quick mount clone
+
+_require_test
+_require_scratch_dev_pool 2
+
+[ "$FSTYP" = "btrfs" ] && _fixed_by_kernel_commit xxxxxxxxxxxx \
+	"btrfs: use on-disk uuid for s_uuid in temp_fsid mounts"
+[ "$FSTYP" = "btrfs" ] && _fixed_by_kernel_commit xxxxxxxxxxxx \
+	"btrfs: derive f_fsid from on-disk fsuuid and dev_t"
+
+_cleanup()
+{
+	cd /
+	rm -r -f $tmp.*
+	umount $mnt2 2>/dev/null
+	_scratch_dev_pool_put
+}
+
+_scratch_dev_pool_get 2
+_scratch_mkfs_sized_clone >$seqres.full 2>&1
+devs=($SCRATCH_DEV_POOL)
+mnt2=$TEST_DIR/mnt2
+mkdir -p $mnt2
+
+_scratch_mount $(_clone_mount_option)
+_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[1]} $mnt2 || \
+						_fail "Failed to mount dev2"
+
+fsid_scratch=$(stat -f -c "%i" $SCRATCH_MNT)
+fsid_clone=$(stat -f -c "%i" $mnt2)
+
+echo "**** fsid initially ****"
+echo $fsid_scratch | sed -e "s/$fsid_scratch/FSID_SCRATCH/g"
+echo $fsid_clone | sed -e "s/$fsid_clone/FSID_CLONE/g"
+
+# Make sure fsid still match across a mount cycle, also reverse the order.
+echo "**** fsid after mount cycle ****"
+_scratch_unmount
+_unmount $mnt2
+_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[1]} $mnt2 || \
+						_fail "Failed to mount dev2"
+_scratch_mount $(_clone_mount_option)
+
+stat -f -c "%i" $SCRATCH_MNT | sed -e "s/$fsid_scratch/FSID_SCRATCH/g"
+stat -f -c "%i" $mnt2 | sed -e "s/$fsid_clone/FSID_CLONE/g"
+
+status=0
+exit
tests/generic/792.out new file +7 -0
new file mode 100644
index 000000000000..27ecbce2225e
@@ -0,0 +1,7 @@
+QA output created by 792
+**** fsid initially ****
+FSID_SCRATCH
+FSID_CLONE
+**** fsid after mount cycle ****
+FSID_SCRATCH
+FSID_CLONE
Signature · 1 line
2.43.0
author
#16 lore raw

PATCH 7/9 fstests: verify libblkid resolution of duplicate UUIDs

In reply to Anand Jain

Verify how findmnt, df (libblkid) resolve device paths when multiple block devices share the same FSUUID.

---
 tests/generic/793     | 73 +++++++++++++++++++++++++++++++++++++++++++
 tests/generic/793.out | 22 +++++++++++++
 2 files changed, 95 insertions(+)
 create mode 100644 tests/generic/793
 create mode 100644 tests/generic/793.out
tests/generic/793 new file +73 -0
new file mode 100644
index 000000000000..dd80212fad73
@@ -0,0 +1,73 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2026 Anand Jain <[email protected]>.  All Rights Reserved.
+#
+# FS QA Test 793
+# Verify how libblkid resolve devices when multiple devices sharing the
+# same FSUUID.
+
+. ./common/preamble
+. ./common/filter
+
+_begin_fstest auto quick mount clone
+
+_require_test
+_require_scratch_dev_pool 2
+
+_cleanup()
+{
+	cd /
+	rm -r -f $tmp.*
+	umount $mnt2 2>/dev/null
+	_scratch_dev_pool_put
+}
+
+filter_pool()
+{
+	_filter_scratch | \
+		sed -e "s|${devs[1]}|DEV2|g" \
+		    -e "s|$mnt2|MNT2|g" | \
+		_filter_spaces
+}
+
+print_info()
+{
+	local mntpt=$1
+	local tgt=$(findmnt -no SOURCE $mntpt)
+	local fsuuid=$(blkid -s UUID -o value $tgt)
+
+	echo "mntpt=$mntpt tgt=$tgt fsuuid=$fsuuid" >> $seqres.full
+	echo
+	findmnt -o SOURCE,TARGET,UUID "$tgt" | tail -n +2 | \
+					sed -e "s/$fsuuid/FSUUID/g" | filter_pool
+	awk -v dev="$tgt" '$1 == dev { print $1, $2 }' /proc/self/mounts | \
+								filter_pool
+	df --all --output=source,target "$tgt" | tail -n +2 | filter_pool
+	echo
+}
+
+_scratch_dev_pool_get 2
+_scratch_mkfs_sized_clone >$seqres.full 2>&1
+devs=($SCRATCH_DEV_POOL)
+mnt2=$TEST_DIR/mnt2
+mkdir -p $mnt2
+
+_scratch_mount $(_clone_mount_option)
+_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[1]} $mnt2 || \
+						_fail "Failed to mount dev2"
+
+print_info $SCRATCH_MNT
+print_info $mnt2
+
+echo "**** mount cycle ****"
+_scratch_unmount
+_unmount $mnt2
+_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[1]} $mnt2 || \
+						_fail "Failed to mount dev2"
+_scratch_mount $(_clone_mount_option)
+
+print_info $SCRATCH_MNT
+print_info $mnt2
+
+status=0
+exit
tests/generic/793.out new file +22 -0
new file mode 100644
index 000000000000..4c7c349ec4ed
@@ -0,0 +1,22 @@
+QA output created by 793
+
+SCRATCH_DEV SCRATCH_MNT FSUUID
+SCRATCH_DEV SCRATCH_MNT
+SCRATCH_DEV SCRATCH_MNT
+
+
+DEV2 MNT2 FSUUID
+DEV2 MNT2
+DEV2 MNT2
+
+**** mount cycle ****
+
+SCRATCH_DEV SCRATCH_MNT FSUUID
+SCRATCH_DEV SCRATCH_MNT
+SCRATCH_DEV SCRATCH_MNT
+
+
+DEV2 MNT2 FSUUID
+DEV2 MNT2
+DEV2 MNT2
+
Signature · 1 line
2.43.0
author
#17 lore raw

PATCH 8/9 fstests: verify IMA isolation on cloned filesystems

In reply to Anand Jain

Add testcase to verify IMA measurement isolation when multiple devices share the same FSUUID.

---
 tests/generic/794     | 101 ++++++++++++++++++++++++++++++++++++++++++
 tests/generic/794.out |  10 +++++
 2 files changed, 111 insertions(+)
 create mode 100644 tests/generic/794
 create mode 100644 tests/generic/794.out
tests/generic/794 new file +101 -0
new file mode 100644
index 000000000000..e3bf3f9c6a7e
@@ -0,0 +1,101 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2026 Anand Jain <[email protected]>.  All Rights Reserved.
+#
+# FS QA Test 794
+# Verify IMA isolation on cloned filesystems:
+# . Mount two devices sharing the same FSUUID (cloned).
+# . Apply an IMA policy to measure files based on that FSUUID.
+# . Create unique files on each mount point to trigger measurements.
+# . Confirm the IMA log correctly attributes events to the respective mounts.
+
+. ./common/preamble
+. ./common/filter
+
+_begin_fstest auto quick clone
+
+_require_test
+_require_scratch_dev_pool 2
+
+[ "$FSTYP" = "btrfs" ] && _fixed_by_kernel_commit xxxxxxxxxxxx \
+	"btrfs: use on-disk uuid for s_uuid in temp_fsid mounts"
+[ "$FSTYP" = "btrfs" ] && _fixed_by_kernel_commit xxxxxxxxxxxx \
+	"btrfs: derive f_fsid from on-disk fsuuid and dev_t"
+
+_cleanup()
+{
+	cd /
+	rm -r -f $tmp.*
+	umount $mnt2 2>/dev/null
+	_scratch_dev_pool_put
+}
+
+filter_pool()
+{
+	_filter_scratch | \
+		sed -e "s|${devs[1]}|DEV2|g" \
+		    -e "s|$mnt2|MNT2|g" | \
+		_filter_spaces
+}
+
+do_ima()
+{
+	local ima_policy="/sys/kernel/security/ima/policy"
+	local ima_log="/sys/kernel/security/ima/ascii_runtime_measurements"
+	local fsuuid
+	local mnt=$1
+	local run_enable=$2
+
+	# Since the in-memory IMA audit log is only cleared upon reboot,
+	# use unique random filenames to avoid log collisions.
+	local foofile=$(mktemp --dry-run foobar_XXXXX)
+
+	echo $mnt $run_enable | filter_pool
+
+	[ -w "$ima_policy" ] || _notrun "IMA policy not writable"
+
+	fsuuid=$(blkid -s UUID -o value $SCRATCH_DEV)
+
+	# Load IMA policy to measure file access specifically for this
+	# filesystem UUID.
+	if [[ $run_enable -eq 1 ]]; then
+		echo "measure func=FILE_CHECK fsuuid=$fsuuid" > "$ima_policy" || \
+			_notrun "Policy rejected"
+	fi
+
+	# Create a file to trigger measurement and verify its entry in
+	# the IMA log.
+	echo "test_data" > $mnt/$foofile
+
+	# For $ima_log column entry please ref to
+	grep $foofile "$ima_log" | awk '{ print $5 }' | filter_pool | \
+						sed "s/$foofile/FOOBAR_FILE/"
+
+	echo "dbg: $mnt $fsuuid $foofile" >> $seqres.full
+	cat $ima_log | tail -1 >> $seqres.full
+	echo >> $seqres.full
+}
+
+_scratch_dev_pool_get 2
+_scratch_mkfs_sized_clone >$seqres.full 2>&1
+devs=($SCRATCH_DEV_POOL)
+mnt2=$TEST_DIR/mnt2
+mkdir -p $mnt2
+
+_scratch_mount $(_clone_mount_option)
+_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[1]} $mnt2 || \
+						_fail "Failed to mount dev2"
+
+do_ima $SCRATCH_MNT 1
+do_ima $mnt2 0
+
+# Btrfs uses in-memory dynamic temp_fsid
+echo mount cycle
+_unmount $mnt2
+_mount $mount_opts ${devs[1]} $mnt2 || _fail "Failed to mount dev2"
+
+do_ima $SCRATCH_MNT 0
+do_ima $mnt2 0
+
+status=0
+exit
tests/generic/794.out new file +10 -0
new file mode 100644
index 000000000000..026b365853e6
@@ -0,0 +1,10 @@
+QA output created by 794
+SCRATCH_MNT 1
+SCRATCH_MNT/FOOBAR_FILE
+MNT2 0
+MNT2/FOOBAR_FILE
+mount cycle
+SCRATCH_MNT 0
+SCRATCH_MNT/FOOBAR_FILE
+MNT2 0
+MNT2/FOOBAR_FILE
Signature · 1 line
2.43.0
author
#18 lore raw

PATCH 9/9 fstests: verify exportfs file handles on cloned filesystems

In reply to Anand Jain

Ensure that exportfs can correctly decode file handles on a cloned filesystem across a mount cycle, by file handles generated on a cloned device remain valid after mount cycle.

---
 tests/generic/795     | 67 +++++++++++++++++++++++++++++++++++++++++++
 tests/generic/795.out |  2 ++
 2 files changed, 69 insertions(+)
 create mode 100644 tests/generic/795
 create mode 100644 tests/generic/795.out
tests/generic/795 new file +67 -0
new file mode 100644
index 000000000000..b6a75e500949
@@ -0,0 +1,67 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2026 Anand Jain <[email protected]>.  All Rights Reserved.
+#
+# FS QA Test No. 795
+
+. ./common/preamble
+
+_begin_fstest auto quick exportfs clone
+
+_require_test
+_require_exportfs
+_require_scratch_dev_pool 2
+_require_test_program "open_by_handle"
+
+_cleanup()
+{
+	cd /
+	rm -r -f $tmp.*
+	_unmount $mnt2 2>/dev/null
+	_scratch_dev_pool_put
+}
+
+# Create test dir and test files, encode file handles and store to tmp file
+create_test_files()
+{
+	rm -rf $testdir
+	mkdir -p $testdir
+	$here/src/open_by_handle -cwp -o $tmp.handles_file $testdir $NUMFILES
+}
+
+# Decode file handles loaded from tmp file
+test_file_handles()
+{
+	local opt=$1
+	local when=$2
+
+	echo test_file_handles after $when
+	$here/src/open_by_handle $opt -i $tmp.handles_file $mnt2 $NUMFILES
+}
+
+_scratch_dev_pool_get 2
+_scratch_mkfs_sized_clone >$seqres.full 2>&1
+devs=($SCRATCH_DEV_POOL)
+mnt2=$TEST_DIR/mnt2
+mkdir -p $mnt2
+
+_scratch_mount $(_clone_mount_option)
+_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[1]} $mnt2 || \
+						_fail "Failed to mount dev2"
+
+NUMFILES=1
+testdir=$mnt2/testdir
+
+# Decode file handles of files/dir after cycle mount
+create_test_files
+
+_scratch_unmount
+_unmount $mnt2
+_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[1]} $mnt2 || \
+						_fail "Failed to mount dev2"
+_scratch_mount $(_clone_mount_option)
+
+test_file_handles -rp "cycle mount"
+
+status=0
+exit
tests/generic/795.out new file +2 -0
new file mode 100644
index 000000000000..774fe7487d65
@@ -0,0 +1,2 @@
+QA output created by 795
+test_file_handles after cycle mount
Signature · 1 line
2.43.0