fstests: tests for cloned filesystem validation and f_fsid
cover fstests: tests for cloned filesystem validation and f_fsid
This series continues the work from the earlier "test coverage for cloned filesystem ids" series (last posted as v8 [1]) and has been tested against the major filesystems: Btrfs, XFS, ext4, and f2fs.
Although this version incorporates the review feedback received on v8, it expands substantially with additional infrastructure helpers, an extra test case to cover the recent regression report, and migration/cleanup of existing generic/744. Because the patch count grew from 13 to 21 patches, disrupting the previous patch numbering and scope, I have reset the versioning and updated the subject line to better reflect the broader validation coverage.
The core motivation remains identical: testing that mounting a block-level cloned filesystem concurrently with the original filesystem behaves correctly across filesystems and VFS subsystems (fanotify, statfs/f_fsid, libblkid resolution, IMA measurement, exportfs file handles, and metadata_uuid handling).
Summary of major changes since v8:
- Added 1 new regression test case to verify statfs f_fsid derivation against FS UUID.
- Dropped the test case verifying f_fsid persistence across mount cycles on cloned filesystems, as this assumption is no longer valid following the Btrfs kernel regression fix [2].
- Introduced common helpers:
. _require_security_ima() and _require_metadata_uuid().
. _scratch_mkfs_uuid() and helpers for f_fsid verification.
- Migrated generic/744 to utilize the new common clone helpers.
- Worked on the review comments.
Details of changes:
- _create_cloned_loop_devs():
. Renamed from _loop_image_create_clone() to _create_cloned_loop_devs(). . Relocated backing image files from "$TEST_DIR/${seq}.*" to a dedicated
directory "$TEST_DIR/${seq}/*". . Added internal call to _require_clone_mount().
. Switched from _create_loop_device() to _create_loop_device_like_bdev()
to guarantee identical logical/physical sector sizes (512 vs 4096) between the original and cloned loop devices.
. Used an intermediate local setup step to ensure consistent Direct I/O
attributes across both loop devices (preventing the first device from enabling DIO while the cloned device fell back to buffered mode).
. Added device geometry and DIO attribute dump to $seqres.full for debugging. . Renamed teardown helper _loop_image_destroy() to _destroy_cloned_loop_devs().
- _clone_mount_options():
. Renamed from _clone_mount_option() to _clone_mount_options().
- _require_metadata_uuid():
. Factored out prerequisite checks from _change_metadata_uuid() into a new
dedicated helper _require_metadata_uuid() and invoked it accordingly.
- _require_clone_mount():
. Introduced new helper to check kernel support for concurrent clone mounts. . Removed obsolete _require_duplicate_fsid() in favor of _require_clone_mount().
- _require_security_ima():
. Introduced new helper to check securityfs and IMA policy availability.
- _create_loop_device_like_bdev():
. Removed unused local variable 'dev'.
- Test Cases common update:
- Adjusted test groups: replaced 'clone' with 'tempfsid'.
- Standardized test exits: replaced open-coded "status=0; exit" with "_exit 0".
- Dropped stale "_require_block_device $TEST_DEV" checks left over from before migrating tests to loop devices.
- Percolated helper renames across all tests:
. _loop_image_create_clone -> _create_cloned_loop_devs
. _loop_image_destroy -> _destroy_cloned_loop_devs
. _clone_mount_option -> _clone_mount_options- Added cleanup of "$TEST_DIR/$seq" in test exit/cleanup handlers.
- Test Cases Individual Updates:
- generic/744:
. Replaced _require_duplicate_fsid with _require_clone_mount().
. Migrated to common _create_cloned_loop_devs() and _clone_mount_options().
- generic/902:
. New regression test case added to verify statfs f_fsid derivation against filesystem UUID.
- generic/903:
. Added --noheadings flag to findmnt queries for cleaner output parsing.
- generic/904:
. Dropped 'auto' and 'quick' from test groups due to runtime and policy requirements. . Updated referenced kernel commit IDs.
[1] https://lore.kernel.org/fstests/[email protected]
[2] 72de4807ba84 ("btrfs: derive f_fsid with dev_t only when temp_fsid is active")
Anand Jain (21):
fstests: introduce _require_clone_mount() helper
fstests: introduce _create_cloned_loop_devs() helper
fstests: add _clone_mount_options() helper
fstests: add FSNOTIFYWAIT_PROG
fstests: add _require_fanotify_function
fstests: add _require_unique_f_fsid() helper
fstests: add SEMANAGE_PROG
fstests: verify fanotify isolation on cloned filesystems
fstests: introduce helper _scratch_mkfs_uuid()
fstests: add helpers to verify the expected f_fsid
fstests: verify statfs f_fsid is derived from the filesystem UUID
fstests: verify libblkid resolution of duplicate UUIDs
fstests: introduce _require_security_ima() helper
fstests: verify IMA isolation on cloned filesystems
fstests: verify exportfs file handles on cloned filesystems
fstests: introduce _require_metadata_uuid() helper
fstests: add _change_metadata_uuid helper
fstests: test UUID consistency for clones with metadata_uuid
fstests: generic/744: use new helper _require_clone_mount()
fstests: generic/744: migrate to _create_cloned_loop_devs()
fstests: _create_loop_device_like_bdev() remove unused variable
common/config | 2 + common/rc | 262 +++++++++++++++++++++++++++++++++++++++--- tests/generic/744 | 72 +++++------- tests/generic/901 | 142 +++++++++++++++++++++++ tests/generic/901.out | 7 ++ tests/generic/902 | 38 ++++++ tests/generic/902.out | 2 + tests/generic/903 | 71 ++++++++++++ tests/generic/903.out | 6 + tests/generic/904 | 113 ++++++++++++++++++ tests/generic/904.out | 10 ++ tests/generic/905 | 79 +++++++++++++ tests/generic/905.out | 2 + tests/generic/906 | 74 ++++++++++++ tests/generic/906.out | 6 + 15 files changed, 827 insertions(+), 59 deletions(-) create mode 100644 tests/generic/901 create mode 100644 tests/generic/901.out create mode 100644 tests/generic/902 create mode 100644 tests/generic/902.out create mode 100644 tests/generic/903 create mode 100644 tests/generic/903.out create mode 100644 tests/generic/904 create mode 100644 tests/generic/904.out create mode 100644 tests/generic/905 create mode 100644 tests/generic/905.out create mode 100644 tests/generic/906 create mode 100644 tests/generic/906.out
Signature · 1 line
2.43.0
PATCH 1/21 fstests: introduce _require_clone_mount() helper
Add _require_clone_mount() to common/rc to check whether the filesystem supports mounting cloned block devices simultaneously. For Btrfs, it verifies kernel support for the temp_fsid feature, while skipping unsupported filesystem types with _notrun.
--- common/rc | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
common/rc +15 -0
@@ -6124,6 +6124,21 @@ _force_inplace_writes() esac } +_require_clone_mount() +{ + case "$FSTYP" in + xfs|ext4|f2fs) + # No kernel-side restriction; always supported + ;; + btrfs) + _require_btrfs_fs_feature "temp_fsid" + ;; + *) + _notrun "$FSTYP does not support mounting cloned devices simultaneously" + ;; + esac +} + # Test that a filesystem can do writes to a file in place (without allocating # new extents, without Copy-On-Write semantics). _require_inplace_writes()
Signature · 1 line
2.43.0
PATCH 2/21 fstests: introduce _create_cloned_loop_devs() helper
In reply to Anand JainIntroduce _create_cloned_loop_devs() and _destroy_cloned_loop_devs 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 | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+)
common/rc +66 -0
@@ -1534,6 +1534,72 @@ _scratch_resvblks() esac } +# Create a small loop image, run an optional tuning function ($2) on it, +# clone it, and attach both to loop devices, returned in ($1). +# Args: +# $1: Nameref to return the array of allocated loop devices [base, clone]. +# $2: Optional callback function to tune the base filesystem before cloning. +_create_cloned_loop_devs() +{ + local -n _ret=$1 + local pre_clone_tune_func="$2" + local img_file="$TEST_DIR/${seq}/orig.img" + local img_file_clone="$TEST_DIR/${seq}/clone.img" + local size=$(_small_fs_size_mb 128) # Smallest possible + local temp_dev + local loop_devs=() + + # All current callers mount the original and the clone simultaneously. + _require_clone_mount + + # Since we copy the block device image, we keep its size small. + _require_fs_space $TEST_DIR $((size * 1024 * 2)) + + _create_file_sized $((size * 1024 * 1024)) $img_file || + _fail "Failed: Create $img_file $size" + + temp_dev=("$(_create_loop_device_like_bdev $img_file ${TEST_DEV})") + _mkfs_dev "${temp_dev}" + + # Only execute if the function argument is not empty + if [ -n "$pre_clone_tune_func" ]; then + $pre_clone_tune_func "${temp_dev}" + fi + + # We are about to copy the loop device's backing file + # Flush loop device's buffer cache + blockdev --flushbufs "${temp_dev}" + # Sync system's dirty pages including backing file's + sync + _destroy_loop_device "${temp_dev}" + + cp $img_file $img_file_clone || _fail "Failed to copy cloned image" + + loop_devs=("$(_create_loop_device_like_bdev $img_file ${TEST_DEV})") + loop_devs+=("$(_create_loop_device_like_bdev $img_file_clone ${TEST_DEV})") + + # Help debug + losetup --list "${loop_devs[0]}" >> $seqres.full + losetup --list "${loop_devs[1]}" >> $seqres.full + + _ret=("${loop_devs[@]}") +} + +# Teardown loop devices and delete their underlying backing image files. +# Accepts a list of loop device paths (e.g., /dev/loop0 /dev/loop1). +_destroy_cloned_loop_devs() +{ + for d in "$@"; do + # Retrieve the path of the backing file + local f=$(losetup --noheadings --output BACK-FILE $d) + + # Detach the loop device from the backing file + _destroy_loop_device "$d" + + # Clean up the backing disk image file + [ -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 3/21 fstests: add _clone_mount_options() helper
In reply to Anand JainAdds _clone_mount_options() helper function to handle filesystem-specific requirements for mounting cloned devices. Abstract the need for -o nouuid on XFS.
--- common/rc | 13 +++++++++++++ 1 file changed, 13 insertions(+)
common/rc +13 -0
@@ -428,6 +428,19 @@ _scratch_mount_options() $SCRATCH_DEV $SCRATCH_MNT } +# Return filesystem-specific mount options required for mounting clone/snapshot +# devices. +_clone_mount_options() +{ + case "$FSTYP" in + xfs) + # Allow mounting a duplicate filesystem on the same host + echo "-o nouuid" + ;; + *) + esac +} + _supports_filetype() { local dir=$1
Signature · 1 line
2.43.0
PATCH 4/21 fstests: add FSNOTIFYWAIT_PROG
In reply to Anand JainDefine FSNOTIFYWAIT_PROG for an upcoming test case that uses fsnotifywait.
--- common/config | 1 + 1 file changed, 1 insertion(+)
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 FSNOTIFYWAIT_PROG="$(type -P fsnotifywait)" # udev wait functions. #
Signature · 1 line
2.43.0
PATCH 5/21 fstests: add _require_fanotify_function
In reply to Anand Jainfanotify support may not be compiled into the kernel. Add _require_fanotify_function to skip tests when fanotify is disabled.
--- common/rc | 7 +++++++ 1 file changed, 7 insertions(+)
common/rc +7 -0
@@ -6384,6 +6384,13 @@ _require_max_file_range_blocks() esac } +_require_fanotify_function() +{ + if $FSNOTIFYWAIT_PROG 2>&1 | grep -q "Function not implemented"; then + _notrun "Need CONFIG_FANOTIFY and CONFIG_FANOTIFY_ACCESS_PERMISSIONS to be enabled" + fi +} + _require_fanotify_ioerrors() { local x
Signature · 1 line
2.43.0
PATCH 6/21 fstests: add _require_unique_f_fsid() helper
In reply to Anand JainAdd a helper to check if the target filesystem supports unique f_fsid tracking across cloned or snapshot instances.
Certain filesystems like XFS, Btrfs, and F2FS ensure unique f_fsid identifiers per filesystem instance. However, Ext4 derives its f_fsid directly from its superblock UUID, which leads to identical f_fsid values on cloned images until the UUID is manually modified by userspace.
Introduce _require_unique_f_fsid() to allow test cases requiring strict f_fsid uniqueness to skip gracefully on unsupported filesystems.
--- common/rc | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
common/rc +27 -0
@@ -6417,6 +6417,33 @@ _require_fanotify_ioerrors() _notrun "$FSTYP does not support fanotify ioerrors" } +# Skip the test if the filesystem does not enforce unique f_fsids +# natively. Checking this dynamically requires recreating a clone +# layout, so we use a static lookup based on FSTYP. +# +# Across all filesystems, a UUID collision causes libblkid tools to return +# non-deterministic device mappings. It is ultimately the responsibility +# of the userspace utility or use-case to enforce uniqueness when a clone +# diverges. For details, see mailing list thread discussions: +# Link: https://lore.kernel.org/linux-ext4/[email protected]/ +_require_unique_f_fsid() +{ + case "$FSTYP" in + ext*) + # Ext4 derives f_fsid from the superblock UUID, meaning + # clones share the same f_fsid until their UUIDs + # diverge. + _notrun "Target filesystem ($FSTYP) does not guarantee unique f_fsid on clones." + ;; + *) + # Conversely, XFS, Btrfs, and F2FS ensure f_fsid remains + # unique per filesystem instance (often by deriving it + # from the UUID and underlying block device.) + ;; + esac +} + + # Computes a percentage of the available space in a filesystem and # returns that quantity in MB. The percentage must not contain a percent # sign ("%").
Signature · 1 line
2.43.0
PATCH 7/21 fstests: add SEMANAGE_PROG
In reply to Anand JainDefine SEMANAGE_PROG for an upcoming test case that uses semanage(8).
--- common/config | 1 + 1 file changed, 1 insertion(+)
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 FSNOTIFYWAIT_PROG="$(type -P fsnotifywait)" +export SEMANAGE_PROG="$(type -P semanage)" # udev wait functions. #
Signature · 1 line
2.43.0
PATCH 8/21 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.
--- tests/generic/901 | 142 ++++++++++++++++++++++++++++++++++++++++++ tests/generic/901.out | 7 +++ 2 files changed, 149 insertions(+) create mode 100644 tests/generic/901 create mode 100644 tests/generic/901.out
tests/generic/901 new file +142 -0
@@ -0,0 +1,142 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2026 Anand Jain <[email protected]>. All Rights Reserved. +# +# FS QA Test No. 901 +# 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 tempfsid + +_require_test +_require_loop +_require_command "$SEMANAGE_PROG" semanage +_require_command "$FSNOTIFYWAIT_PROG" fsnotifywait +_require_fanotify_function +_require_unique_f_fsid + +_cleanup() +{ + cd / + [[ -n $pid1 ]] && { kill -TERM "$pid1" 2> /dev/null; wait $pid1; } + [[ -n $pid2 ]] && { kill -TERM "$pid2" 2> /dev/null; wait $pid2; } + + if [ "$semanage_added" = "yes" ]; then + semanage permissive -d unconfined_t >/dev/null 2>&1 || true + fi + + umount $mnt1 $mnt2 >/dev/null 2>&1 + _destroy_cloned_loop_devs "${devs[@]}" 2> /dev/null + rm -r -f $tmp.* +} + +# Run fsnotifywait in unbuffered mode to watch filesystem-wide create events +monitor_fanotify() +{ + local mmnt=$1 + exec stdbuf -oL $FSNOTIFYWAIT_PROG -m -F -S -e create "$mmnt" 2>&1 +} + +# Transform f_fsid into the hi.lo format used in fanotify FID logs +fsid_to_fid_parts() +{ + local fsid=$1 + # Pad to 16 hex chars (64-bit), then split into two 32-bit halves + local padded=$(printf '%016x' "0x${fsid}") + local hi=$(printf '%x' "0x${padded:0:8}") # strips leading zeros + local lo=$(printf '%x' "0x${padded:8:8}") # strips leading zeros + echo "${hi}.${lo}" +} + +rm -rf $TEST_DIR/$seq 2>/dev/null +mkdir -p $TEST_DIR/$seq +# Create base loop device and its clone +devs=() +_create_cloned_loop_devs devs +mnt1=$TEST_DIR/$seq/mnt1 +mnt2=$TEST_DIR/$seq/mnt2 +mkdir -p $mnt1 +mkdir -p $mnt2 + +# Mount both base and clone filesystems using required clone mount options +_mount $(_common_dev_mount_options) $(_clone_mount_options) ${devs[0]} $mnt1 || \ + _fail "Failed to mount dev1" +_mount $(_common_dev_mount_options) $(_clone_mount_options) ${devs[1]} $mnt2 || \ + _fail "Failed to mount dev2" + +# Fetch filesystem IDs to verify the kernel can differentiate between them +fsid1=$(stat -f -c "%i" $mnt1) +fsid2=$(stat -f -c "%i" $mnt2) + +log1=$tmp.fanotify1 +log2=$tmp.fanotify2 + +pid1="" +pid2="" +echo "Setup FID fanotify watchers on both mnt1 and mnt2" + +# Permit unconfined_t domains when SELinux is enforcing to prevent fanotify +# blockages +semanage_added="no" +if [ "$(getenforce 2>/dev/null)" = "Enforcing" ]; then + if ! semanage permissive -l | grep -q "unconfined_t"; then + semanage permissive -a unconfined_t >/dev/null 2>&1 && semanage_added="yes" + fi +fi + +# Start asynchronous fanotify monitors +( monitor_fanotify "$mnt1" > "$log1" ) & +pid1=$! +( monitor_fanotify "$mnt2" > "$log2" ) & +pid2=$! +sleep 2 + +if ! kill -0 "$pid1" 2>/dev/null || ! kill -0 "$pid2" 2>/dev/null; then + cat "$log1" + cat "$log2" + _fail "$FSNOTIFYWAIT_PROG setup failed" +fi + +echo "Trigger file creation on mnt1" +touch $mnt1/file_on_mnt1 +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 +pid1="" +pid2="" + +e_fsid1=$(fsid_to_fid_parts "$fsid1") +e_fsid2=$(fsid_to_fid_parts "$fsid2") + +# Dump debug details to the full log +echo $fsid1 $e_fsid1 $fsid2 $e_fsid2 >> $seqres.full +cat $log1 >> $seqres.full +cat $log2 >> $seqres.full + +# Ensure monitor 1 only captured events belonging to mnt 1 and fsid 1 +if grep -qF "$e_fsid1" "$log1" && ! grep -qF "$e_fsid2" "$log1"; then + echo "SUCCESS: mnt1 events found" +else + [ ! -s "$log1" ] && echo " - mnt1 received no events." + grep -qF "$e_fsid2" "$log1" && echo " - mnt1 received event from mnt2." +fi + +# Ensure monitor 2 only captured events belonging to mnt 2 and fsid 2 +if grep -qF "$e_fsid2" "$log2" && ! grep -qF "$e_fsid1" "$log2"; then + echo "SUCCESS: mnt2 events found" +else + [ ! -s "$log2" ] && echo " - mnt2 received no events." + grep -qF "$e_fsid1" "$log2" && echo " - mnt2 received event from mnt1." +fi + +_exit 0
tests/generic/901.out new file +7 -0
@@ -0,0 +1,7 @@ +QA output created by 901 +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 9/21 fstests: introduce helper _scratch_mkfs_uuid()
In reply to Anand Jain--- common/rc | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
common/rc +30 -0
@@ -1449,6 +1449,36 @@ _scratch_mkfs_sized() _try_scratch_mkfs_sized "$@" || _notrun "_scratch_mkfs_sized failed with ($*)" } +# mkfs filesystem with a known uuid +# Input argument : none +_scratch_mkfs_uuid() +{ + case $FSTYP in + f2fs|ext4) + if echo "$MKFS_OPTIONS" | grep -E -q "-U"; then + _notrun "Config contains mkfs uuid option" + fi + MKFS_OPTIONS+=" -U 12345678-1234-1234-1234-123456789abc" + ;; + xfs) + if echo "$MKFS_OPTIONS" | grep -E -q "uuid"; then + _notrun "Config contains mkfs uuid option" + fi + MKFS_OPTIONS+=" -m uuid=12345678-1234-1234-1234-123456789abc" + ;; + btrfs) + if echo "$MKFS_OPTIONS" | grep -E -q "uuid|-U"; then + _notrun "Config contains mkfs uuid option" + fi + MKFS_OPTIONS+=" --uuid 12345678-1234-1234-1234-123456789abc" + ;; + *) + _notrun "can't mkfs $FSTYP with uuid" + ;; + esac + _scratch_mkfs +} + # Emulate an N-data-disk stripe w/ various stripe units # _scratch_mkfs_geom <sunit bytes> <swidth multiplier> [optional blocksize] _scratch_mkfs_geom()
Signature · 1 line
2.43.0
PATCH 10/21 fstests: add helpers to verify the expected f_fsid
In reply to Anand JainAdd two helpers to common/rc:
_require_uuid_based_fsid() skips the test unless the filesystem derives statfs f_fsid from the UUID alone (currently btrfs and ext4).
_scratch_expected_fsid() prints the f_fsid expected for a filesystem created with the fixed test UUID.
--- common/rc | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+)
common/rc +31 -0
@@ -6065,6 +6065,37 @@ hexdump() _fail "Use _hexdump(), please!" } +# Require a filesystem whose statfs f_fsid is derived from the filesystem +# UUID only, so that it is stable across devices and mounts. +_require_uuid_based_fsid() +{ + case $FSTYP in + btrfs|ext4) + ;; + *) + _notrun "Require a filesystem that derives f_fsid from the UUID only" + ;; + esac +} + +# Print the statfs f_fsid expected for a filesystem created with the test +# UUID 12345678-1234-1234-1234-123456789abc. +# Must be guarded by _require_uuid_based_fsid. +_scratch_expected_fsid() +{ + case $FSTYP in + ext4) + echo "4c44000088884c44" + ;; + btrfs) + echo "444c444c888d" + ;; + *) + return 1 + ;; + esac +} + # Try to create a file with inode->i_blocks >= (length / blocksize). # There may be some small overhead, e.g. ext2 filesystem allocates a # substantial number of blocks to store block mappings. Those are accounted
Signature · 1 line
2.43.0
PATCH 11/21 fstests: verify statfs f_fsid is derived from the filesystem UUID
In reply to Anand JainOn btrfs and ext4, statfs f_fsid is computed from the filesystem UUID, so a filesystem created with a known UUID must always report the same f_fsid. Userspace relies on this, for example fanotify and file handle users that identify a filesystem across mounts.
Guards against f_fsid changing across kernel versions, which would break userspace that relies on it.
--- tests/generic/902 | 38 ++++++++++++++++++++++++++++++++++++++ tests/generic/902.out | 2 ++ 2 files changed, 40 insertions(+) create mode 100644 tests/generic/902 create mode 100644 tests/generic/902.out
tests/generic/902 new file +38 -0
@@ -0,0 +1,38 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2026 Anand Jain <[email protected]>. All Rights Reserved. +# +# FS QA Test No. 902 +# +# Verify that statfs f_fsid is derived from the filesystem UUID. +# Create a filesystem with a fixed UUID, mount it, and check that f_fsid +# matches the expected value. Applies only to filesystems that derive +# f_fsid from the UUID (btrfs, ext4). + +. ./common/preamble + +_begin_fstest auto quick + +_require_scratch +_require_uuid_based_fsid + +_fixed_by_fs_commit btrfs 72de4807ba84 \ + "btrfs: derive f_fsid with dev_t only when temp_fsid is active" + +_scratch_mkfs_uuid >> $seqres.full 2>&1 || _fail "mkfs failed" + +_scratch_mount + +blkid $SCRATCH_DEV >> $seqres.full +f_fsid=$(stat -f -c "%i" $SCRATCH_MNT) +expected=$(_scratch_expected_fsid) + +echo "f_fsid=$f_fsid expected=$expected" >> $seqres.full + +[[ $f_fsid == "$expected" ]] || _fail "f_fsid mismatch" + +_scratch_unmount + +echo "Silence is golden" + +_exit 0
tests/generic/902.out new file +2 -0
@@ -0,0 +1,2 @@ +QA output created by 902 +Silence is golden
Signature · 1 line
2.43.0
PATCH 12/21 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/903 | 71 +++++++++++++++++++++++++++++++++++++++++++ tests/generic/903.out | 6 ++++ 2 files changed, 77 insertions(+) create mode 100644 tests/generic/903 create mode 100644 tests/generic/903.out
tests/generic/903 new file +71 -0
@@ -0,0 +1,71 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2026 Anand Jain <[email protected]>. All Rights Reserved. +# +# FS QA Test No. 903 +# Check if the mountinfo based findmnt would resolve to the common uuid +# as per the blkid (libblkid based). + +. ./common/preamble +. ./common/filter + +_begin_fstest auto quick mount tempfsid + +_require_test +_require_loop + +_cleanup() +{ + cd / + rm -r -f $tmp.* + umount $mnt1 $mnt2 2>/dev/null + _destroy_cloned_loop_devs "${devs[@]}" 2> /dev/null +} + +# Normalize pool devices and mount points names +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 +} + +rm -rf $TEST_DIR/$seq 2>/dev/null +mkdir -p $TEST_DIR/$seq +# Setup base loop device and its clone +devs=() +_create_cloned_loop_devs devs +mnt1=$TEST_DIR/$seq/mnt1 +mnt2=$TEST_DIR/$seq/mnt2 +mkdir -p $mnt1 +mkdir -p $mnt2 + +# Get the uuid from the source device +fsuuid=$(blkid -s UUID -o value ${devs[0]}) + +# Mount both identical UUID filesystems simultaneously +_mount $(_common_dev_mount_options) $(_clone_mount_options) ${devs[0]} $mnt1 || \ + _fail "Failed to mount dev1" +_mount $(_common_dev_mount_options) $(_clone_mount_options) ${devs[1]} $mnt2 || \ + _fail "Failed to mount dev2" + +findmnt --noheadings -o SOURCE,TARGET,UUID "${devs[0]}" | \ + sed -e "s/${fsuuid}/FSUUID/g" | filter_pool +findmnt --noheadings -o SOURCE,TARGET,UUID "${devs[1]}" | \ + sed -e "s/${fsuuid}/FSUUID/g" | filter_pool + +# Btrfs assigned a random uuid for the clone fs before the fix. +# Cycle mounts and reverse the initialization (source and clone fs) order. +echo "**** mount cycle ****" +_unmount $mnt1 +_unmount $mnt2 +_mount $(_common_dev_mount_options) $(_clone_mount_options) ${devs[1]} $mnt2 || \ + _fail "Failed to mount dev2" +_mount $(_common_dev_mount_options) $(_clone_mount_options) ${devs[0]} $mnt1 || \ + _fail "Failed to mount dev1" + +findmnt --noheadings -o SOURCE,TARGET,UUID "${devs[0]}" | \ + sed -e "s/${fsuuid}/FSUUID/g" | filter_pool +findmnt --noheadings -o SOURCE,TARGET,UUID "${devs[1]}" | \ + sed -e "s/${fsuuid}/FSUUID/g" | filter_pool + +_exit 0
tests/generic/903.out new file +6 -0
@@ -0,0 +1,6 @@ +QA output created by 903 +DEV1 MNT1 FSUUID +DEV2 MNT2 FSUUID +**** mount cycle **** +DEV1 MNT1 FSUUID +DEV2 MNT2 FSUUID
Signature · 1 line
2.43.0
PATCH 13/21 fstests: introduce _require_security_ima() helper
In reply to Anand JainVerifying FSID handling in cloned filesystems with Integrity Measurement Architecture (IMA) requires active IMA policy configuration.
Introduce _require_security_ima() to common/rc to ensure securityfs is available and the IMA policy file is present and writable, skipping tests with _notrun when unsupported.
--- common/rc | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
common/rc +23 -0
@@ -6354,6 +6354,29 @@ _max() { echo $ret } +# Check if the requirements for Integrity Measurement Architecture (IMA) testing are met: +# 1. securityfs is enabled in the kernel. +# 2. securityfs is rw-mountable with the IMA policy loadable. +_require_security_ima() +{ + [ -d /sys/kernel/security ] || _notrun "kernel doesn't support securityfs" + + # securityfs may not be mounted yet on the host; mount it read-only + # in a scratch location just to probe for IMA support. + local se_mnt="${TEST_MNT}/${seq}/se_mnt" + local has_ima=1 + + mkdir -p "${se_mnt}" + _mount -t securityfs securityfs "${se_mnt}" 2>/dev/null || _notrun "cannot mount securityfs" + + [ -d "${se_mnt}/ima" ] || has_ima=0 + [ -w "${se_mnt}/ima/policy" ] || _notrun "IMA policy not writable" + + _unmount "${se_mnt}" + + [ $has_ima -eq 1 ] || _notrun "kernel doesn't support IMA" +} + # Due to reasons explained in fio commit 40f1fc11d, fio version between # v3.33 and v3.38 have atomic= feature but it is a no-op and doesn't do # RWF_ATOMIC write. Hence, use this helper to ensure fio has the
Signature · 1 line
2.43.0
PATCH 14/21 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/904 | 113 ++++++++++++++++++++++++++++++++++++++++++ tests/generic/904.out | 10 ++++ 2 files changed, 123 insertions(+) create mode 100644 tests/generic/904 create mode 100644 tests/generic/904.out
tests/generic/904 new file +113 -0
@@ -0,0 +1,113 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2026 Anand Jain <[email protected]>. All Rights Reserved. +# +# FS QA Test No. 904 +# 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 tempfsid + +_require_test +_require_loop +_require_security_ima + +_fixed_by_fs_commit btrfs df84f6c77377 \ + "btrfs: use on-disk uuid for s_uuid in temp_fsid mounts" +_fixed_by_fs_commit btrfs c2a74ed0494c \ + "btrfs: derive f_fsid from on-disk fsuuid and dev_t" +_fixed_by_fs_commit btrfs 72de4807ba84 \ + "btrfs: derive f_fsid with dev_t only when temp_fsid is active" + +_cleanup() +{ + cd / + rm -r -f $tmp.* + _unmount $mnt1 2>/dev/null + _unmount $mnt2 2>/dev/null + _destroy_cloned_loop_devs "${devs[@]}" 2> /dev/null +} + +# Normalize device names and mount points +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 +} + +# Core helper to set IMA policy and check measurement logs +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 + + 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" || \ + _fail "Policy rejected" + fi + + # Create a file to trigger measurement and verify its entry in + # the IMA log. + echo "test_data" > $mnt/$foofile + + # IMA log extract + grep $foofile "$ima_log" | awk '{ print $5 }' | filter_pool | \ + sed "s/$foofile/FOOBAR_FILE/" + + echo "dbg: $mnt $fsuuid $foofile" >> $seqres.full + tail -1 "$ima_log" >> $seqres.full + echo >> $seqres.full +} + +# Core helper to set IMA policy and check measurement logs + +rm -rf $TEST_DIR/$seq 2>/dev/null +mkdir -p $TEST_DIR/$seq + +# Initialize loop base and cloned instances +devs=() +_create_cloned_loop_devs devs +mnt1=$TEST_DIR/$seq/mnt1 +mnt2=$TEST_DIR/$seq/mnt2 +mkdir -p $mnt1 +mkdir -p $mnt2 + +# Concurrently mount both clones +_mount $(_common_dev_mount_options) $(_clone_mount_options) ${devs[0]} $mnt1 || \ + _fail "Failed to mount dev1" +_mount $(_common_dev_mount_options) $(_clone_mount_options) ${devs[1]} $mnt2 || \ + _fail "Failed to mount dev2" + +# IMA response on baseline and clone configuration +do_ima $mnt1 1 +do_ima $mnt2 0 + +# Cycle mount on the second device. +echo mount cycle +_unmount $mnt2 +_mount $(_common_dev_mount_options) $(_clone_mount_options) ${devs[1]} $mnt2 || \ + _fail "Failed to mount dev2" + +do_ima $mnt1 0 +do_ima $mnt2 0 + +_exit 0
tests/generic/904.out new file +10 -0
@@ -0,0 +1,10 @@ +QA output created by 904 +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 15/21 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/905 | 79 +++++++++++++++++++++++++++++++++++++++++++ tests/generic/905.out | 2 ++ 2 files changed, 81 insertions(+) create mode 100644 tests/generic/905 create mode 100644 tests/generic/905.out
tests/generic/905 new file +79 -0
@@ -0,0 +1,79 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2026 Anand Jain <[email protected]>. All Rights Reserved. +# +# FS QA Test No. 905 +# Verify that file handles encoded on a cloned filesystem remain valid and +# resolvable via open_by_handle across a mount cycle and mount order swap. + +. ./common/preamble + +_begin_fstest auto quick exportfs tempfsid + +_require_test +_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 + _destroy_cloned_loop_devs "${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 +} + +# Attempt to read and decode the saved file handles on the targeted mount point. +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 +} + +rm -rf $TEST_DIR/$seq 2>/dev/null +mkdir -p $TEST_DIR/$seq +# Setup base loop device and its clone +devs=() +_create_cloned_loop_devs devs +mnt1=$TEST_DIR/$seq/mnt1 +mnt2=$TEST_DIR/$seq/mnt2 +mkdir -p $mnt1 +mkdir -p $mnt2 + +# Mount both identical UUID filesystems simultaneously +_mount $(_common_dev_mount_options) $(_clone_mount_options) ${devs[0]} $mnt1 || \ + _fail "Failed to mount dev1" +_mount $(_common_dev_mount_options) $(_clone_mount_options) ${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 + +# Cycle mounts and reverse initialization sequence to check if +# file handle lookups are okay +_unmount $mnt1 +_unmount $mnt2 +_mount $(_common_dev_mount_options) $(_clone_mount_options) ${devs[1]} $mnt2 || \ + _fail "Failed to mount dev2" +_mount $(_common_dev_mount_options) $(_clone_mount_options) ${devs[0]} $mnt1 || \ + _fail "Failed to mount dev1" + +# Verify file handles can still be resolved post-mount-cycle +test_file_handles -rp "cycle mount" + +_exit 0
tests/generic/905.out new file +2 -0
@@ -0,0 +1,2 @@ +QA output created by 905 +test_file_handles after cycle mount
Signature · 1 line
2.43.0
PATCH 16/21 fstests: introduce _require_metadata_uuid() helper
In reply to Anand JainAdd _require_metadata_uuid() to common/rc to check for the required userspace tools (xfs_admin and btrfstune) on XFS and Btrfs, and verify kernel metadata_uuid feature support on Btrfs before testing filesystem UUID changes.
--- common/rc | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
common/rc +18 -0
@@ -6527,6 +6527,24 @@ _require_unique_f_fsid() esac } +_require_metadata_uuid() +{ + case $FSTYP in + xfs) + # The xfs_admin utility is required to modify the filesystem UUID. + # Kernel support for metadata_uuid has been present since 4.16, so + # it is assumed to be available. + _require_command "$XFS_ADMIN_PROG" "xfs_admin" + ;; + btrfs) + _require_btrfs_fs_feature "metadata_uuid" + _require_command "$BTRFS_TUNE_PROG" "btrfstune" + ;; + *) + _notrun "Require filesystem with metadata_uuid feature" + ;; + esac +} # Computes a percentage of the available space in a filesystem and # returns that quantity in MB. The percentage must not contain a percent
Signature · 1 line
2.43.0
PATCH 17/21 fstests: add _change_metadata_uuid helper
In reply to Anand Jain_change_metadata_uuid changes the UUID of the golden filesystem before it is cloned.
--- common/rc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
common/rc +17 -0
@@ -1577,6 +1577,23 @@ _scratch_resvblks() esac } +# Change the metadata UUID of the given device to a newly generated one. +# Args: +# $1: Block device path to modify. +_change_metadata_uuid() +{ + local dev=$1 + + case $FSTYP in + xfs) + $XFS_ADMIN_PROG -U generate $dev >> $seqres.full + ;; + btrfs) + $BTRFS_TUNE_PROG -m $dev + ;; + esac +} + # Create a small loop image, run an optional tuning function ($2) on it, # clone it, and attach both to loop devices, returned in ($1). # Args:
Signature · 1 line
2.43.0
PATCH 18/21 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/906 | 74 +++++++++++++++++++++++++++++++++++++++++++ tests/generic/906.out | 6 ++++ 2 files changed, 80 insertions(+) create mode 100644 tests/generic/906 create mode 100644 tests/generic/906.out
tests/generic/906 new file +74 -0
@@ -0,0 +1,74 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2026 Anand Jain <[email protected]>. All Rights Reserved. +# +# FS QA Test No. 906 +# +# 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 tempfsid + +_require_test +_require_loop +_require_metadata_uuid + +_cleanup() +{ + cd / + rm -r -f $tmp.* + umount $mnt1 $mnt2 2>/dev/null + _destroy_cloned_loop_devs "${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 +} + +rm -rf $TEST_DIR/$seq 2>/dev/null +mkdir -p $TEST_DIR/$seq +# Create base loop device and its clone, applying the metadata_uuid tuning +# callback to the base filesystem before the copy occurs. +devs=() +_create_cloned_loop_devs devs _change_metadata_uuid +mnt1=$TEST_DIR/$seq/mnt1 +mnt2=$TEST_DIR/$seq/mnt2 +mkdir -p $mnt1 +mkdir -p $mnt2 + +# Get the uuid from the source device +fsuuid=$(blkid -s UUID -o value ${devs[0]}) + +# Mount both clone and baseline +_mount $(_common_dev_mount_options) $(_clone_mount_options) ${devs[0]} $mnt1 || \ + _fail "Failed to mount dev1" +_mount $(_common_dev_mount_options) $(_clone_mount_options) ${devs[1]} $mnt2 || \ + _fail "Failed to mount dev2" + +findmnt -o SOURCE,TARGET,UUID "${devs[0]}" | tail -n +2 | \ + sed -e "s/${fsuuid}/FSUUID/g" | filter_pool +findmnt -o SOURCE,TARGET,UUID "${devs[1]}" | tail -n +2 | \ + sed -e "s/${fsuuid}/FSUUID/g" | filter_pool + +# Cycle mounts and reverse the initialization order to ensure UUID tracking +# doesn't mismatch or flip when metadata_uuid optimization is active. +echo "**** mount cycle ****" +_unmount $mnt1 +_unmount $mnt2 +_mount $(_common_dev_mount_options) $(_clone_mount_options) ${devs[1]} $mnt2 || \ + _fail "Failed to mount dev2" +_mount $(_common_dev_mount_options) $(_clone_mount_options) ${devs[0]} $mnt1 || \ + _fail "Failed to mount dev1" + +findmnt -o SOURCE,TARGET,UUID "${devs[0]}" | tail -n +2 | \ + sed -e "s/${fsuuid}/FSUUID/g" | filter_pool +findmnt -o SOURCE,TARGET,UUID "${devs[1]}" | tail -n +2 | \ + sed -e "s/${fsuuid}/FSUUID/g" | filter_pool + +_exit 0
tests/generic/906.out new file +6 -0
@@ -0,0 +1,6 @@ +QA output created by 906 +DEV1 MNT1 FSUUID +DEV2 MNT2 FSUUID +**** mount cycle **** +DEV1 MNT1 FSUUID +DEV2 MNT2 FSUUID
Signature · 1 line
2.43.0
PATCH 19/21 fstests: generic/744: use new helper _require_clone_mount()
In reply to Anand JainReplace _require_duplicate_fsid() with the newly introduced _require_clone_mount() helper to verify kernel support for mounting cloned block devices with duplicate UUIDs.
--- common/rc | 14 -------------- tests/generic/744 | 8 ++++---- 2 files changed, 4 insertions(+), 18 deletions(-)
common/rc +0 -14
@@ -6235,20 +6235,6 @@ _random_file() { echo "$basedir/$(ls -U $basedir | shuf -n 1)" } -_require_duplicate_fsid() -{ - case "$FSTYP" in - "btrfs") - _require_btrfs_fs_feature temp_fsid - ;; - "ext4") - ;; - *) - _notrun "$FSTYP does not support duplicate fsid" - ;; - esac -} - # Can we find a program in the $PATH? _have_program() { command -v "$1" &>/dev/null
tests/generic/744 +4 -4
@@ -25,8 +25,7 @@ _cleanup() . ./common/filter . ./common/reflink -# Modify as appropriate. -_require_duplicate_fsid +_require_clone_mount _require_test _require_block_device $TEST_DEV _require_test_reflink
@@ -66,11 +65,12 @@ loop_dev2=$(_create_loop_device "$loop_file2") clone_filesystem ${loop_dev1} ${loop_dev2} # Mounting original device -_mount $loop_dev1 $mnt1 +_mount $(_common_dev_mount_options) $(_clone_mount_options) $loop_dev1 $mnt1 $XFS_IO_PROG -fc 'pwrite -S 0x61 0 9000' $mnt1/foo | _filter_xfs_io # Mounting cloned device -_mount $loop_dev2 $mnt2 || _fail "mount of cloned device failed" +_mount $(_common_dev_mount_options) $(_clone_mount_options) $loop_dev2 $mnt2 \ + || _fail "mount of cloned device failed" # cp reflink across two different filesystems must fail _cp_reflink $mnt1/foo $mnt2/bar 2>&1 | _filter_test_dir
Signature · 1 line
2.43.0
PATCH 20/21 fstests: generic/744: migrate to _create_cloned_loop_devs()
In reply to Anand JainSwitch generic/744 to use the common _create_cloned_loop_devs() helper to format, modify, and clone the underlying loop devices, avoiding open-coded clone setup and teardown logic.
--- tests/generic/744 | 70 ++++++++++++++++++----------------------------- 1 file changed, 27 insertions(+), 43 deletions(-)
tests/generic/744 +27 -43
@@ -10,71 +10,55 @@ . ./common/preamble _begin_fstest auto clone volume tempfsid -_cleanup() -{ - cd / - rm -r -f $tmp.* - - _unmount $mnt2 &> /dev/null - _unmount $mnt1 &> /dev/null - [ -b "$loop_dev2" ] && _destroy_loop_device $loop_dev2 - [ -b "$loop_dev1" ] && _destroy_loop_device $loop_dev1 - [ -n "$seq" ] && rm -rf $TEST_DIR/$seq -} - . ./common/filter . ./common/reflink -_require_clone_mount _require_test _require_block_device $TEST_DEV _require_test_reflink _require_cp_reflink _require_loop -clone_filesystem() +_cleanup() { - local dev1=$1 - local dev2=$2 - - _mkfs_dev $dev1 - - _mount $dev1 $mnt1 - $XFS_IO_PROG -fc 'pwrite -S 0x61 0 9000' $mnt1/foo >> $seqres.full - _unmount $mnt1 + cd / + rm -r -f $tmp.* - # device dump of $dev1 to $dev2 - dd if=$dev1 of=$dev2 conv=fsync status=none || _fail "dd failed: $?" + _unmount $mnt2 &> /dev/null + _unmount $mnt1 &> /dev/null + _destroy_cloned_loop_devs "${devs[@]}" 2> /dev/null } -[ -n "$seq" ] && rm -rf $TEST_DIR/$seq -mkdir $TEST_DIR/$seq +add_foo() +{ + local orig_dev="$1" + local temp_mnt="$TEST_DIR/$seq/temp_mnt" + + mkdir -p $temp_mnt + _mount $(_common_dev_mount_options) $(_clone_mount_options) $orig_dev $temp_mnt + $XFS_IO_PROG -fc 'pwrite -S 0x61 0 9000' $temp_mnt/foo >> $seqres.full + $XFS_IO_PROG -c 'fsync' $temp_mnt/foo + _unmount $temp_mnt +} +rm -rf $TEST_DIR/$seq 2>/dev/null +mkdir -p $TEST_DIR/$seq +# Setup base loop device and its clone +devs=() +_create_cloned_loop_devs devs add_foo mnt1=$TEST_DIR/$seq/mnt1 mnt2=$TEST_DIR/$seq/mnt2 -mkdir -p $mnt1 $mnt2 - -loop_file1="$TEST_DIR/$seq/image1" -truncate -s 300m "$loop_file1" -loop_dev1=$(_create_loop_device "$loop_file1") - -loop_file2="$TEST_DIR/$seq/image2" -truncate -s 300m "$loop_file2" -loop_dev2=$(_create_loop_device "$loop_file2") - -clone_filesystem ${loop_dev1} ${loop_dev2} +mkdir -p $mnt1 +mkdir -p $mnt2 # Mounting original device -_mount $(_common_dev_mount_options) $(_clone_mount_options) $loop_dev1 $mnt1 +_mount $(_common_dev_mount_options) $(_clone_mount_options) ${devs[0]} $mnt1 $XFS_IO_PROG -fc 'pwrite -S 0x61 0 9000' $mnt1/foo | _filter_xfs_io - # Mounting cloned device -_mount $(_common_dev_mount_options) $(_clone_mount_options) $loop_dev2 $mnt2 \ +_mount $(_common_dev_mount_options) $(_clone_mount_options) ${devs[1]} $mnt2 \ || _fail "mount of cloned device failed" # cp reflink across two different filesystems must fail _cp_reflink $mnt1/foo $mnt2/bar 2>&1 | _filter_test_dir -# success, all done -status=0 -exit +_exit 0
Signature · 1 line
2.43.0
PATCH 21/21 fstests: _create_loop_device_like_bdev() remove unused variable
In reply to Anand JainRemove unused local dev.
--- common/rc | 1 - 1 file changed, 1 deletion(-)
common/rc +0 -1
@@ -4815,7 +4815,6 @@ _create_loop_device_like_bdev() { local file=$1 local bdev=$2 - local dev local blksize test -b "$bdev" || \
Signature · 1 line
2.43.0
ping?
Regards, Anand