* [PATCH v4 5/9] fstests: verify f_fsid for cloned filesystems
From: Anand Jain @ 2026-04-28 6:42 UTC (permalink / raw)
To: fstests
Cc: linux-btrfs, linux-ext4, linux-xfs, linux-f2fs, amir73il, zlang,
hch
In-Reply-To: <cover.1777357320.git.asj@kernel.org>
Verify that the cloned filesystem provides an f_fsid that is persistent
across mount cycles, yet unique from the original filesystem's f_fsid.
Signed-off-by: Anand Jain <asj@kernel.org>
---
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
diff --git a/tests/generic/802 b/tests/generic/802
new file mode 100644
index 000000000000..31044695f3a8
--- /dev/null
+++ b/tests/generic/802
@@ -0,0 +1,62 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2026 Anand Jain <asj@kernel.org>. 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
diff --git a/tests/generic/802.out b/tests/generic/802.out
new file mode 100644
index 000000000000..d1e008f122bb
--- /dev/null
+++ b/tests/generic/802.out
@@ -0,0 +1,7 @@
+QA output created by 802
+**** fsid initially ****
+FSID_SCRATCH
+FSID_CLONE
+**** fsid after mount cycle ****
+FSID_SCRATCH
+FSID_CLONE
--
2.43.0
^ permalink raw reply related
* [PATCH v4 4/9] fstests: verify fanotify isolation on cloned filesystems
From: Anand Jain @ 2026-04-28 6:42 UTC (permalink / raw)
To: fstests
Cc: linux-btrfs, linux-ext4, linux-xfs, linux-f2fs, amir73il, zlang,
hch
In-Reply-To: <cover.1777357320.git.asj@kernel.org>
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.
Signed-off-by: Anand Jain <asj@kernel.org>
---
common/config | 1 +
tests/generic/801 | 113 ++++++++++++++++++++++++++++++++++++++++++
tests/generic/801.out | 7 +++
3 files changed, 121 insertions(+)
create mode 100644 tests/generic/801
create mode 100644 tests/generic/801.out
diff --git a/common/config b/common/config
index 605a57947a40..1588bdcb1aa1 100644
--- a/common/config
+++ b/common/config
@@ -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.
#
diff --git a/tests/generic/801 b/tests/generic/801
new file mode 100644
index 000000000000..e1282f4e3d71
--- /dev/null
+++ b/tests/generic/801
@@ -0,0 +1,113 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2026 Anand Jain <asj@kernel.org>. All Rights Reserved.
+#
+# FS QA Test 801
+# 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_block_device $TEST_DEV
+_require_loop
+_require_command "$FSNOTIFYWAIT_PROG" fsnotifywait
+
+_cleanup()
+{
+ cd /
+ [[ -n $pid1 ]] && { kill -TERM "$pid1" 2> /dev/null; wait $pid1; }
+ [[ -n $pid2 ]] && { kill -TERM "$pid2" 2> /dev/null; wait $pid2; }
+ umount $mnt1 $mnt2 2>/dev/null
+ _loop_image_destroy "${devs[@]}" 2> /dev/null
+ rm -r -f $tmp.*
+}
+
+monitor_fanotify()
+{
+ local mmnt=$1
+ exec stdbuf -oL $FSNOTIFYWAIT_PROG -m -F -S -e create "$mmnt" 2>&1
+}
+
+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}"
+}
+
+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"
+
+fsid1=$(stat -f -c "%i" $mnt1)
+fsid2=$(stat -f -c "%i" $mnt2)
+
+[[ "$fsid1" == "$fsid2" ]] && \
+ _notrun "Require clone filesystem with unique f_fsid"
+
+log1=$tmp.fanotify1
+log2=$tmp.fanotify2
+
+pid1=""
+pid2=""
+echo "Setup FID fanotify watchers on both mnt1 and mnt2"
+( monitor_fanotify "$mnt1" > "$log1" ) &
+pid1=$!
+( monitor_fanotify "$mnt2" > "$log2" ) &
+pid2=$!
+sleep 2
+
+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")
+
+echo $fsid1 $e_fsid1 $fsid2 $e_fsid2 >> $seqres.full
+cat $log1 >> $seqres.full
+cat $log2 >> $seqres.full
+
+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
+
+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
+
+status=0
+exit
diff --git a/tests/generic/801.out b/tests/generic/801.out
new file mode 100644
index 000000000000..d7b318d9f27c
--- /dev/null
+++ b/tests/generic/801.out
@@ -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
--
2.43.0
^ permalink raw reply related
* [PATCH v4 3/9] fstests: add test for inotify isolation on cloned devices
From: Anand Jain @ 2026-04-28 6:42 UTC (permalink / raw)
To: fstests
Cc: linux-btrfs, linux-ext4, linux-xfs, linux-f2fs, amir73il, zlang,
hch
In-Reply-To: <cover.1777357320.git.asj@kernel.org>
Add a new test, to verify that the kernel correctly differentiates between
two block devices sharing the same FSID/UUID.
Signed-off-by: Anand Jain <asj@kernel.org>
---
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
diff --git a/common/config b/common/config
index 4fd4c2c8af11..605a57947a40 100644
--- a/common/config
+++ b/common/config
@@ -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.
#
diff --git a/tests/generic/800 b/tests/generic/800
new file mode 100644
index 000000000000..4b9bd3e4f487
--- /dev/null
+++ b/tests/generic/800
@@ -0,0 +1,89 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2026 Anand Jain <asj@kernel.org>. All Rights Reserved.
+#
+# FS QA Test 800
+#
+# 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_block_device $TEST_DEV
+_require_loop
+_require_command "$INOTIFYWAIT_PROG" inotifywait
+
+_cleanup()
+{
+ cd /
+ [[ -n $pid1 ]] && { kill -TERM "$pid1" 2> /dev/null; wait $pid1; }
+ [[ -n $pid2 ]] && { kill -TERM "$pid2" 2> /dev/null; wait $pid2; }
+ rm -r -f $tmp.*
+ _unmount $mnt1 2>/dev/null
+ _unmount $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"
+
+log1=$tmp.inotify1
+log2=$tmp.inotify2
+
+pid1=""
+pid2=""
+echo "Setup inotify watchers on both mnt1 and mnt2"
+$INOTIFYWAIT_PROG -m -e create --format '%f' $mnt1 > $log1 2>&1 &
+pid1=$!
+$INOTIFYWAIT_PROG -m -e create --format '%f' $mnt2 > $log2 2>&1 &
+pid2=$!
+sleep 2
+
+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 inotify isolation"
+kill $pid1 $pid2
+wait $pid1 $pid2 2>/dev/null
+pid1=""
+pid2=""
+
+if grep -q "file_on_mnt1" $log1 && ! grep -q "file_on_mnt2" $log1; then
+ echo "SUCCESS: mnt1 events isolated."
+else
+ echo "FAIL: mnt1 inotify confusion!"
+ [ ! -s $log1 ] && echo " - mnt1 received no events."
+ grep -q "file_on_mnt2" $log1 && echo " - mnt1 received event from mnt2."
+fi
+
+if grep -q "file_on_mnt2" $log2 && ! grep -q "file_on_mnt1" $log2; then
+ echo "SUCCESS: mnt2 events isolated."
+else
+ echo "FAIL: mnt2 inotify confusion!"
+ [ ! -s $log2 ] && echo " - mnt2 received no events."
+ grep -q "file_on_mnt1" $log2 && echo " - mnt2 received event from mnt1."
+fi
+
+status=0
+exit
diff --git a/tests/generic/800.out b/tests/generic/800.out
new file mode 100644
index 000000000000..b10842a31210
--- /dev/null
+++ b/tests/generic/800.out
@@ -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.
--
2.43.0
^ permalink raw reply related
* [PATCH v4 2/9] fstests: add _clone_mount_option() helper
From: Anand Jain @ 2026-04-28 6:42 UTC (permalink / raw)
To: fstests
Cc: linux-btrfs, linux-ext4, linux-xfs, linux-f2fs, amir73il, zlang,
hch
In-Reply-To: <cover.1777357320.git.asj@kernel.org>
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 <asj@kernel.org>
---
common/rc | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/common/rc b/common/rc
index 754365e80dca..771472d2f8c7 100644
--- a/common/rc
+++ b/common/rc
@@ -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
--
2.43.0
^ permalink raw reply related
* [PATCH v4 1/9] fstests: add _loop_image_create_clone() helper
From: Anand Jain @ 2026-04-28 6:42 UTC (permalink / raw)
To: fstests
Cc: linux-btrfs, linux-ext4, linux-xfs, linux-f2fs, amir73il, zlang,
hch
In-Reply-To: <cover.1777357320.git.asj@kernel.org>
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 <asj@kernel.org>
---
common/rc | 47 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/common/rc b/common/rc
index 9632b211b58f..754365e80dca 100644
--- a/common/rc
+++ b/common/rc
@@ -1503,6 +1503,53 @@ _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
+
+ ($pre_clone_tune_func)
+
+ 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
--
2.43.0
^ permalink raw reply related
* [PATCH v4 0/9] fstests: add test coverage for cloned filesystem ids
From: Anand Jain @ 2026-04-28 6:42 UTC (permalink / raw)
To: fstests
Cc: linux-btrfs, linux-ext4, linux-xfs, linux-f2fs, amir73il, zlang,
hch
v4:
In _loop_image_create_clone() (Patch 1/9):
. Added _require_fs_space $TEST_DIR $((size * 1024)).
. Switched to the _create_file_sized() helper.
. Used the loop device in mkfs instead of the image file directly.
. Added a sync on the loop device before copying to ensure consistency.
For test cases (Patches 3/9 to 9/9):
. Added _require_block_device $TEST_DEV.
For test case (Patch 4/9):
. Removed the ext4 patch reference in _fixed_by_kernel_commit since
that part of the plan was dropped.
v3:
https://lore.kernel.org/fstests/cover.1777281778.git.asj@kernel.org
Anand Jain (9):
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: btrfs: test UUID consistency for clones with metadata_uuid
common/config | 2 +
common/rc | 61 +++++++++++++++++++++++
tests/btrfs/348 | 92 ++++++++++++++++++++++++++++++++++
tests/btrfs/348.out | 19 +++++++
tests/generic/800 | 89 +++++++++++++++++++++++++++++++++
tests/generic/800.out | 7 +++
tests/generic/801 | 113 ++++++++++++++++++++++++++++++++++++++++++
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 +
16 files changed, 742 insertions(+)
create mode 100644 tests/btrfs/348
create mode 100644 tests/btrfs/348.out
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
--
2.43.0
^ permalink raw reply
* Re: [PATCH v3 1/9] fstests: add _loop_image_create_clone() helper
From: Anand Jain @ 2026-04-28 6:42 UTC (permalink / raw)
To: Amir Goldstein, Anand Jain
Cc: fstests, linux-btrfs, linux-ext4, linux-xfs, linux-f2fs, zlang,
hch
In-Reply-To: <CAOQ4uxjEcHiqzB+JrnzDExMcBuTbLaPT5qQcEDX0GO0TX7hp=g@mail.gmail.com>
On 28/4/26 02:31, Amir Goldstein wrote:
> On Mon, Apr 27, 2026 at 12:19 PM Anand Jain <asj@kernel.org> wrote:
>>
>> 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 <asj@kernel.org>
>> ---
>> common/rc | 44 ++++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 44 insertions(+)
>>
>> diff --git a/common/rc b/common/rc
>> index 9632b211b58f..0e7b7eb1d98f 100644
>> --- a/common/rc
>> +++ b/common/rc
>> @@ -1503,6 +1503,50 @@ _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
>> +
>> + size=$((size * 1024 * 1024))
>> + $XFS_IO_PROG -f -c "truncate $size" $img_file
>> +
>> + loop_devs=$(_create_loop_device $img_file)
>> + _ret=($loop_devs)
>> +
>> + case $FSTYP in
>> + xfs)
>> + _mkfs_dev "-s size=4096" $img_file
>> + ;;
>> + btrfs)
>> + _mkfs_dev $img_file
>> + ;;
>> + *)
>> + _mkfs_dev $img_file
>
> You making a wrong assumption that FSTYP can format the loop devices
>
> You should add _require_block_device $SCRATCH_DEV
> to all your tests or maybe nicer, add:
>
> _require_loop_mountable which requires loop and block dev fs
> and use this requirement instead of just _require_loop in all tests.
>
Thanks. I've fixed this in v4 by adding
_require_block_device $TEST_DEV
Since SCRATCH_DEV is not required.
I didn't create a new _require_loop_mountable() helper.
Both _require_loop() and _require_block_device() are
used both together across other existing tests;
I prefer not to deviate into cleaning that up in this
patch set.
v4 is in the ML for rvb.
Thanks, Anand
> Thanks,
> Amir.
^ permalink raw reply
* Re: [PATCH v11 08/15] xfs: Report case sensitivity in fileattr_get
From: Chuck Lever @ 2026-04-28 1:32 UTC (permalink / raw)
To: Darrick J. Wong
Cc: Alexander Viro, Christian Brauner, Jan Kara, linux-fsdevel,
linux-ext4, linux-xfs, linux-cifs, linux-nfs, linux-api,
linux-f2fs-devel, OGAWA Hirofumi, Namjae Jeon, Sungjong Seo,
Yuezhang Mo, almaz.alexandrovich, Viacheslav Dubeyko,
John Paul Adrian Glaubitz, frank.li, Theodore Tso, adilger.kernel,
Carlos Maiolino, Steve French, Paulo Alcantara, Ronnie Sahlberg,
Shyam Prasad N, Trond Myklebust, Anna Schumaker, Jaegeuk Kim,
Chao Yu, Hans de Goede, senozhatsky, Chuck Lever, Roland Mainz
In-Reply-To: <20260427155636.GC7751@frogsfrogsfrogs>
On Mon, Apr 27, 2026, at 11:56 AM, Darrick J. Wong wrote:
> On Fri, Apr 24, 2026 at 09:53:10PM -0400, Chuck Lever wrote:
>> From: Chuck Lever <chuck.lever@oracle.com>
>>
>> Upper layers such as NFSD need to query whether a filesystem
>> is case-sensitive. Add FS_XFLAG_CASEFOLD to xfs_ip2xflags()
>> when the filesystem is formatted with the ASCIICI feature
>> flag. This serves both FS_IOC_FSGETXATTR (via xfs_fill_fsxattr() in
>> xfs_fileattr_get()) and XFS_IOC_BULKSTAT (which populates bs_xflags
>> directly from xfs_ip2xflags()), so bulkstat consumers and per-inode
>> queries see a consistent view of the filesystem's case-folding
>> behavior.
>>
>> XFS always preserves case. XFS is case-sensitive by default, but
>> supports ASCII case-insensitive lookups when formatted with the
>> ASCIICI feature flag.
>>
>> Reviewed-by: Roland Mainz <roland.mainz@nrubsig.org>
>> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
>> ---
> I don't understand this at all. Yes, FS_XFLAG_CASEFOLD is readonly,
> but how does clearing FS_CASEFOLD_FL from the fileattr_get output
> (without clearing XFLAG_CASEFOLD!) solve anything? This makes the
> reported output inconsistent between fsgetxattr and getflags -- one
> reports case folding, the other reports no casefolding.
The masking is a misplaced reaction to a sashiko review on the
v9 predecessor of this patch [1], which pointed out that v9 set
FS_XFLAG_CASEFOLD in fa->fsx_xflags after xfs_fill_fsxattr() had
already synced fa->flags, leaving the two views inconsistent in
the other direction, and that bulkstat would miss the flag for
the same reason. Moving the injection into xfs_ip2xflags() fixed
both gaps -- but it also surfaced FS_CASEFOLD_FL on the legacy
view, so chattr's RMW through FS_IOC_SETFLAGS hits the EOPNOTSUPP
gate at the top of xfs_fileattr_set(). Hiding it from getflags
was the wrong place to address that.
> If you want to avoid fileattr_set returning EINVAL when setting
> attributes due to the casefold flag, then don't you want to check
> the flag state vs. xfs_has_asciici() in the *fileattr_set* path?
Yep. For v12 I’ll drop the fa->flags mask and add FS_CASEFOLD_FL
to the allowlist in xfs_fileattr_set(), gated on xfs_has_asciici(mp).
xfs_flags2diflags() already has no clause for CASEFOLD, so the
FSSETXATTR path silently no-ops it the same way it does for
FS_XFLAG_HASATTR, and FS_XFLAG_CASEFOLD is in FS_XFLAG_RDONLY_MASK
so FSSETXATTR strips it centrally. Both views then agree, and a
chattr round-trip is accepted as a no-op.
The hfsplus patch in this series carries the same pattern --
FS_XFLAG_CASEFOLD is set after fileattr_fill_flags() so that
FS_CASEFOLD_FL stays out of fa->flags and dodges the EOPNOTSUPP
gate in hfsplus_fileattr_set(). I will fix it the same way.
Thanks for the catch!
[1] https://sashiko.dev/#/patchset/20260422-case-sensitivity-v9-0-be023cc070e2@oracle.com?part=9
--
Chuck Lever
^ permalink raw reply
* Re: [PATCH] ext4: avoid __GFP_NOFAIL in __ext4_get_inode_loc allocation
From: Theodore Tso @ 2026-04-28 1:28 UTC (permalink / raw)
To: Chao Shi
Cc: linux-ext4, adilger.kernel, jack, Sungwoo Kim, Dave Tian,
Weidong Zhu
In-Reply-To: <20260427222300.1284855-1-coshi036@gmail.com>
On Mon, Apr 27, 2026 at 06:23:00PM -0400, Chao Shi wrote:
> When kswapd shrinks the dcache, the last iput() on an ext4 inode can
> trigger ext4_orphan_del(), which calls ext4_reserve_inode_write() and
> ultimately __ext4_get_inode_loc(). That function calls sb_getblk(),
> which wraps __getblk() and carries implicit __GFP_NOFAIL. Because
> kswapd runs with PF_MEMALLOC set, combining NOFAIL with a non-reclaimable
> context trips WARN_ON_ONCE(current->flags & PF_MEMALLOC) inside
> __alloc_pages_slowpath(), producing a spurious splat even though the
> allocation could simply fail and return -ENOMEM to the caller.
NAK. As Sashiko correctly points out:
Sashiko AI review found 1 potential issue(s):
- [Critical] Removing __GFP_NOFAIL from __ext4_get_inode_loc causes transient memory
shortages to trigger a fatal filesystem abort (remount read-only) or severe metadata
corruption, trading a memory reclaim warning for a Denial of Service.
The warning in mm/page_alloc.c is the sort of thing that causes file
system developers to decide to drop __GFP_NOFAIL and replace it with a
retry loop just to shut the mm subsystem the heck up, since some mm
developers seem to view hangs in heavy OOM conditions as the worst
thing, where as fs developers consider data corruption to be far
worse, since users tend to get cranky when they lose their data, and
(a) in practice the OOM killer tends to get triggered first, and (b)
that's what software and hardware watchdogs are for.
In any case, there are *far* worse things than a random splat, and if
you really want to make it go away, my suggestion is to remove the
WARN_ON_ONCE from __alloc_pages_slowpath().
/*
* PF_MEMALLOC request from this context is rather bizarre
* because we cannot reclaim anything and only can loop waiting
* for somebody to do a work for us.
*/
WARN_ON_ONCE(current->flags & PF_MEMALLOC);
I disagrr the premise; it's not bizzare at all.
- Ted
^ permalink raw reply
* [PATCH] ext4: avoid __GFP_NOFAIL in __ext4_get_inode_loc allocation
From: Chao Shi @ 2026-04-27 22:23 UTC (permalink / raw)
To: linux-ext4
Cc: tytso, adilger.kernel, jack, Chao Shi, Sungwoo Kim, Dave Tian,
Weidong Zhu
When kswapd shrinks the dcache, the last iput() on an ext4 inode can
trigger ext4_orphan_del(), which calls ext4_reserve_inode_write() and
ultimately __ext4_get_inode_loc(). That function calls sb_getblk(),
which wraps __getblk() and carries implicit __GFP_NOFAIL. Because
kswapd runs with PF_MEMALLOC set, combining NOFAIL with a non-reclaimable
context trips WARN_ON_ONCE(current->flags & PF_MEMALLOC) inside
__alloc_pages_slowpath(), producing a spurious splat even though the
allocation could simply fail and return -ENOMEM to the caller.
Switch both sb_getblk() call sites in __ext4_get_inode_loc() to
sb_getblk_gfp() with the same flags minus __GFP_NOFAIL
(mapping_gfp_constraint(~__GFP_FS) | __GFP_MOVABLE), computing the gfp
value once and reusing it for the optional bitmap_bh optimisation fetch.
All callers of __ext4_get_inode_loc() -- reached via ext4_get_inode_loc(),
__ext4_get_inode_loc_noinmem(), and ext4_get_fc_inode_loc() -- already
propagate a non-zero return as an error without aborting the filesystem.
Both sb_getblk() call sites in __ext4_get_inode_loc() are converted; the
bitmap_bh fetch already falls back to make_io on NULL, so allowing it to
fail is a no-op there.
Reproduced under syzkaller+FEMU based fuzz tool (FuzzNvme) on x86_64 QEMU,
based on mainline 894009e2ef10:
WARNING: CPU: 0 PID: 55 at mm/page_alloc.c:4722
__alloc_pages_slowpath
Comm: kswapd0 Not tainted 6.19.0+ #14
Call Trace:
__alloc_pages_slowpath
alloc_pages_mpol
folio_alloc_noprof
filemap_alloc_folio_noprof
__filemap_get_folio
grow_dev_folio
grow_buffers
__getblk_slow
bdev_getblk
__ext4_get_inode_loc
ext4_get_inode_loc
ext4_reserve_inode_write
ext4_orphan_del
ext4_evict_inode
evict
iput
dentry_unlink_inode
__dentry_kill
shrink_dentry_list
prune_dcache_sb
super_cache_scan
do_shrink_slab
shrink_slab
shrink_node
balance_pgdat
kswapd
kthread
ret_from_fork
Related: see d8b90e6387a ("ext4: add ext4_sb_bread_nofail() helper
function for ext4_free_branches()") for the same strategy applied to
the read path in ext4_free_branches().
Link: https://lore.kernel.org/all/?q=PF_MEMALLOC+nofail+ext4+iput
Acked-by: Sungwoo Kim <iam@sung-woo.kim>
Acked-by: Dave Tian <daveti@purdue.edu>
Acked-by: Weidong Zhu <weizhu@fiu.edu>
Signed-off-by: Chao Shi <coshi036@gmail.com>
---
fs/ext4/inode.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index c2c2d6ac7f3..1b2a7bd59b8 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4859,6 +4859,7 @@ static int __ext4_get_inode_loc(struct super_block *sb, unsigned long ino,
ext4_fsblk_t block;
struct blk_plug plug;
int inodes_per_block, inode_offset;
+ gfp_t gfp;
iloc->bh = NULL;
if (ino < EXT4_ROOT_INO ||
@@ -4887,7 +4888,14 @@ static int __ext4_get_inode_loc(struct super_block *sb, unsigned long ino,
}
block += (inode_offset / inodes_per_block);
- bh = sb_getblk(sb, block);
+ /*
+ * No __GFP_NOFAIL: this can run from reclaim context (kswapd
+ * shrinker -> iput -> ext4_orphan_del path) where NOFAIL trips
+ * WARN_ON_ONCE in __alloc_pages_slowpath().
+ */
+ gfp = mapping_gfp_constraint(sb->s_bdev->bd_mapping, ~__GFP_FS) |
+ __GFP_MOVABLE;
+ bh = sb_getblk_gfp(sb, block, gfp);
if (unlikely(!bh))
return -ENOMEM;
if (ext4_buffer_uptodate(bh))
@@ -4912,7 +4920,7 @@ static int __ext4_get_inode_loc(struct super_block *sb, unsigned long ino,
start = inode_offset & ~(inodes_per_block - 1);
/* Is the inode bitmap in cache? */
- bitmap_bh = sb_getblk(sb, ext4_inode_bitmap(sb, gdp));
+ bitmap_bh = sb_getblk_gfp(sb, ext4_inode_bitmap(sb, gdp), gfp);
if (unlikely(!bitmap_bh))
goto make_io;
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v3 4/9] fstests: verify fanotify isolation on cloned filesystems
From: Amir Goldstein @ 2026-04-27 18:32 UTC (permalink / raw)
To: Anand Jain
Cc: fstests, linux-btrfs, linux-ext4, linux-xfs, linux-f2fs, zlang,
hch
In-Reply-To: <4777ecd14815b92c9e8577ed4d073d0f999e51ef.1777281778.git.asj@kernel.org>
On Mon, Apr 27, 2026 at 12:20 PM Anand Jain <asj@kernel.org> wrote:
>
> 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.
>
> Signed-off-by: Anand Jain <asj@kernel.org>
> ---
> common/config | 1 +
> tests/generic/801 | 115 ++++++++++++++++++++++++++++++++++++++++++
> tests/generic/801.out | 7 +++
> 3 files changed, 123 insertions(+)
> create mode 100644 tests/generic/801
> create mode 100644 tests/generic/801.out
>
> diff --git a/common/config b/common/config
> index 605a57947a40..1588bdcb1aa1 100644
> --- a/common/config
> +++ b/common/config
> @@ -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.
> #
> diff --git a/tests/generic/801 b/tests/generic/801
> new file mode 100644
> index 000000000000..3f64e4de2206
> --- /dev/null
> +++ b/tests/generic/801
> @@ -0,0 +1,115 @@
> +#! /bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +# Copyright (c) 2026 Anand Jain <asj@kernel.org>. All Rights Reserved.
> +#
> +# FS QA Test 801
> +# 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_loop
insufficient check for mounting a blockdev fs
> +_require_command "$FSNOTIFYWAIT_PROG" fsnotifywait
> +
> +[ "$FSTYP" = "ext4" ] && _fixed_by_kernel_commit xxxxxxxxxxxx \
Fix before merging
Other than that it looks ok.
Thanks,
Amir.
> + "ext4: derive f_fsid from block device to avoid collisions"
> +
> +_cleanup()
> +{
> + cd /
> + [[ -n $pid1 ]] && { kill -TERM "$pid1" 2> /dev/null; wait $pid1; }
> + [[ -n $pid2 ]] && { kill -TERM "$pid2" 2> /dev/null; wait $pid2; }
> + umount $mnt1 $mnt2 2>/dev/null
> + _loop_image_destroy "${devs[@]}" 2> /dev/null
> + rm -r -f $tmp.*
> +}
> +
> +monitor_fanotify()
> +{
> + local mmnt=$1
> + exec stdbuf -oL $FSNOTIFYWAIT_PROG -m -F -S -e create "$mmnt" 2>&1
> +}
> +
> +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}"
> +}
> +
> +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"
> +
> +fsid1=$(stat -f -c "%i" $mnt1)
> +fsid2=$(stat -f -c "%i" $mnt2)
> +
> +[[ "$fsid1" == "$fsid2" ]] && \
> + _notrun "Require clone filesystem with unique f_fsid"
> +
> +log1=$tmp.fanotify1
> +log2=$tmp.fanotify2
> +
> +pid1=""
> +pid2=""
> +echo "Setup FID fanotify watchers on both mnt1 and mnt2"
> +( monitor_fanotify "$mnt1" > "$log1" ) &
> +pid1=$!
> +( monitor_fanotify "$mnt2" > "$log2" ) &
> +pid2=$!
> +sleep 2
> +
> +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")
> +
> +echo $fsid1 $e_fsid1 $fsid2 $e_fsid2 >> $seqres.full
> +cat $log1 >> $seqres.full
> +cat $log2 >> $seqres.full
> +
> +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
> +
> +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
> +
> +status=0
> +exit
> diff --git a/tests/generic/801.out b/tests/generic/801.out
> new file mode 100644
> index 000000000000..d7b318d9f27c
> --- /dev/null
> +++ b/tests/generic/801.out
> @@ -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
> --
> 2.43.0
>
^ permalink raw reply
* Re: [PATCH v3 1/9] fstests: add _loop_image_create_clone() helper
From: Amir Goldstein @ 2026-04-27 18:31 UTC (permalink / raw)
To: Anand Jain
Cc: fstests, linux-btrfs, linux-ext4, linux-xfs, linux-f2fs, zlang,
hch
In-Reply-To: <05ace38b54ea49f462bcd6274c4a2528192e6949.1777281778.git.asj@kernel.org>
On Mon, Apr 27, 2026 at 12:19 PM Anand Jain <asj@kernel.org> wrote:
>
> 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 <asj@kernel.org>
> ---
> common/rc | 44 ++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 44 insertions(+)
>
> diff --git a/common/rc b/common/rc
> index 9632b211b58f..0e7b7eb1d98f 100644
> --- a/common/rc
> +++ b/common/rc
> @@ -1503,6 +1503,50 @@ _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
> +
> + size=$((size * 1024 * 1024))
> + $XFS_IO_PROG -f -c "truncate $size" $img_file
> +
> + loop_devs=$(_create_loop_device $img_file)
> + _ret=($loop_devs)
> +
> + case $FSTYP in
> + xfs)
> + _mkfs_dev "-s size=4096" $img_file
> + ;;
> + btrfs)
> + _mkfs_dev $img_file
> + ;;
> + *)
> + _mkfs_dev $img_file
You making a wrong assumption that FSTYP can format the loop devices
You should add _require_block_device $SCRATCH_DEV
to all your tests or maybe nicer, add:
_require_loop_mountable which requires loop and block dev fs
and use this requirement instead of just _require_loop in all tests.
Thanks,
Amir.
^ permalink raw reply
* Re: [PATCH v3 3/9] fstests: add test for inotify isolation on cloned devices
From: Amir Goldstein @ 2026-04-27 17:15 UTC (permalink / raw)
To: Anand Jain
Cc: fstests, linux-btrfs, linux-ext4, linux-xfs, linux-f2fs, zlang,
hch
In-Reply-To: <d5bff7b1c8f17cffb13c8a8f28bd8ad645306e09.1777281778.git.asj@kernel.org>
On Mon, Apr 27, 2026 at 12:20 PM Anand Jain <asj@kernel.org> wrote:
>
> Add a new test, to verify that the kernel correctly differentiates between
> two block devices sharing the same FSID/UUID.
>
> Signed-off-by: Anand Jain <asj@kernel.org>
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
> ---
> common/config | 1 +
> tests/generic/800 | 88 +++++++++++++++++++++++++++++++++++++++++++
> tests/generic/800.out | 7 ++++
> 3 files changed, 96 insertions(+)
> create mode 100644 tests/generic/800
> create mode 100644 tests/generic/800.out
>
> diff --git a/common/config b/common/config
> index 4fd4c2c8af11..605a57947a40 100644
> --- a/common/config
> +++ b/common/config
> @@ -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.
> #
> diff --git a/tests/generic/800 b/tests/generic/800
> new file mode 100644
> index 000000000000..16bc1159a2e1
> --- /dev/null
> +++ b/tests/generic/800
> @@ -0,0 +1,88 @@
> +#! /bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +# Copyright (c) 2026 Anand Jain <asj@kernel.org>. All Rights Reserved.
> +#
> +# FS QA Test 800
> +#
> +# 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_loop
> +_require_command "$INOTIFYWAIT_PROG" inotifywait
> +
> +_cleanup()
> +{
> + cd /
> + [[ -n $pid1 ]] && { kill -TERM "$pid1" 2> /dev/null; wait $pid1; }
> + [[ -n $pid2 ]] && { kill -TERM "$pid2" 2> /dev/null; wait $pid2; }
> + rm -r -f $tmp.*
> + _unmount $mnt1 2>/dev/null
> + _unmount $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"
> +
> +log1=$tmp.inotify1
> +log2=$tmp.inotify2
> +
> +pid1=""
> +pid2=""
> +echo "Setup inotify watchers on both mnt1 and mnt2"
> +$INOTIFYWAIT_PROG -m -e create --format '%f' $mnt1 > $log1 2>&1 &
> +pid1=$!
> +$INOTIFYWAIT_PROG -m -e create --format '%f' $mnt2 > $log2 2>&1 &
> +pid2=$!
> +sleep 2
> +
> +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 inotify isolation"
> +kill $pid1 $pid2
> +wait $pid1 $pid2 2>/dev/null
> +pid1=""
> +pid2=""
> +
> +if grep -q "file_on_mnt1" $log1 && ! grep -q "file_on_mnt2" $log1; then
> + echo "SUCCESS: mnt1 events isolated."
> +else
> + echo "FAIL: mnt1 inotify confusion!"
> + [ ! -s $log1 ] && echo " - mnt1 received no events."
> + grep -q "file_on_mnt2" $log1 && echo " - mnt1 received event from mnt2."
> +fi
> +
> +if grep -q "file_on_mnt2" $log2 && ! grep -q "file_on_mnt1" $log2; then
> + echo "SUCCESS: mnt2 events isolated."
> +else
> + echo "FAIL: mnt2 inotify confusion!"
> + [ ! -s $log2 ] && echo " - mnt2 received no events."
> + grep -q "file_on_mnt1" $log2 && echo " - mnt2 received event from mnt1."
> +fi
> +
> +status=0
> +exit
> diff --git a/tests/generic/800.out b/tests/generic/800.out
> new file mode 100644
> index 000000000000..b10842a31210
> --- /dev/null
> +++ b/tests/generic/800.out
> @@ -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.
> --
> 2.43.0
>
^ permalink raw reply
* [PATCH] ext4: avoid BUG_ON() in ext4_get_inline_entry()
From: Vineet Agarwal @ 2026-04-27 16:20 UTC (permalink / raw)
To: linux-ext4, linux-kernel
Cc: tytso, adilger.kernel, libaokun1, jack, ojaswin, ritesh.list,
yi.zhang, Vineet Agarwal
Corrupted inline directory metadata can cause offset to exceed
the inline data size through rec_len processing in
empty_inline_dir().
This triggers BUG_ON() in ext4_get_inline_entry(), causing a
kernel panic before ext4_check_dir_entry() can handle the
corruption gracefully.
Replace BUG_ON() with a NULL return and handle the invalid
offset in the caller by emitting a warning and exiting safely.
This prevents a kernel panic from corrupted inline directory
metadata.
Signed-off-by: Vineet Agarwal <agarwal.vineet2006@gmail.com>
---
fs/ext4/inline.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index 8045e4ff270c..bca9936ed6d0 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -1718,7 +1718,8 @@ ext4_get_inline_entry(struct inode *inode,
{
void *inline_pos;
- BUG_ON(offset > ext4_get_inline_size(inode));
+ if (offset > ext4_get_inline_size(inode))
+ return NULL;
if (offset < EXT4_MIN_INLINE_DATA_SIZE) {
inline_pos = (void *)ext4_raw_inode(iloc)->i_block;
@@ -1773,6 +1774,12 @@ bool empty_inline_dir(struct inode *dir, int *has_inline_data)
while (offset < inline_len) {
de = ext4_get_inline_entry(dir, &iloc, offset,
&inline_pos, &inline_size);
+ if (!de) {
+ ext4_warning(dir->i_sb,
+ "bad inline directory (dir #%llu) - invalid offset",
+ dir->i_ino);
+ goto out;
+ }
if (ext4_check_dir_entry(dir, NULL, de,
iloc.bh, inline_pos,
inline_size, offset)) {
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v11 08/15] xfs: Report case sensitivity in fileattr_get
From: Darrick J. Wong @ 2026-04-27 15:56 UTC (permalink / raw)
To: Chuck Lever
Cc: Al Viro, Christian Brauner, Jan Kara, linux-fsdevel, linux-ext4,
linux-xfs, linux-cifs, linux-nfs, linux-api, linux-f2fs-devel,
hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever,
Roland Mainz
In-Reply-To: <20260424-case-sensitivity-v11-8-de5619beddaf@oracle.com>
On Fri, Apr 24, 2026 at 09:53:10PM -0400, Chuck Lever wrote:
> From: Chuck Lever <chuck.lever@oracle.com>
>
> Upper layers such as NFSD need to query whether a filesystem
> is case-sensitive. Add FS_XFLAG_CASEFOLD to xfs_ip2xflags()
> when the filesystem is formatted with the ASCIICI feature
> flag. This serves both FS_IOC_FSGETXATTR (via xfs_fill_fsxattr() in
> xfs_fileattr_get()) and XFS_IOC_BULKSTAT (which populates bs_xflags
> directly from xfs_ip2xflags()), so bulkstat consumers and per-inode
> queries see a consistent view of the filesystem's case-folding
> behavior.
>
> XFS always preserves case. XFS is case-sensitive by default, but
> supports ASCII case-insensitive lookups when formatted with the
> ASCIICI feature flag.
>
> Reviewed-by: Roland Mainz <roland.mainz@nrubsig.org>
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
> ---
> fs/xfs/libxfs/xfs_inode_util.c | 2 ++
> fs/xfs/xfs_ioctl.c | 7 +++++++
> 2 files changed, 9 insertions(+)
>
> diff --git a/fs/xfs/libxfs/xfs_inode_util.c b/fs/xfs/libxfs/xfs_inode_util.c
> index 551fa51befb6..82be54b6f8d3 100644
> --- a/fs/xfs/libxfs/xfs_inode_util.c
> +++ b/fs/xfs/libxfs/xfs_inode_util.c
> @@ -130,6 +130,8 @@ xfs_ip2xflags(
>
> if (xfs_inode_has_attr_fork(ip))
> flags |= FS_XFLAG_HASATTR;
> + if (xfs_has_asciici(ip->i_mount))
> + flags |= FS_XFLAG_CASEFOLD;
> return flags;
> }
>
> diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> index ed9b4846c05f..5a58fb0bad2b 100644
> --- a/fs/xfs/xfs_ioctl.c
> +++ b/fs/xfs/xfs_ioctl.c
> @@ -472,6 +472,13 @@ xfs_fill_fsxattr(
>
> fileattr_fill_xflags(fa, xfs_ip2xflags(ip));
>
> + /*
> + * FS_XFLAG_CASEFOLD is read-only; hide it from the legacy
> + * flags view so chattr's RMW cycle does not pass it back to
> + * xfs_fileattr_set().
> + */
> + fa->flags &= ~FS_CASEFOLD_FL;
I don't understand this at all. Yes, FS_XFLAG_CASEFOLD is readonly, but
how does clearing FS_CASEFOLD_FL from the fileattr_get output (without
clearing XFLAG_CASEFOLD!) solve anything? This makes the reported
output inconsistent between fsgetxattr and getflags -- one reports case
folding, the other reports no casefolding.
If you want to avoid fileattr_set returning EINVAL when setting
attributes due to the casefold flag, then don't you want to check the
flag state vs. xfs_has_asciici() in the *fileattr_set* path?
--D
> +
> if (ip->i_diflags & XFS_DIFLAG_EXTSIZE) {
> fa->fsx_extsize = XFS_FSB_TO_B(mp, ip->i_extsize);
> } else if (ip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) {
>
> --
> 2.53.0
>
>
^ permalink raw reply
* Re: [PATCH v11 00/15] Exposing case folding behavior
From: Jan Kara @ 2026-04-27 15:30 UTC (permalink / raw)
To: Chuck Lever
Cc: Jan Kara, Alexander Viro, Christian Brauner, linux-fsdevel,
linux-ext4, linux-xfs, linux-cifs, linux-nfs, linux-api,
linux-f2fs-devel, OGAWA Hirofumi, Namjae Jeon, Sungjong Seo,
Yuezhang Mo, almaz.alexandrovich, Viacheslav Dubeyko,
John Paul Adrian Glaubitz, frank.li, Theodore Tso, adilger.kernel,
Carlos Maiolino, Steve French, Paulo Alcantara, Ronnie Sahlberg,
Shyam Prasad N, Trond Myklebust, Anna Schumaker, Jaegeuk Kim,
Chao Yu, Hans de Goede, senozhatsky, Chuck Lever, Darrick J. Wong,
Roland Mainz, Steve French
In-Reply-To: <af3f7518-7501-4c25-9bbc-a8fc8cdb4e29@app.fastmail.com>
On Mon 27-04-26 09:30:28, Chuck Lever wrote:
>
> On Mon, Apr 27, 2026, at 6:55 AM, Jan Kara wrote:
> > On Fri 24-04-26 21:53:02, Chuck Lever wrote:
> >> Changes since v10:
> >> - cifs: Source case-handling flags from the server's cached
> >> FS_ATTRIBUTE_INFORMATION reply instead of the nocase mount
> >> option, with a nocase fallback when the reply is absent
> >> - Address findings from sashiko(gemini-3) and gpt-5.5:
> >> - nfs: Skip pathconf case bits on NFSv4 (set via FATTR4_CASE_*
> >> instead)
> >> - xfs: Hide FS_CASEFOLD_FL from the legacy flags view so
> >> chattr round-trips do not hit the setflags whitelist
> >> - ext4, f2fs: Drop redundant fileattr_get patches; the
> >> FS_CASEFOLD_FL translation in fileattr_fill_flags() already
> >> reports FS_XFLAG_CASEFOLD for casefolded directories
> >
> > Err, how is this supposed to work? I wasn't able to find any code
> > transforming S_CASEFOLDED inode flag into FS_CASEFOLD_FL on fileattr_get
> > path. Sure, fileattr_fill_flags() takes care of setting FS_XFLAG_CASEFOLD
> > once FS_CASEFOLD_FL is set. What am I missing?
>
> Agreed, that is a little surprising.
>
> The path does not go through S_CASEFOLD. Both filesystems
> report FS_CASEFOLD_FL straight from their on-disk flag word.
>
> For ext4, EXT4_CASEFOLD_FL is 0x40000000, the same bit value
> as FS_CASEFOLD_FL, and it is included in EXT4_FL_USER_VISIBLE.
> ext4_iget() loads it into ei->i_flags directly from
> raw_inode->i_flags (fs/ext4/inode.c:5358). ext4_fileattr_get()
> then masks with EXT4_FL_USER_VISIBLE and hands the result to
> fileattr_fill_flags(), which translates FS_CASEFOLD_FL into
> FS_XFLAG_CASEFOLD on the way out.
Oh, right. I've missed how EXT4_CASEFOLD_FL propagates into FS_CASEFOLD_FL.
Thanks for clearing that out.
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* Re: [PATCH v11 00/15] Exposing case folding behavior
From: Chuck Lever @ 2026-04-27 13:30 UTC (permalink / raw)
To: Jan Kara
Cc: Alexander Viro, Christian Brauner, linux-fsdevel, linux-ext4,
linux-xfs, linux-cifs, linux-nfs, linux-api, linux-f2fs-devel,
OGAWA Hirofumi, Namjae Jeon, Sungjong Seo, Yuezhang Mo,
almaz.alexandrovich, Viacheslav Dubeyko,
John Paul Adrian Glaubitz, frank.li, Theodore Tso, adilger.kernel,
Carlos Maiolino, Steve French, Paulo Alcantara, Ronnie Sahlberg,
Shyam Prasad N, Trond Myklebust, Anna Schumaker, Jaegeuk Kim,
Chao Yu, Hans de Goede, senozhatsky, Chuck Lever, Darrick J. Wong,
Roland Mainz, Steve French
In-Reply-To: <yc7ygk6w6zvf46arzzvmxnuoqjrni2dtlhmywaivzmvfxnilf3@xv7tthtrowns>
On Mon, Apr 27, 2026, at 6:55 AM, Jan Kara wrote:
> On Fri 24-04-26 21:53:02, Chuck Lever wrote:
>> Changes since v10:
>> - cifs: Source case-handling flags from the server's cached
>> FS_ATTRIBUTE_INFORMATION reply instead of the nocase mount
>> option, with a nocase fallback when the reply is absent
>> - Address findings from sashiko(gemini-3) and gpt-5.5:
>> - nfs: Skip pathconf case bits on NFSv4 (set via FATTR4_CASE_*
>> instead)
>> - xfs: Hide FS_CASEFOLD_FL from the legacy flags view so
>> chattr round-trips do not hit the setflags whitelist
>> - ext4, f2fs: Drop redundant fileattr_get patches; the
>> FS_CASEFOLD_FL translation in fileattr_fill_flags() already
>> reports FS_XFLAG_CASEFOLD for casefolded directories
>
> Err, how is this supposed to work? I wasn't able to find any code
> transforming S_CASEFOLDED inode flag into FS_CASEFOLD_FL on fileattr_get
> path. Sure, fileattr_fill_flags() takes care of setting FS_XFLAG_CASEFOLD
> once FS_CASEFOLD_FL is set. What am I missing?
Agreed, that is a little surprising.
The path does not go through S_CASEFOLD. Both filesystems
report FS_CASEFOLD_FL straight from their on-disk flag word.
For ext4, EXT4_CASEFOLD_FL is 0x40000000, the same bit value
as FS_CASEFOLD_FL, and it is included in EXT4_FL_USER_VISIBLE.
ext4_iget() loads it into ei->i_flags directly from
raw_inode->i_flags (fs/ext4/inode.c:5358). ext4_fileattr_get()
then masks with EXT4_FL_USER_VISIBLE and hands the result to
fileattr_fill_flags(), which translates FS_CASEFOLD_FL into
FS_XFLAG_CASEFOLD on the way out.
For f2fs, f2fs_fileattr_get() runs fi->i_flags through
f2fs_iflags_to_fsflags(), whose mapping table has an explicit
{ F2FS_CASEFOLD_FL, FS_CASEFOLD_FL } entry (fs/f2fs/file.c:2205).
F2FS_GETTABLE_FS_FL includes FS_CASEFOLD_FL, so
fileattr_fill_flags() again lights up FS_XFLAG_CASEFOLD.
S_CASEFOLD is a separate VFS-level cache that
ext4_set_inode_flags() and f2fs's equivalent set at iget
time; nothing on the fileattr_get path consults it.
For reference, the original observation about the manual
assignment being redundant came from sashiko's review of v10:
https://sashiko.dev/#/patchset/20260423-case-sensitivity-v10-0-c385d674a6cf%40oracle.com?part=8
https://sashiko.dev/#/patchset/20260423-case-sensitivity-v10-0-c385d674a6cf%40oracle.com?part=12
--
Chuck Lever
^ permalink raw reply
* Re: [PATCH v11 12/15] isofs: Implement fileattr_get for case sensitivity
From: Jan Kara @ 2026-04-27 13:30 UTC (permalink / raw)
To: Lionel Cons
Cc: Jan Kara, Chuck Lever, Al Viro, Christian Brauner, linux-fsdevel,
linux-ext4, linux-xfs, linux-cifs, linux-nfs, linux-api,
linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever,
Roland Mainz
In-Reply-To: <CAPJSo4WmRu_64TxBsaimWOqz3VAU0TZ1H-_hw36HSqzQULm39w@mail.gmail.com>
On Mon 27-04-26 14:02:00, Lionel Cons wrote:
> On Mon, 27 Apr 2026 at 12:47, Jan Kara <jack@suse.cz> wrote:
> >
> > On Fri 24-04-26 21:53:14, Chuck Lever wrote:
> > > From: Chuck Lever <chuck.lever@oracle.com>
> > >
> > > Upper layers such as NFSD need a way to query whether a
> > > filesystem handles filenames in a case-sensitive manner so
> > > they can provide correct semantics to remote clients. Without
> > > this information, NFS exports of ISO 9660 filesystems cannot
> > > advertise their filename case behavior.
> > >
> > > Implement isofs_fileattr_get() to report ISO 9660 case handling
> > > behavior via the FS_XFLAG_CASEFOLD flag. The 'check=r' (relaxed)
> > > mount option enables case-insensitive lookups, and this setting
> > > determines the value reported. By default, Joliet extensions
> > > operate in relaxed mode while plain ISO 9660 uses strict
> > > (case-sensitive) mode. All ISO 9660 variants are case-preserving,
> > > meaning filenames are stored exactly as they appear on the disc.
> > >
> > > Case handling is a superblock-wide property, so the callback
> > > must report the same value for every inode type. Regular files
> > > previously had no inode_operations; introduce
> > > isofs_file_inode_operations to carry the callback. Symlinks
> > > previously shared page_symlink_inode_operations; introduce
> > > isofs_symlink_inode_operations, which wires page_get_link
> > > alongside the callback, so that fileattr queries on a symlink
> > > reach the isofs implementation instead of returning
> > > -ENOIOCTLCMD. The flag is set in both fa->fsx_xflags and
> > > fa->flags so FS_IOC_FSGETXATTR and FS_IOC_GETFLAGS agree.
> > >
> > > Reviewed-by: Jan Kara <jack@suse.cz>
> > > Reviewed-by: Roland Mainz <roland.mainz@nrubsig.org>
> > > Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
> >
> > ...
> >
> > > @@ -281,6 +293,18 @@ const struct file_operations isofs_dir_operations =
> > > const struct inode_operations isofs_dir_inode_operations =
> > > {
> > > .lookup = isofs_lookup,
> > > + .fileattr_get = isofs_fileattr_get,
> > > +};
> > > +
> > > +const struct inode_operations isofs_file_inode_operations =
> > > +{
> > > + .fileattr_get = isofs_fileattr_get,
> > > +};
> > > +
> > > +const struct inode_operations isofs_symlink_inode_operations =
> > > +{
> > > + .get_link = page_get_link,
> > > + .fileattr_get = isofs_fileattr_get,
> > > };
> >
> > Hum, I thought casefolding is a directory attribute. At least I don't see
> > a big point in reporting it for regular files or symlinks (and then why not
> > report it for device nodes or named pipes?). So why did you decide for this
> > change?
>
> Where do you see this being a per-directory attribute in
> https://web.archive.org/web/20170404043745/http://www.ymi.com/ymi/sites/default/files/pdf/Rockridge.pdf
I wasn't refering to Rockridge standard but rather to the general way how
VFS tracks (and reports) casefolding.
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* Re: [PATCH v2] generic/790: test post-EOF gap zeroing persistence
From: Brian Foster @ 2026-04-27 13:03 UTC (permalink / raw)
To: Zhang Yi
Cc: fstests, zlang, linux-ext4, linux-fsdevel, jack, yi.zhang,
yizhang089, yangerkun
In-Reply-To: <038228d9-8058-43e0-8be9-b8afc9e8397c@huaweicloud.com>
On Sat, Apr 25, 2026 at 11:06:27AM +0800, Zhang Yi wrote:
> On 4/24/2026 9:09 PM, Brian Foster wrote:
> > On Fri, Apr 24, 2026 at 05:22:28PM +0800, Zhang Yi wrote:
> >> From: Zhang Yi <yi.zhang@huawei.com>
> >>
> >> Test that extending a file past a non-block-aligned EOF correctly
> >> zero-fills the gap [old_EOF, block_boundary), and that this zeroing
> >> persists through a filesystem shutdown+remount cycle.
> >>
> >> Stale data beyond EOF can persist on disk when append write data blocks
> >> are flushed before the on-disk file size update, or when concurrent
> >> append writeback and mmap writes persist non-zero data past EOF.
> >> Subsequent post-EOF operations (append write, fallocate, truncate up)
> >> must zero-fill and persist the gap to prevent exposing stale data.
> >>
> >> The test pollutes the file's last physical block (via FIEMAP + raw
> >> device write) with a sentinel pattern beyond i_size, then performs each
> >> extend operation and verifies the gap is zeroed both in memory and on
> >> disk.
> >>
> >> Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
> >> ---
> >> v1->v2:
> >> - Add _require_no_realtime to prevent testing on XFS realtime devices,
> >> where file data may reside on $SCRATCH_RTDEV.
> >> - Add _exclude_fs btrfs since FIEMAP returns logical addresses, not
> >> physical device offsets, writing to these offsets on $SCRATCH_DEV
> >> would corrupt the filesystem in multi-device setups. Besides, since
> >> btrfs doesn't support shutdown right now, we can support it later.
> >> - Add -v flag to od in _check_gap_zero() to prevent line folding of
> >> identical consecutive lines.
> >> - Add expected_new_sz parameter to _test_eof_zeroing(), verify file
> >> size was not rolled back after shutdown+remount cycle, and also drop
> >> the unnecessary file size check before the shutdown as well.
> >> - Clarify the comment regarding when stale data beyond EOF can persist.
> >>
> >
> > Thanks for the tweaks. This all LGTM from a review standpoint. I gave it
> > a quick test on latest master and I see a few failures in a couple runs:
> >
> > - On XFS (mkfs defaults) I saw one unexpected i_size failure and one
> > zeroing failure, both on write extension fwiw.
>
> Previously, I only discovered the zeroing failure of append write. This
> is because xfs_file_write_checks() -> xfs_file_write_zero_eof() only
> zeroes the gap range in the page cache, without providing any
> synchronous or asynchronous persistence (instead, truncate up does
> synchronously writeback in xfs_vn_setattr_size(), and ext4 achieves
> persistence via asynchronous writeback in data=ordered mode). So I think
> this is a XFS problem.
>
Ah Ok.. the truncate flush has been there for a while to combat the NULL
files problem, and the zeroing check ties into that. I suspect the
reason we don't see this often is typical ascending offset writeback
order, whereas this test is doing a targeted sync range of a later
offset in the file (i.e. technically not overlapping with the range that
was zeroed internally).
I guess the simple thing to do there would be to similarly flush on
write extension. I'd want to think about that just a bit because we
haven't historically flushed there and I know the zeroing improvements
I've made in iomap have caused a couple performance regressions along
the way related to aggressive flushing that had to be fixed.
Maybe this is less of an issue now, but regardless if my assumptions are
correct here than I agree this isn't a test issue.
> Regarding the i_size failure, I did not directly reproduce this issue.
> After analysis, I believe it is because the test case did not include
> the -a option in sync_range, meaning it did not wait for IO writeback
> completion and file size update persistence. I reproduced this issue by
> adding a delay in the XFS end IO path. This is a problem with the test
> case, and I will fix it in v3. Thank you for pointing this out.
>
Makes sense. It will be interesting to see if we can still reproduce the
above issue with this change.
> > - On ext4 I saw a few unexpected i_size failures (both with mkfs
> > defaults and 1k block size).
> >
>
> This is an ext4 issue on the shutdown path. Since ext4 set the shutdown
> flag too early, it was unable to write back ordered zero data when
> flushing the journal, which led to a journal abort and prevented the file
> size update from being persisted. I have submitted a patch to fix this
> issue. Please see below link for details.
>
> https://lore.kernel.org/linux-ext4/20260424104201.1930823-1-yi.zhang@huaweicloud.com/
>
Ok, thanks.
Brian
> Thanks
> Yi.
>
> > I haven't dug into anything beyond that. Does this match what you're
> > seeing on current kernels or are these unexpected failures?
> >
> > Brian
> >
> >> tests/generic/790 | 164 ++++++++++++++++++++++++++++++++++++++++++
> >> tests/generic/790.out | 4 ++
> >> 2 files changed, 168 insertions(+)
> >> create mode 100755 tests/generic/790
> >> create mode 100644 tests/generic/790.out
> >>
> >> diff --git a/tests/generic/790 b/tests/generic/790
> >> new file mode 100755
> >> index 00000000..2adc06f8
> >> --- /dev/null
> >> +++ b/tests/generic/790
> >> @@ -0,0 +1,164 @@
> >> +#! /bin/bash
> >> +# SPDX-License-Identifier: GPL-2.0
> >> +# Copyright (c) 2026 Huawei. All Rights Reserved.
> >> +#
> >> +# FS QA Test No. 790
> >> +#
> >> +# Test that extending a file past a non-block-aligned EOF correctly zero-fills
> >> +# the gap [old_EOF, block_boundary), and that this zeroing persists through a
> >> +# filesystem shutdown+remount cycle.
> >> +#
> >> +# Stale data beyond EOF can persist on disk when:
> >> +# 1) append write data blocks are flushed before the on-disk file size update,
> >> +# and the system crashes in this window.
> >> +# 2) concurrent append writeback and mmap writes persist non-zero data past EOF.
> >> +#
> >> +# Subsequent post-EOF operations (append write, fallocate, truncate up) must
> >> +# zero-fill and persist the gap to prevent exposing stale data.
> >> +#
> >> +# The test pollutes the file's last physical block (via FIEMAP + raw device
> >> +# write) with a sentinel pattern beyond i_size, then performs each extend
> >> +# operation and verifies the gap is zeroed both in memory and on disk.
> >> +#
> >> +. ./common/preamble
> >> +_begin_fstest auto quick rw shutdown
> >> +
> >> +. ./common/filter
> >> +
> >> +_require_scratch
> >> +_require_block_device $SCRATCH_DEV
> >> +_require_no_realtime
> >> +_require_scratch_shutdown
> >> +_require_metadata_journaling $SCRATCH_DEV
> >> +
> >> +# FIEMAP on Btrfs returns logical addresses within the filesystem's address
> >> +# space, not physical device offsets. Writing to these offsets on $SCRATCH_DEV
> >> +# would corrupt the filesystem in multi-device setups.
> >> +_exclude_fs btrfs
> >> +
> >> +_require_xfs_io_command "fiemap"
> >> +_require_xfs_io_command "falloc"
> >> +_require_xfs_io_command "pwrite"
> >> +_require_xfs_io_command "truncate"
> >> +_require_xfs_io_command "sync_range"
> >> +
> >> +# Check that gap region [offset, offset+nbytes) is entirely zero
> >> +_check_gap_zero()
> >> +{
> >> + local file="$1"
> >> + local offset="$2"
> >> + local nbytes="$3"
> >> + local label="$4"
> >> + local data
> >> + local stripped
> >> +
> >> + data=$(od -A n -t x1 -v -j $offset -N $nbytes "$file" 2>/dev/null)
> >> +
> >> + # Remove whitespace and check if any byte is non-zero
> >> + stripped=$(printf '%s' "$data" | tr -d ' \n\t')
> >> + if [ -n "$stripped" ] && ! echo "$stripped" | grep -qE "^0+$"; then
> >> + echo "FAIL: non-zero data in gap [$offset,$((offset + nbytes))) $label"
> >> + _hexdump -N $((offset + nbytes)) "$file"
> >> + return 1
> >> + fi
> >> + return 0
> >> +}
> >> +
> >> +# Get the physical block offset (in bytes) of the file's first block on device
> >> +_get_phys_offset()
> >> +{
> >> + local file="$1"
> >> + local fiemap_output
> >> + local phys_blk
> >> +
> >> + fiemap_output=$($XFS_IO_PROG -r -c "fiemap -v" "$file" 2>/dev/null)
> >> + phys_blk=$(echo "$fiemap_output" | _filter_xfs_io_fiemap | head -1 | awk '{print $3}')
> >> + if [ -z "$phys_blk" ]; then
> >> + echo ""
> >> + return
> >> + fi
> >> + # Convert 512-byte blocks to bytes
> >> + echo $((phys_blk * 512))
> >> +}
> >> +
> >> +_test_eof_zeroing()
> >> +{
> >> + local test_name="$1"
> >> + local extend_cmd="$2"
> >> + local expected_new_sz="$3"
> >> + local file=$SCRATCH_MNT/testfile_${test_name}
> >> +
> >> + echo "$test_name" | tee -a $seqres.full
> >> +
> >> + # Compute non-block-aligned EOF offset
> >> + local gap_bytes=16
> >> + local eof_offset=$((blksz - gap_bytes))
> >> +
> >> + # Step 1: Write one full block to ensure the filesystem allocates a
> >> + # physical block for the file instead of using inline data.
> >> + $XFS_IO_PROG -f -c "pwrite -S 0x5a 0 $blksz" -c fsync \
> >> + "$file" >> $seqres.full 2>&1
> >> +
> >> + # Step 2: Get physical block offset on device via FIEMAP
> >> + local phys_offset
> >> + phys_offset=$(_get_phys_offset "$file")
> >> + if [ -z "$phys_offset" ]; then
> >> + _fail "$test_name: failed to get physical block offset via fiemap"
> >> + fi
> >> +
> >> + # Step 3: Truncate file to non-block-aligned size and fsync.
> >> + # The on-disk region [eof_offset, blksz) may or may not be
> >> + # zeroed by the filesystem at this point.
> >> + $XFS_IO_PROG -c "truncate $eof_offset" -c fsync \
> >> + "$file" >> $seqres.full 2>&1
> >> +
> >> + # Step 4: Unmount and restore the physical block to all-0x5a on disk.
> >> + # This bypasses the kernel's pagecache EOF-zeroing to ensure
> >> + # the stale pattern is present on disk. Then remount.
> >> + _scratch_unmount
> >> + $XFS_IO_PROG -d -c "pwrite -S 0x5a $phys_offset $blksz" \
> >> + $SCRATCH_DEV >> $seqres.full 2>&1
> >> + _scratch_mount >> $seqres.full 2>&1
> >> +
> >> + # Step 5: Execute the extend operation.
> >> + $XFS_IO_PROG -c "$extend_cmd" "$file" >> $seqres.full 2>&1
> >> +
> >> + # Step 6: Verify gap [eof_offset, blksz) is zeroed BEFORE shutdown
> >> + _check_gap_zero "$file" $eof_offset $gap_bytes "before shutdown" || return 1
> >> +
> >> + # Step 7: Sync the extended range and shutdown the filesystem with
> >> + # journal flush. This persists the file size extending, and
> >> + # the filesystem should persist the zeroed data in the gap
> >> + # range as well.
> >> + if [ "$extend_cmd" != "${extend_cmd#pwrite}" ]; then
> >> + $XFS_IO_PROG -c "sync_range -w $blksz $blksz" \
> >> + "$file" >> $seqres.full 2>&1
> >> + fi
> >> + _scratch_shutdown -f
> >> +
> >> + # Step 8: Remount and verify gap is still zeroed
> >> + _scratch_cycle_mount
> >> +
> >> + # Verify file size was not rolled back after shutdown+remount
> >> + local sz
> >> + sz=$(stat -c %s "$file")
> >> + if [ "$sz" -ne "$expected_new_sz" ]; then
> >> + _fail "$test_name: file size rolled back after shutdown+remount: $sz != $expected_new_sz"
> >> + fi
> >> +
> >> + _check_gap_zero "$file" $eof_offset $gap_bytes "after shutdown+remount" || return 1
> >> +}
> >> +
> >> +_scratch_mkfs >> $seqres.full 2>&1
> >> +_scratch_mount
> >> +
> >> +blksz=$(_get_block_size $SCRATCH_MNT)
> >> +
> >> +# Test three variants of EOF-extending operations
> >> +_test_eof_zeroing "append_write" "pwrite -S 0x42 $blksz $blksz" $((blksz * 2))
> >> +_test_eof_zeroing "truncate_up" "truncate $((blksz * 2))" $((blksz * 2))
> >> +_test_eof_zeroing "fallocate" "falloc $blksz $blksz" $((blksz * 2))
> >> +
> >> +# success, all done
> >> +status=0
> >> +exit
> >> diff --git a/tests/generic/790.out b/tests/generic/790.out
> >> new file mode 100644
> >> index 00000000..e5e2cc09
> >> --- /dev/null
> >> +++ b/tests/generic/790.out
> >> @@ -0,0 +1,4 @@
> >> +QA output created by 790
> >> +append_write
> >> +truncate_up
> >> +fallocate
> >> --
> >> 2.52.0
> >>
>
^ permalink raw reply
* Re: [PATCH v11 12/15] isofs: Implement fileattr_get for case sensitivity
From: Lionel Cons @ 2026-04-27 12:02 UTC (permalink / raw)
To: Jan Kara
Cc: Chuck Lever, Al Viro, Christian Brauner, linux-fsdevel,
linux-ext4, linux-xfs, linux-cifs, linux-nfs, linux-api,
linux-f2fs-devel, hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever,
Roland Mainz
In-Reply-To: <isfgwmd5hxjfn7dj7p54yzlhumx2hrkt3zw7fscs2ywm57g3hu@co27drpx24lq>
On Mon, 27 Apr 2026 at 12:47, Jan Kara <jack@suse.cz> wrote:
>
> On Fri 24-04-26 21:53:14, Chuck Lever wrote:
> > From: Chuck Lever <chuck.lever@oracle.com>
> >
> > Upper layers such as NFSD need a way to query whether a
> > filesystem handles filenames in a case-sensitive manner so
> > they can provide correct semantics to remote clients. Without
> > this information, NFS exports of ISO 9660 filesystems cannot
> > advertise their filename case behavior.
> >
> > Implement isofs_fileattr_get() to report ISO 9660 case handling
> > behavior via the FS_XFLAG_CASEFOLD flag. The 'check=r' (relaxed)
> > mount option enables case-insensitive lookups, and this setting
> > determines the value reported. By default, Joliet extensions
> > operate in relaxed mode while plain ISO 9660 uses strict
> > (case-sensitive) mode. All ISO 9660 variants are case-preserving,
> > meaning filenames are stored exactly as they appear on the disc.
> >
> > Case handling is a superblock-wide property, so the callback
> > must report the same value for every inode type. Regular files
> > previously had no inode_operations; introduce
> > isofs_file_inode_operations to carry the callback. Symlinks
> > previously shared page_symlink_inode_operations; introduce
> > isofs_symlink_inode_operations, which wires page_get_link
> > alongside the callback, so that fileattr queries on a symlink
> > reach the isofs implementation instead of returning
> > -ENOIOCTLCMD. The flag is set in both fa->fsx_xflags and
> > fa->flags so FS_IOC_FSGETXATTR and FS_IOC_GETFLAGS agree.
> >
> > Reviewed-by: Jan Kara <jack@suse.cz>
> > Reviewed-by: Roland Mainz <roland.mainz@nrubsig.org>
> > Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
>
> ...
>
> > @@ -281,6 +293,18 @@ const struct file_operations isofs_dir_operations =
> > const struct inode_operations isofs_dir_inode_operations =
> > {
> > .lookup = isofs_lookup,
> > + .fileattr_get = isofs_fileattr_get,
> > +};
> > +
> > +const struct inode_operations isofs_file_inode_operations =
> > +{
> > + .fileattr_get = isofs_fileattr_get,
> > +};
> > +
> > +const struct inode_operations isofs_symlink_inode_operations =
> > +{
> > + .get_link = page_get_link,
> > + .fileattr_get = isofs_fileattr_get,
> > };
>
> Hum, I thought casefolding is a directory attribute. At least I don't see
> a big point in reporting it for regular files or symlinks (and then why not
> report it for device nodes or named pipes?). So why did you decide for this
> change?
Where do you see this being a per-directory attribute in
https://web.archive.org/web/20170404043745/http://www.ymi.com/ymi/sites/default/files/pdf/Rockridge.pdf
Lionel
^ permalink raw reply
* Re: [PATCH] ext4: fix LOGFLUSH shutdown ordering to allow ordered-mode data writeback
From: Baokun Li @ 2026-04-27 11:23 UTC (permalink / raw)
To: Zhang Yi
Cc: linux-ext4, linux-fsdevel, linux-kernel, tytso, adilger.kernel,
jack, ojaswin, ritesh.list, yi.zhang, yizhang089, yangerkun,
yukuai
In-Reply-To: <20260424104201.1930823-1-yi.zhang@huaweicloud.com>
On 2026/4/24 18:42, Zhang Yi wrote:
> From: Zhang Yi <yi.zhang@huawei.com>
>
> In EXT4_GOING_FLAGS_LOGFLUSH mode, the EXT4_FLAGS_SHUTDOWN flag was set
> before calling ext4_force_commit(). This caused ordered-mode data
> writeback (triggered by journal commit) to fail with -EIO, since
> ext4_do_writepages() checks for the shutdown flag. The journal would
> then be aborted prematurely before the commit could succeed.
>
> Fix this by calling ext4_force_commit() first, then setting the
> shutdown flag, so that pending data can be written back correctly.
>
> Note that moving ext4_force_commit() before setting the shutdown flag
> creates a small window in which new writes may occur and generate new
> journal transactions. When the journal is subsequently aborted, the
> new transactions will not be able to write to disk. This is intentional
> because LOGFLUSH's semantics are to flush pre-existing journal entries
> before shutdown, not to guarantee atomicity for writes that race with
> the ioctl.
>
> Fixes: 783d94854499 ("ext4: add EXT4_IOC_GOINGDOWN ioctl")
> Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
Looks good to me.
Reviewed-by: Baokun Li <libaokun@linux.alibaba.com>
> ---
> This fix addresses my new generic/970 test, which fails during the file
> size verification after shutdown and remount.
>
> https://lore.kernel.org/fstests/20260424092228.1396658-1-yi.zhang@huaweicloud.com/
>
> fs/ext4/ioctl.c | 12 +++++++++---
> 1 file changed, 9 insertions(+), 3 deletions(-)
>
> diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
> index 1d0c3d4bdf47..110e3fb194ec 100644
> --- a/fs/ext4/ioctl.c
> +++ b/fs/ext4/ioctl.c
> @@ -830,11 +830,17 @@ int ext4_force_shutdown(struct super_block *sb, u32 flags)
> bdev_thaw(sb->s_bdev);
> break;
> case EXT4_GOING_FLAGS_LOGFLUSH:
> + /*
> + * Call ext4_force_commit() before setting EXT4_FLAGS_SHUTDOWN.
> + * This is because in data=ordered mode, journal commit
> + * triggers data writeback which fails if shutdown is already
> + * set, causing the journal to be aborted prematurely before
> + * the commit succeeds.
> + */
> + (void) ext4_force_commit(sb);
> set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
> - if (sbi->s_journal && !is_journal_aborted(sbi->s_journal)) {
> - (void) ext4_force_commit(sb);
> + if (sbi->s_journal && !is_journal_aborted(sbi->s_journal))
> jbd2_journal_abort(sbi->s_journal, -ESHUTDOWN);
> - }
> break;
> case EXT4_GOING_FLAGS_NOLOGFLUSH:
> set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags);
^ permalink raw reply
* Re: [BUG] ext4: BUG_ON in ext4_write_inline_data (fs/ext4/inline.c:240)
From: Jan Kara @ 2026-04-27 11:17 UTC (permalink / raw)
To: Demi Marie Obenour
Cc: Theodore Tso, Zw Tang, Andreas Dilger, libaokun, jack, ojaswin,
linux-ext4, linux-kernel, yi.zhang, syzkaller-bugs
In-Reply-To: <4e76eb68-862d-4b9f-8242-e6aced2704ee@gmail.com>
On Sat 25-04-26 14:00:23, Demi Marie Obenour wrote:
> On 4/21/26 08:20, Theodore Tso wrote:
> > On Tue, Apr 21, 2026 at 07:32:43PM +0800, Zw Tang wrote:
> >> This looks like an ext4 inline-data boundary/state inconsistency triggered
> >> while writing to an ext4 image crafted by syzkaller. The later
> >> KASAN: slab-use-after-free in rwsem_down_write_slowpath() appears to be a
> >> secondary effect after the primary ext4 BUG, likely during teardown/unlink
> >> after the filesystem failure.
> >
> > Writing to a mounted image is not something that we consider a valid
> > threat model. If you can write to a mounted image, there are a
> > zillion different ways that you can creash the kernel, or you can
> > create a setuid shell, etc.
> >
> > The upstream syzkaller bot makes sure that CONFIG_BLK_DEV_WRITE_MOUNTED
> > is not defined to avoid syzkaller noise.
>
> CONFIG_BLK_DEV_WRITE_MOUNTED only blocks writing via the specific block
> device that is mounted. It doesn't block writing via other methods.
> If I recall correctly, its purpose was to prevent writing to the
> buffer cache used by the filesystem driver.
Correct. This a kind of corruption that's impossible to address only at fs
level.
> Changing block devices that are mounted is also reachable via USB.
> Yes, some distros may disable automount, but users who have stuff to
> get done will mount USB devices anyway. Telling users "don't do this"
> very rarely works in practice.
>
> I asked a distro maintainer about using libguestfs by default and
> they refused, citing poor performance. Unfortunately, there is no
> way at the OS level to distinguish "trusted device used for backups"
> and "untrusted USB stick".
Well, people *are* seriously looking into mounting hotpluggable devices with
FUSE (or other userspace means) - e.g. openSUSE has experimental packages
doing just that for a few months. Darrick Wong is also working on making
FUSE more performant so the plan is to eventually get there.
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* Re: [PATCH v11 00/15] Exposing case folding behavior
From: Jan Kara @ 2026-04-27 10:55 UTC (permalink / raw)
To: Chuck Lever
Cc: Al Viro, Christian Brauner, Jan Kara, linux-fsdevel, linux-ext4,
linux-xfs, linux-cifs, linux-nfs, linux-api, linux-f2fs-devel,
hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever,
Darrick J. Wong, Roland Mainz, Steve French
In-Reply-To: <20260424-case-sensitivity-v11-0-de5619beddaf@oracle.com>
On Fri 24-04-26 21:53:02, Chuck Lever wrote:
> Changes since v10:
> - cifs: Source case-handling flags from the server's cached
> FS_ATTRIBUTE_INFORMATION reply instead of the nocase mount
> option, with a nocase fallback when the reply is absent
> - Address findings from sashiko(gemini-3) and gpt-5.5:
> - nfs: Skip pathconf case bits on NFSv4 (set via FATTR4_CASE_*
> instead)
> - xfs: Hide FS_CASEFOLD_FL from the legacy flags view so
> chattr round-trips do not hit the setflags whitelist
> - ext4, f2fs: Drop redundant fileattr_get patches; the
> FS_CASEFOLD_FL translation in fileattr_fill_flags() already
> reports FS_XFLAG_CASEFOLD for casefolded directories
Err, how is this supposed to work? I wasn't able to find any code
transforming S_CASEFOLDED inode flag into FS_CASEFOLD_FL on fileattr_get
path. Sure, fileattr_fill_flags() takes care of setting FS_XFLAG_CASEFOLD
once FS_CASEFOLD_FL is set. What am I missing?
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* Re: [PATCH v11 12/15] isofs: Implement fileattr_get for case sensitivity
From: Jan Kara @ 2026-04-27 10:44 UTC (permalink / raw)
To: Chuck Lever
Cc: Al Viro, Christian Brauner, Jan Kara, linux-fsdevel, linux-ext4,
linux-xfs, linux-cifs, linux-nfs, linux-api, linux-f2fs-devel,
hirofumi, linkinjeon, sj1557.seo, yuezhang.mo,
almaz.alexandrovich, slava, glaubitz, frank.li, tytso,
adilger.kernel, cem, sfrench, pc, ronniesahlberg, sprasad,
trondmy, anna, jaegeuk, chao, hansg, senozhatsky, Chuck Lever,
Roland Mainz
In-Reply-To: <20260424-case-sensitivity-v11-12-de5619beddaf@oracle.com>
On Fri 24-04-26 21:53:14, Chuck Lever wrote:
> From: Chuck Lever <chuck.lever@oracle.com>
>
> Upper layers such as NFSD need a way to query whether a
> filesystem handles filenames in a case-sensitive manner so
> they can provide correct semantics to remote clients. Without
> this information, NFS exports of ISO 9660 filesystems cannot
> advertise their filename case behavior.
>
> Implement isofs_fileattr_get() to report ISO 9660 case handling
> behavior via the FS_XFLAG_CASEFOLD flag. The 'check=r' (relaxed)
> mount option enables case-insensitive lookups, and this setting
> determines the value reported. By default, Joliet extensions
> operate in relaxed mode while plain ISO 9660 uses strict
> (case-sensitive) mode. All ISO 9660 variants are case-preserving,
> meaning filenames are stored exactly as they appear on the disc.
>
> Case handling is a superblock-wide property, so the callback
> must report the same value for every inode type. Regular files
> previously had no inode_operations; introduce
> isofs_file_inode_operations to carry the callback. Symlinks
> previously shared page_symlink_inode_operations; introduce
> isofs_symlink_inode_operations, which wires page_get_link
> alongside the callback, so that fileattr queries on a symlink
> reach the isofs implementation instead of returning
> -ENOIOCTLCMD. The flag is set in both fa->fsx_xflags and
> fa->flags so FS_IOC_FSGETXATTR and FS_IOC_GETFLAGS agree.
>
> Reviewed-by: Jan Kara <jack@suse.cz>
> Reviewed-by: Roland Mainz <roland.mainz@nrubsig.org>
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
...
> @@ -281,6 +293,18 @@ const struct file_operations isofs_dir_operations =
> const struct inode_operations isofs_dir_inode_operations =
> {
> .lookup = isofs_lookup,
> + .fileattr_get = isofs_fileattr_get,
> +};
> +
> +const struct inode_operations isofs_file_inode_operations =
> +{
> + .fileattr_get = isofs_fileattr_get,
> +};
> +
> +const struct inode_operations isofs_symlink_inode_operations =
> +{
> + .get_link = page_get_link,
> + .fileattr_get = isofs_fileattr_get,
> };
Hum, I thought casefolding is a directory attribute. At least I don't see
a big point in reporting it for regular files or symlinks (and then why not
report it for device nodes or named pipes?). So why did you decide for this
change?
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* [PATCH v3 9/9] fstests: btrfs: test UUID consistency for clones with metadata_uuid
From: Anand Jain @ 2026-04-27 10:19 UTC (permalink / raw)
To: fstests
Cc: linux-btrfs, linux-ext4, linux-xfs, linux-f2fs, amir73il, zlang,
hch
In-Reply-To: <cover.1777281778.git.asj@kernel.org>
Btrfs 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.
Signed-off-by: Anand Jain <asj@kernel.org>
---
tests/btrfs/348 | 91 +++++++++++++++++++++++++++++++++++++++++++++
tests/btrfs/348.out | 19 ++++++++++
2 files changed, 110 insertions(+)
create mode 100644 tests/btrfs/348
create mode 100644 tests/btrfs/348.out
diff --git a/tests/btrfs/348 b/tests/btrfs/348
new file mode 100644
index 000000000000..cfa56fdb4a4a
--- /dev/null
+++ b/tests/btrfs/348
@@ -0,0 +1,91 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2026 Anand Jain <asj@kernel.org>. All Rights Reserved.
+#
+# FS QA Test 348
+#
+# 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_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
+}
+
+pre_clone_tune()
+{
+ local temp_mnt=$TEST_DIR/${seq}_mnt
+
+ _require_command "$BTRFS_TUNE_PROG" btrfstune
+ mkdir -p $temp_mnt
+ _mount ${devs[0]} $temp_mnt
+ $BTRFS_UTIL_PROG subvolume create $temp_mnt/sv1 &> /dev/null
+ _unmount $temp_mnt
+ rm -r -f $temp_mnt
+
+ $BTRFS_TUNE_PROG -m ${devs[0]}
+}
+
+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
+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
diff --git a/tests/btrfs/348.out b/tests/btrfs/348.out
new file mode 100644
index 000000000000..4b102e986246
--- /dev/null
+++ b/tests/btrfs/348.out
@@ -0,0 +1,19 @@
+QA output created by 348
+
+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
--
2.43.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox