Skip to content

Commit 70cc4ab

Browse files
mdouchaacerv
authored andcommitted
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>
1 parent 22fc4a9 commit 70cc4ab

File tree

1 file changed

+78
-1
lines changed

1 file changed

+78
-1
lines changed

lib/tst_device.c

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ uint64_t tst_get_device_size(const char *dev_path)
239239
return size/1024/1024;
240240
}
241241

242-
int tst_detach_device_by_fd(const char *dev, int *dev_fd)
242+
static int detach_loop_fd(const char *dev, int *dev_fd)
243243
{
244244
int ret, i, retval = 1;
245245

@@ -275,6 +275,83 @@ int tst_detach_device_by_fd(const char *dev, int *dev_fd)
275275
return retval;
276276
}
277277

278+
static int find_loop_device_partition(const char *dev, char *part_path,
279+
unsigned int path_size)
280+
{
281+
int dev_num = -1;
282+
unsigned int i;
283+
284+
snprintf(part_path, path_size, "%sp1", dev);
285+
286+
if (!access(part_path, F_OK))
287+
return 1;
288+
289+
/* Parse loop device number */
290+
for (i = 0; i < ARRAY_SIZE(dev_loop_variants); i++) {
291+
if (sscanf(dev, dev_loop_variants[i], &dev_num) == 1)
292+
break;
293+
294+
dev_num = -1;
295+
}
296+
297+
if (dev_num < 0) {
298+
tst_resm(TWARN, "Cannot parse %s device number", dev);
299+
return 0;
300+
}
301+
302+
snprintf(part_path, path_size, "/sys/block/loop%d/loop%dp1", dev_num,
303+
dev_num);
304+
305+
if (!access(part_path, F_OK))
306+
return 1;
307+
308+
/* The loop device has no leftover partitions */
309+
return 0;
310+
}
311+
312+
static int clear_loop_device_partitions(const char *dev)
313+
{
314+
char part_path[PATH_MAX];
315+
struct loop_info loopinfo = {};
316+
int dev_fd;
317+
318+
if (!find_loop_device_partition(dev, part_path, PATH_MAX))
319+
return 0;
320+
321+
tst_resm(TWARN, "Detached device %s has leftover partitions", dev);
322+
tst_fill_file(DEV_FILE, 0, 1024 * 1024, 1);
323+
tst_attach_device(dev, DEV_FILE);
324+
dev_fd = open(dev, O_RDWR);
325+
326+
if (dev_fd < 0) {
327+
tst_resm(TWARN | TERRNO,
328+
"Cannot clear leftover partitions on %s", dev);
329+
/* Do not detach device to prevent infinite recursion */
330+
return 1;
331+
}
332+
333+
loopinfo.lo_flags = LO_FLAGS_PARTSCAN;
334+
ioctl(dev_fd, LOOP_SET_STATUS, &loopinfo);
335+
336+
if (!access(part_path, F_OK)) {
337+
tst_resm(TWARN, "Cannot clear leftover partitions on %s", dev);
338+
detach_loop_fd(dev, &dev_fd);
339+
return 1;
340+
}
341+
342+
return detach_loop_fd(dev, &dev_fd);
343+
}
344+
345+
int tst_detach_device_by_fd(const char *dev, int *dev_fd)
346+
{
347+
int ret = detach_loop_fd(dev, dev_fd);
348+
349+
if (!ret)
350+
ret = clear_loop_device_partitions(dev);
351+
352+
return ret;
353+
}
354+
278355
int tst_detach_device(const char *dev)
279356
{
280357
int dev_fd, ret;

0 commit comments

Comments
 (0)