[PATCH v8 01/13] fstests: add _loop_image_create_clone() helper

Anand Jain <[email protected]> Sat, 25 Jul 2026 15:38:58 +0800
Newsgroups org.kernel.vger.fstests,net.sourceforge.lists.linux-f2fs-devel,org.kernel.vger.linux-btrfs,org.kernel.vger.linux-ext4,org.kernel.vger.linux-xfs
Message-ID <4fa4f6bc500e0496e3d8598d38cf69597493a25b.1784949154.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 <[email protected]>
---
 common/rc | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/common/rc b/common/rc
index 106f044adc2d..e8ff5be0c547 100644
--- a/common/rc
+++ b/common/rc
@@ -1520,6 +1520,71 @@ _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.
+_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=()
+
+	# 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"
+
+	loop_devs=("$(_create_loop_device $img_file)")
+
+	case $FSTYP in
+	xfs)
+		_mkfs_dev -s size=4096 "${loop_devs[0]}"
+		;;
+	btrfs)
+		_mkfs_dev "${loop_devs[0]}"
+		;;
+	*)
+		_mkfs_dev "${loop_devs[0]}"
+		;;
+	esac
+
+	# Only execute if the function argument is not empty
+	if [ -n "$pre_clone_tune_func" ]; then
+		$pre_clone_tune_func "${loop_devs[0]}"
+	fi
+
+	sync "${loop_devs[0]}"
+	cp $img_file $img_file_clone || _fail "Failed to copy cloned image"
+
+	loop_devs+=("$(_create_loop_device $img_file_clone)")
+
+	_ret=()
+	for i in "${loop_devs[@]}"; do
+		_ret+=("$i")
+	done
+}
+
+# Teardown loop devices and delete their underlying backing image files.
+# Accepts a list of loop device paths (e.g., /dev/loop0 /dev/loop1).
+_loop_image_destroy()
+{
+	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
-- 
2.43.0