fstests: add test coverage for cloned filesystem ids
v5 cover fstests: add test coverage for cloned filesystem ids
v5:
XFS supports metadata_uuid, I converted patch 10/10 to a generic
test. To do this, I moved the in-test helper to common/rc as pre_clone_tune_uuid().
I also verified fanotifywait with SELinux in enforcing mode and
fixed patch 4/10.
v4:
https://lore.kernel.org/fstests/[email protected]
v3:
https://lore.kernel.org/fstests/[email protected]
v2:
https://lore.kernel.org/fstests/[email protected]
v1:
https://lore.kernel.org/fstests/[email protected]
This series adds fstests infrastructure and test cases to verify correct filesystem identity when a filesystem is cloned (block-level copy). Test covers inotify, fanotify, f_fsid, libblkid, IMA, exportfs file handles and libblkid tools verify with metadata_uuid.
New helpers:
- _mkfs_scratch_sized_clone() helper to create a cloned filesystem
- _clone_mount_option() helper to apply per-filesystem clone mount options
- pre_clone_tune_uuid() changes the UUID before the clone
New tests:
- 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 with and without metadata_uuid
- IMA distinct identity for each cloned filesystem
- exportfs file handles resolve correctly on cloned filesystems
Kernel Patches:
Requires Btrfs kernel patches for all tests to pass.
[1] https://lore.kernel.org/linux-btrfs/[email protected]
Anand Jain (10):
fstests: add _loop_image_create_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
fstests: add pre_clone_tune_uuid() healper
fstests: test UUID consistency for clones with metadata_uuid
common/config | 2 + common/rc | 84 ++++++++++++++++++++++++++++ tests/generic/800 | 89 ++++++++++++++++++++++++++++++ tests/generic/800.out | 7 +++ tests/generic/801 | 125 ++++++++++++++++++++++++++++++++++++++++++ tests/generic/801.out | 7 +++ tests/generic/802 | 62 +++++++++++++++++++++ tests/generic/802.out | 7 +++ tests/generic/803 | 76 +++++++++++++++++++++++++ tests/generic/803.out | 19 +++++++ tests/generic/804 | 103 ++++++++++++++++++++++++++++++++++ tests/generic/804.out | 10 ++++ tests/generic/805 | 73 ++++++++++++++++++++++++ tests/generic/805.out | 2 + tests/generic/806 | 78 ++++++++++++++++++++++++++ tests/generic/806.out | 19 +++++++ 16 files changed, 763 insertions(+) create mode 100644 tests/generic/800 create mode 100644 tests/generic/800.out create mode 100644 tests/generic/801 create mode 100644 tests/generic/801.out create mode 100644 tests/generic/802 create mode 100644 tests/generic/802.out create mode 100644 tests/generic/803 create mode 100644 tests/generic/803.out create mode 100644 tests/generic/804 create mode 100644 tests/generic/804.out create mode 100644 tests/generic/805 create mode 100644 tests/generic/805.out create mode 100644 tests/generic/806 create mode 100644 tests/generic/806.out
Signature · 1 line
2.43.0
PATCH v5 1/10 fstests: add _loop_image_create_clone() helper
Introduce _loop_image_create_clone() and _loop_image_destroy() to mkfs an image file and clone it to another image file, and attach a loop device to them. And its destroy part.
--- common/rc | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+)
common/rc +50 -0
@@ -1503,6 +1503,56 @@ _scratch_resvblks() esac } +_loop_image_create_clone() +{ + local -n _ret=$1 + local pre_clone_tune_func="$2" + local img_file=$TEST_DIR/${seq}.img + local img_file_clone=$TEST_DIR/${seq}_clone.img + local size=$(_small_fs_size_mb 128) # Smallest possible + local loop_devs + + _require_fs_space $TEST_DIR $((size * 1024)) + + _create_file_sized $((size * 1024 * 1024)) $img_file || + _fail "Failed: Create $img_file $size" + + loop_devs=$(_create_loop_device $img_file) + _ret=($loop_devs) + + case $FSTYP in + xfs) + _mkfs_dev "-s size=4096" ${loop_devs[0]} + ;; + btrfs) + _mkfs_dev ${loop_devs[0]} + ;; + *) + _mkfs_dev ${loop_devs[0]} + ;; + esac + + # Only execute if the function argument is not empty + if [ -n "$pre_clone_tune_func" ]; then + $pre_clone_tune_func ${loop_devs[0]} + fi + + sync ${loop_devs[0]} + cp $img_file $img_file_clone + + loop_devs="$loop_devs $(_create_loop_device $img_file_clone)" + + _ret=($loop_devs) +} + +_loop_image_destroy() +{ + for d in "$@"; do + local f=$(losetup --noheadings --output BACK-FILE $d) + _destroy_loop_device "$d" + [ -n "$f" ] && rm -f "$f" + done +} # 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
PATCH v5 2/10 fstests: add _clone_mount_option() helper
In reply to Anand JainAdds _clone_mount_option() helper function to handle filesystem-specific requirements for mounting cloned devices. Abstract the need for -o nouuid on XFS.
--- common/rc | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
common/rc +14 -0
@@ -397,6 +397,20 @@ _scratch_mount_options() $SCRATCH_DEV $SCRATCH_MNT } +_clone_mount_option() +{ + local mount_opts="" + + case "$FSTYP" in + xfs) + mount_opts="-o nouuid" + ;; + *) + esac + + echo $mount_opts +} + _supports_filetype() { local dir=$1
Signature · 1 line
2.43.0
PATCH v5 3/10 fstests: add test for inotify isolation on cloned devices
In reply to Anand JainAdd a new test, to verify that the kernel correctly differentiates between two block devices sharing the same FSID/UUID.
--- common/config | 1 + tests/generic/800 | 89 +++++++++++++++++++++++++++++++++++++++++++ tests/generic/800.out | 7 ++++ 3 files changed, 97 insertions(+) create mode 100644 tests/generic/800 create mode 100644 tests/generic/800.out
common/config +1 -0
@@ -242,6 +242,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/800 new file +89 -0
89 lines not on this page · raw message
tests/generic/800.out new file +7 -0
@@ -0,0 +1,7 @@ +QA output created by 800 +Setup inotify watchers on both mnt1 and mnt2 +Trigger file creation on mnt1 +Trigger file creation on mnt2 +Verify inotify isolation +SUCCESS: mnt1 events isolated. +SUCCESS: mnt2 events isolated.
Signature · 1 line
2.43.0
PATCH v5 4/10 fstests: verify fanotify isolation on cloned filesystems
In reply to Anand JainVerify 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.
--- common/config | 1 + tests/generic/801 | 125 ++++++++++++++++++++++++++++++++++++++++++ tests/generic/801.out | 7 +++ 3 files changed, 133 insertions(+) create mode 100644 tests/generic/801 create mode 100644 tests/generic/801.out
common/config +1 -0
@@ -243,6 +243,7 @@ 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)" +export FSNOTIFYWAIT_PROG="$(type -P fsnotifywait)" # udev wait functions. #
tests/generic/801 new file +125 -0
125 lines not on this page · raw message
tests/generic/801.out new file +7 -0
@@ -0,0 +1,7 @@ +QA output created by 801 +Setup FID fanotify watchers on both mnt1 and mnt2 +Trigger file creation on mnt1 +Trigger file creation on mnt2 +Verify fsid in the fanotify +SUCCESS: mnt1 events found +SUCCESS: mnt2 events found
Signature · 1 line
2.43.0
PATCH v5 5/10 fstests: verify f_fsid for cloned filesystems
In reply to Anand JainVerify 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/802 | 62 +++++++++++++++++++++++++++++++++++++++++++ tests/generic/802.out | 7 +++++ 2 files changed, 69 insertions(+) create mode 100644 tests/generic/802 create mode 100644 tests/generic/802.out
tests/generic/802 new file +62 -0
@@ -0,0 +1,62 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2026 Anand Jain <[email protected]>. All Rights Reserved. +# +# FS QA Test 802 +# Verify f_fsid and s_uuid of cloned filesystems across mount cycle. + +. ./common/preamble + +_begin_fstest auto quick mount clone + +_require_test +_require_block_device $TEST_DEV +_require_loop + +[ "$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 $mnt1 $mnt2 2>/dev/null + _loop_image_destroy "${devs[@]}" 2> /dev/null +} + +devs=() +_loop_image_create_clone devs +mkdir -p $TEST_DIR/$seq +mnt1=$TEST_DIR/$seq/mnt1 +mnt2=$TEST_DIR/$seq/mnt2 +mkdir -p $mnt1 +mkdir -p $mnt2 + +_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[0]} $mnt1 || \ + _fail "Failed to mount dev1" +_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[1]} $mnt2 || \ + _fail "Failed to mount dev2" + +fsid_scratch=$(stat -f -c "%i" $mnt1) +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 ****" +_unmount $mnt1 +_unmount $mnt2 +_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[1]} $mnt2 || \ + _fail "Failed to mount dev2" +_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[0]} $mnt1 || \ + _fail "Failed to mount dev1" + +stat -f -c "%i" $mnt1 | 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/802.out new file +7 -0
@@ -0,0 +1,7 @@ +QA output created by 802 +**** fsid initially **** +FSID_SCRATCH +FSID_CLONE +**** fsid after mount cycle **** +FSID_SCRATCH +FSID_CLONE
Signature · 1 line
2.43.0
PATCH v5 6/10 fstests: verify libblkid resolution of duplicate UUIDs
In reply to Anand JainVerify how findmnt, df (libblkid) resolve device paths when multiple block devices share the same FSUUID.
--- tests/generic/803 | 76 +++++++++++++++++++++++++++++++++++++++++++ tests/generic/803.out | 19 +++++++++++ 2 files changed, 95 insertions(+) create mode 100644 tests/generic/803 create mode 100644 tests/generic/803.out
tests/generic/803 new file +76 -0
@@ -0,0 +1,76 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2026 Anand Jain <[email protected]>. All Rights Reserved. +# +# FS QA Test 803 +# 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_block_device $TEST_DEV +_require_loop + +_cleanup() +{ + cd / + rm -r -f $tmp.* + umount $mnt1 $mnt2 2>/dev/null + _loop_image_destroy "${devs[@]}" 2> /dev/null +} + +filter_pool() +{ + sed -e "s|${devs[0]}|DEV1|g" -e "s|${mnt1}|MNT1|g" \ + -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 +} + +devs=() +_loop_image_create_clone devs +mkdir -p $TEST_DIR/$seq +mnt1=$TEST_DIR/$seq/mnt1 +mnt2=$TEST_DIR/$seq/mnt2 +mkdir -p $mnt1 +mkdir -p $mnt2 + +_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[0]} $mnt1 || \ + _fail "Failed to mount dev1" +_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[1]} $mnt2 || \ + _fail "Failed to mount dev2" + +print_info $mnt1 +print_info $mnt2 + +echo +echo "**** mount cycle ****" +_unmount $mnt1 +_unmount $mnt2 +_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[1]} $mnt2 || \ + _fail "Failed to mount dev2" +_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[0]} $mnt1 || \ + _fail "Failed to mount dev1" + +print_info $mnt1 +print_info $mnt2 + +status=0 +exit
tests/generic/803.out new file +19 -0
@@ -0,0 +1,19 @@ +QA output created by 803 + +DEV1 MNT1 FSUUID +DEV1 MNT1 +DEV1 MNT1 + +DEV2 MNT2 FSUUID +DEV2 MNT2 +DEV2 MNT2 + +**** mount cycle **** + +DEV1 MNT1 FSUUID +DEV1 MNT1 +DEV1 MNT1 + +DEV2 MNT2 FSUUID +DEV2 MNT2 +DEV2 MNT2
Signature · 1 line
2.43.0
PATCH v5 7/10 fstests: verify IMA isolation on cloned filesystems
In reply to Anand JainAdd testcase to verify IMA measurement isolation when multiple devices share the same FSUUID.
--- tests/generic/804 | 103 ++++++++++++++++++++++++++++++++++++++++++ tests/generic/804.out | 10 ++++ 2 files changed, 113 insertions(+) create mode 100644 tests/generic/804 create mode 100644 tests/generic/804.out
tests/generic/804 new file +103 -0
@@ -0,0 +1,103 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2026 Anand Jain <[email protected]>. All Rights Reserved. +# +# FS QA Test 804 +# 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_block_device $TEST_DEV +_require_loop + +[ "$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.* + _unmount $mnt1 2>/dev/null + _unmount $mnt2 2>/dev/null + _loop_image_destroy "${devs[@]}" 2> /dev/null +} + +filter_pool() +{ + sed -e "s|${devs[0]}|DEV1|g" -e "s|$mnt1|MNT1|g" \ + -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 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 $enable | filter_pool + + [ -w "$ima_policy" ] || _notrun "IMA policy not writable" + + fsuuid=$(blkid -s UUID -o value ${devs[0]}) + + # Load IMA policy to measure file access specifically for this + # filesystem UUID. + if [[ $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 +} + +devs=() +_loop_image_create_clone devs +mnt1=$TEST_DIR/$seq/mnt1 +mnt2=$TEST_DIR/$seq/mnt2 +mkdir -p $mnt1 +mkdir -p $mnt2 + +_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[0]} $mnt1 || \ + _fail "Failed to mount dev1" +_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[1]} $mnt2 || \ + _fail "Failed to mount dev2" + +do_ima $mnt1 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 $mnt1 0 +do_ima $mnt2 0 + +status=0 +exit
tests/generic/804.out new file +10 -0
@@ -0,0 +1,10 @@ +QA output created by 804 +MNT1 1 +MNT1/FOOBAR_FILE +MNT2 0 +MNT2/FOOBAR_FILE +mount cycle +MNT1 0 +MNT1/FOOBAR_FILE +MNT2 0 +MNT2/FOOBAR_FILE
Signature · 1 line
2.43.0
PATCH v5 8/10 fstests: verify exportfs file handles on cloned filesystems
In reply to Anand JainEnsure 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/805 | 73 +++++++++++++++++++++++++++++++++++++++++++ tests/generic/805.out | 2 ++ 2 files changed, 75 insertions(+) create mode 100644 tests/generic/805 create mode 100644 tests/generic/805.out
tests/generic/805 new file +73 -0
@@ -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 No. 805 + +. ./common/preamble + +_begin_fstest auto quick exportfs clone + +_require_test +_require_block_device $TEST_DEV +_require_exportfs +_require_loop +_require_test_program "open_by_handle" + +_cleanup() +{ + cd / + rm -r -f $tmp.* + _unmount $mnt1 2>/dev/null + _unmount $mnt2 2>/dev/null + _loop_image_destroy "${devs[@]}" 2> /dev/null +} + +# 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 +} + +devs=() +_loop_image_create_clone devs +mkdir -p $TEST_DIR/$seq +mnt1=$TEST_DIR/$seq/mnt1 +mnt2=$TEST_DIR/$seq/mnt2 +mkdir -p $mnt1 +mkdir -p $mnt2 + +_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[0]} $mnt1 || \ + _fail "Failed to mount dev1" +_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 + +_unmount $mnt1 +_unmount $mnt2 +_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[1]} $mnt2 || \ + _fail "Failed to mount dev2" +_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[0]} $mnt1 || \ + _fail "Failed to mount dev1" + +test_file_handles -rp "cycle mount" + +status=0 +exit
tests/generic/805.out new file +2 -0
@@ -0,0 +1,2 @@ +QA output created by 805 +test_file_handles after cycle mount
Signature · 1 line
2.43.0
PATCH v5 9/10 fstests: add pre_clone_tune_uuid() healper
In reply to Anand Jainpre_clone_tune_uuid() changes the UUID of the golden filesystem before it is cloned.
--- common/rc | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
common/rc +20 -0
@@ -1517,6 +1517,26 @@ _scratch_resvblks() esac } +pre_clone_tune_uuid() +{ + local temp_mnt=$TEST_DIR/${seq}_mnt + local dev=$1 + + case $FSTYP in + xfs) + _require_command "$XFS_ADMIN_PROG" "xfs_admin" + $XFS_ADMIN_PROG -U generate $dev >> $seqres.full + ;; + btrfs) + _require_command "$BTRFS_TUNE_PROG" "btrfstune" + $BTRFS_TUNE_PROG -m $dev + ;; + *) + _notrun "Require filesystem with metadata_uuid feature" + ;; + esac +} + _loop_image_create_clone() { local -n _ret=$1
Signature · 1 line
2.43.0
PATCH v5 10/10 fstests: test UUID consistency for clones with metadata_uuid
In reply to Anand JainBtrfs and xfs uses the metadata_uuid superblock feature to change the on-disk UUID without rewriting every block header. This patch adds a sanity check to ensure UUID consistency when a filesystem with metadata_uuid enabled is cloned.
--- tests/generic/806 | 78 +++++++++++++++++++++++++++++++++++++++++++ tests/generic/806.out | 19 +++++++++++ 2 files changed, 97 insertions(+) create mode 100644 tests/generic/806 create mode 100644 tests/generic/806.out
tests/generic/806 new file +78 -0
@@ -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 806 +# +# Verify that the cloned filesystem UUID remains consistent, even when the +# `metadata_uuid` feature is enabled. +# + +. ./common/preamble +. ./common/filter + +_begin_fstest auto quick mount clone + +_require_test +_require_block_device $TEST_DEV +_require_loop + +_cleanup() +{ + cd / + rm -r -f $tmp.* + umount $mnt1 $mnt2 2>/dev/null + _loop_image_destroy "${devs[@]}" 2> /dev/null +} + +filter_pool() +{ + sed -e "s|${devs[0]}|DEV1|g" -e "s|${mnt1}|MNT1|g" \ + -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 +} + +devs=() +_loop_image_create_clone devs pre_clone_tune_uuid +mkdir -p $TEST_DIR/$seq +mnt1=$TEST_DIR/$seq/mnt1 +mnt2=$TEST_DIR/$seq/mnt2 +mkdir -p $mnt1 +mkdir -p $mnt2 + +_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[0]} $mnt1 || \ + _fail "Failed to mount dev1" +_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[1]} $mnt2 || \ + _fail "Failed to mount dev2" + +print_info $mnt1 +print_info $mnt2 + +echo +echo "**** mount cycle ****" +_unmount $mnt1 +_unmount $mnt2 +_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[1]} $mnt2 || \ + _fail "Failed to mount dev2" +_mount $(_common_dev_mount_options) $(_clone_mount_option) ${devs[0]} $mnt1 || \ + _fail "Failed to mount dev1" + +print_info $mnt1 +print_info $mnt2 + +status=0 +exit
tests/generic/806.out new file +19 -0
@@ -0,0 +1,19 @@ +QA output created by 806 + +DEV1 MNT1 FSUUID +DEV1 MNT1 +DEV1 MNT1 + +DEV2 MNT2 FSUUID +DEV2 MNT2 +DEV2 MNT2 + +**** mount cycle **** + +DEV1 MNT1 FSUUID +DEV1 MNT1 +DEV1 MNT1 + +DEV2 MNT2 FSUUID +DEV2 MNT2 +DEV2 MNT2
Signature · 1 line
2.43.0
Re: [PATCH v5 09/10] fstests: add pre_clone_tune_uuid() healper
In reply to Anand JainQuoted 13 lines · Anand Jain
pre_clone_tune_uuid()changes the UUID of the golden filesystem before it is cloned.Signed-off-by Anand Jain <[email protected]>--- common/rc | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)common/rc +0
-0
common/rc _scratch_resvblks() · line 1520
Quoted 4 lines
common/rc +1
-0@@ -1517,6 +1517,26 @@ _scratch_resvblks() esac } +pre_clone_tune_uuid()
I missed the "_" prefix for pre_clone_tune_uuid() to match the common/rc style.
Zorro,
If there are no other rerolls, can you please fix it at merge or should I resend?
Thanks
Quoted 22 lines
common/rc +19
-0+{ + local temp_mnt=$TEST_DIR/${seq}_mnt + local dev=$1 + + case $FSTYP in + xfs) + _require_command "$XFS_ADMIN_PROG" "xfs_admin" + $XFS_ADMIN_PROG -U generate $dev >> $seqres.full + ;; + btrfs) + _require_command "$BTRFS_TUNE_PROG" "btrfstune" + $BTRFS_TUNE_PROG -m $dev + ;; + *) + _notrun "Require filesystem with metadata_uuid feature" + ;; + esac +} + _loop_image_create_clone() { local -n _ret=$1
Re: [PATCH v5 01/10] fstests: add _loop_image_create_clone() helper
In reply to Anand JainQuoted 14 lines · Anand Jain
Introduce
_loop_image_create_clone()and_loop_image_destroy()to mkfs an image file and clone it to another image file, and attach a loop device to them. And its destroy part.Signed-off-by Anand Jain <[email protected]>--- common/rc | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+)common/rc +0
-0
common/rc _scratch_resvblks() · line 1507
Quoted 5 lines
common/rc +2
-0@@ -1503,6 +1503,56 @@ _scratch_resvblks() esac } +_loop_image_create_clone() +{
Please add a comment explaining the function and how to use it.
common/rc _scratch_resvblks() · line 1549
Quoted 2 lines
common/rc +2
-0+_loop_image_destroy() +{
Same.
Re: [PATCH v5 02/10] fstests: add _clone_mount_option() helper
In reply to Anand JainQuoted 14 lines · 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.Signed-off-by Anand Jain <[email protected]>--- common/rc | 14 ++++++++++++++ 1 file changed, 14 insertions(+)common/rc +0
-0
common/rc _scratch_mount_options() · line 401
Quoted 5 lines
common/rc +2
-0@@ -397,6 +397,20 @@ _scratch_mount_options() $SCRATCH_DEV $SCRATCH_MNT } +_clone_mount_option() +{
Comment please.
Re: [PATCH v5 03/10] fstests: add test for inotify isolation on cloned devices
In reply to Anand Jaincommon/config export BTRFS_MAP_LOGICAL_PROG=$(type -P btrfs-map-logical) · line 245
Quoted 9 lines
common/config +1
-0@@ -242,6 +242,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)"
Usually we try to split infrastructure changes like this out into separate patches.
Also any reason to rely on the obsolete inotify instead of fsnotify?
Re: [PATCH v5 04/10] fstests: verify fanotify isolation on cloned filesystems
In reply to Anand JainQuoted 1 line
+export FSNOTIFYWAIT_PROG="$(type -P fsnotifywait)"
Same comment about adding new common bits outside of test cases applies, but why use both inotify and fsnotify?
tests/generic/801 line 66
Quoted 2 lines
+[[ "$fsid1" == "$fsid2" ]] && \
tests/generic/801 new file +1
-0+ _notrun "Require clone filesystem with unique f_fsid"
Please add a comment why this happens. I also have to say I find the if syntax easier to follow then && with a line continuation.
Re: [PATCH v5 05/10] fstests: verify f_fsid for cloned filesystems
In reply to Anand Jaintests/generic/802 line 19
Quoted 4 lines · Anand Jain
+[ "$FSTYP" = "btrfs" ] &&
_fixed_by_kernel_commitxxxxxxxxxxxx \tests/generic/802 new file +3
-0+ "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"
Seems like these are stuck on the btrfs list. Any progress on that?
Re: [PATCH v5 09/10] fstests: add pre_clone_tune_uuid() healper
In reply to Anand JainQuoted 5 lines · Anand Jain
Quoted 1 line
+pre_clone_tune_uuid()
I missed the "_" prefix for
pre_clone_tune_uuid()to match the common/rc style.
and a comment explaining the helper. Also I think it should be named to describe what it does, not what you use for, i.e. something about changing the metadata uuid.
Re: [PATCH v5 09/10] fstests: add pre_clone_tune_uuid() healper
Quoted 11 lines · Christoph Hellwig
Quoted 5 lines · Anand Jain
Quoted 1 line
+pre_clone_tune_uuid()
I missed the "_" prefix for
pre_clone_tune_uuid()to match the common/rc style.and a comment explaining the helper. Also I think it should be named to describe what it does, not what you use for, i.e. something about changing the metadata uuid.
Agreed. I'll update it. Is _change_metadata_uuid() a better name?
Re: [PATCH v5 09/10] fstests: add pre_clone_tune_uuid() healper
Quoted 6 lines · Anand Jain
Quoted 4 lines
and a comment explaining the helper. Also I think it should be named to describe what it does, not what you use for, i.e. something about changing the metadata uuid.
Agreed. I'll update it. Is
_change_metadata_uuid()a better name?
Sounds better to me at least.
Re: [PATCH v5 04/10] fstests: verify fanotify isolation on cloned filesystems
In reply to Christoph HellwigQuoted 3 lines · Christoph Hellwig
Quoted 1 line
+export FSNOTIFYWAIT_PROG="$(type -P fsnotifywait)"
Same comment about adding new common bits outside of test cases applies,
Got it.
Quoted 2 lines
but why use both inotify and fsnotify?
The SYSCALL and stuffs until fsnotify_..() are different, so I decided to keep them both.
Quoted 5 lines
tests/generic/801 line 66
Quoted 2 lines
+[[ "$fsid1" == "$fsid2" ]] && \
tests/generic/801 new file +1
-0+ _notrun "Require clone filesystem with unique f_fsid"Please add a comment why this happens. I also have to say I find the if syntax easier to follow then && with a line continuation.
Got it. If statements are better for readability.
Also, I'll add comments.
Re: [PATCH v5 03/10] fstests: add test for inotify isolation on cloned devices
In reply to Christoph HellwigQuoted 4 lines · Christoph Hellwig
Quoted 4 lines
common/config +0
-0
Quoted 8 lines
common/config export BTRFS_MAP_LOGICAL_PROG=$(type -P btrfs-map-logical) · line 245
Quoted 5 lines
common/config +1
-0@@ -242,6 +242,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)"Usually we try to split infrastructure changes like this out into separate patches.
Right. I'll split it into a separate patch.
Quoted 1 line
Also any reason to rely on the obsolete inotify instead of fsnotify?
fsnotify is exercised in patch 4/10.
IMO, exercising inotify ensures we don't break legacy stuff.
In general, is it fine to keep obsolete command/testcase from an LTS kernel perspective? We did that a couple of times before.
Re: [PATCH v5 03/10] fstests: add test for inotify isolation on cloned devices
Quoted 4 lines · Anand Jain
Quoted 1 line
Also any reason to rely on the obsolete inotify instead of fsnotify?
fsnotify is exercised in patch 4/10.
IMO, exercising inotify ensures we don't break legacy stuff.
fanotity and inotify use exactly the same backends, so I'm not sure why testing both matters. Not that I care very strongly, I'm just a bit confused.
Re: [PATCH v5 03/10] fstests: add test for inotify isolation on cloned devices
Quoted 8 lines · Christoph Hellwig
Quoted 4 lines · Anand Jain
Quoted 1 line
Also any reason to rely on the obsolete inotify instead of fsnotify?
fsnotify is exercised in patch 4/10.
IMO, exercising inotify ensures we don't break legacy stuff.fanotity and inotify use exactly the same backends, so I'm not sure why testing both matters.
I noticed that back then I decided to keep both. Since fsnotifywait -F is only supported from kernel 5.1x. inotifywait serves the legacy LTS kernels where required.
Quoted 2 lines
Not that I care very strongly, I'm just a
bit confused.
I am happy dropping inotifywait if unnecessary and confusing.
Thanks.
Re: [PATCH v5 03/10] fstests: add test for inotify isolation on cloned devices
Quoted 6 lines · Anand Jain
Quoted 2 lines
fanotity and inotify use exactly the same backends, so I'm not sure why testing both matters.
I noticed that back then I decided to keep both. Since fsnotifywait -F is only supported from kernel 5.1x. inotifywait serves the legacy LTS kernels where required.
< 5.1x is pretty old these days, I would not add test just for that.
Quoted 4 lines
Quoted 2 lines
Not that I care very strongly, I'm just a
bit confused.I am happy dropping inotifywait if unnecessary and confusing.
Not a major issue, but it felt weird.
Re: [PATCH v5 03/10] fstests: add test for inotify isolation on cloned devices
Quoted 8 lines · Christoph Hellwig
Quoted 6 lines · Anand Jain
Quoted 2 lines
fanotity and inotify use exactly the same backends, so I'm not sure why testing both matters.
I noticed that back then I decided to keep both. Since fsnotifywait -F is only supported from kernel 5.1x. inotifywait serves the legacy LTS kernels where required.
Quoted 9 lines
< 5.1x is pretty old these days, I would not add test just for that.
Quoted 4 lines
Quoted 2 lines
Not that I care very strongly, I'm just a
bit confused.I am happy dropping inotifywait if unnecessary and confusing.
Not a major issue, but it felt weird.
Okay, dropping the inotifywait test case in the reroll.
Thanks.
Re: [PATCH v5 05/10] fstests: verify f_fsid for cloned filesystems
In reply to Christoph HellwigQuoted 7 lines · Christoph Hellwig
tests/generic/802 line 19
Quoted 4 lines · Anand Jain
+[ "$FSTYP" = "btrfs" ] &&
_fixed_by_kernel_commitxxxxxxxxxxxx \tests/generic/802 new file +3
-0+ "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"Seems like these are stuck on the btrfs list. Any progress on that?
They are in the for-next branch of the Btrfs Linux repository:
https://github.com/btrfs/linux.git