File tst_detach_device_Clear_leftover_partitions.patch of Package ltp-stable
From 70cc4ab9a5febaec1c841f021c625f0d0ef72a09 Mon Sep 17 00:00:00 2001
From: Martin Doucha <mdoucha@suse.cz>
Date: Fri, 12 Dec 2025 11:40:23 +0100
Subject: [PATCH] tst_detach_device: Clear leftover partitions
Some kernels have a race condition during loop device release
which results in partitions being left over on unattached device.
The partitions then cause mkfs.vfat failures in later tests.
Check for loop device partitions after detaching it and clear them
if necessary.
Signed-off-by: Martin Doucha <mdoucha@suse.cz>
Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
lib/tst_device.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 78 insertions(+), 1 deletion(-)
diff --git a/lib/tst_device.c b/lib/tst_device.c
index 6ae914720a2..85f5f8cac32 100644
--- a/lib/tst_device.c
+++ b/lib/tst_device.c
@@ -239,7 +239,7 @@ uint64_t tst_get_device_size(const char *dev_path)
return size/1024/1024;
}
-int tst_detach_device_by_fd(const char *dev, int *dev_fd)
+static int detach_loop_fd(const char *dev, int *dev_fd)
{
int ret, i, retval = 1;
@@ -275,6 +275,83 @@ int tst_detach_device_by_fd(const char *dev, int *dev_fd)
return retval;
}
+static int find_loop_device_partition(const char *dev, char *part_path,
+ unsigned int path_size)
+{
+ int dev_num = -1;
+ unsigned int i;
+
+ snprintf(part_path, path_size, "%sp1", dev);
+
+ if (!access(part_path, F_OK))
+ return 1;
+
+ /* Parse loop device number */
+ for (i = 0; i < ARRAY_SIZE(dev_loop_variants); i++) {
+ if (sscanf(dev, dev_loop_variants[i], &dev_num) == 1)
+ break;
+
+ dev_num = -1;
+ }
+
+ if (dev_num < 0) {
+ tst_resm(TWARN, "Cannot parse %s device number", dev);
+ return 0;
+ }
+
+ snprintf(part_path, path_size, "/sys/block/loop%d/loop%dp1", dev_num,
+ dev_num);
+
+ if (!access(part_path, F_OK))
+ return 1;
+
+ /* The loop device has no leftover partitions */
+ return 0;
+}
+
+static int clear_loop_device_partitions(const char *dev)
+{
+ char part_path[PATH_MAX];
+ struct loop_info loopinfo = {};
+ int dev_fd;
+
+ if (!find_loop_device_partition(dev, part_path, PATH_MAX))
+ return 0;
+
+ tst_resm(TWARN, "Detached device %s has leftover partitions", dev);
+ tst_fill_file(DEV_FILE, 0, 1024 * 1024, 1);
+ tst_attach_device(dev, DEV_FILE);
+ dev_fd = open(dev, O_RDWR);
+
+ if (dev_fd < 0) {
+ tst_resm(TWARN | TERRNO,
+ "Cannot clear leftover partitions on %s", dev);
+ /* Do not detach device to prevent infinite recursion */
+ return 1;
+ }
+
+ loopinfo.lo_flags = LO_FLAGS_PARTSCAN;
+ ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo);
+
+ if (!access(part_path, F_OK)) {
+ tst_resm(TWARN, "Cannot clear leftover partitions on %s", dev);
+ detach_loop_fd(dev, &dev_fd);
+ return 1;
+ }
+
+ return detach_loop_fd(dev, &dev_fd);
+}
+
+int tst_detach_device_by_fd(const char *dev, int *dev_fd)
+{
+ int ret = detach_loop_fd(dev, dev_fd);
+
+ if (!ret)
+ ret = clear_loop_device_partitions(dev);
+
+ return ret;
+}
+
int tst_detach_device(const char *dev)
{
int dev_fd, ret;