On systems employing the "lazy loop device removal", commit a1ecac3b0656 ("loop: Make explicit loop device destruction lazy"), ioctl(LOOP_CLR_FD) may return 0 when the loop device is in use, for example by udev.
Therefore, there is a chance that a quick attach/detach may not give udev enough time to complete, like this: open("file.img", O_RDWR) = 4 ioctl(3, LOOP_SET_FD, 0x4) = 0 close(3) = 0 close(4) = 0 open("/dev/loop0", O_RDONLY) = 3 ioctl(3, LOOP_CLR_FD, 0) = 0 close(3) = 0 open("/dev/loop0", O_RDWR) = 3 open("file.img", O_RDWR) = 4 ioctl(3, LOOP_SET_FD, 0x4) = -1 EBUSY (Device or resource busy) So let's wait until the kernel frees the loop device, i.e. when ioctl(LOOP_CLR_FD) starts failing with ENXIO. Signed-off-by: Stanislav Kholmanskikh <stanislav.kholmansk...@oracle.com> --- lib/tst_device.c | 22 ++++++++++++---------- 1 files changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/tst_device.c b/lib/tst_device.c index 3bded53..4725570 100644 --- a/lib/tst_device.c +++ b/lib/tst_device.c @@ -150,30 +150,32 @@ static void attach_device(void (*cleanup_fn)(void), static void detach_device(void (*cleanup_fn)(void), const char *dev) { - int dev_fd, err, i; + int dev_fd, ret, i; dev_fd = SAFE_OPEN(cleanup_fn, dev, O_RDONLY); - /* keep trying to clear LOOPDEV fd if EBUSY, a quick succession + /* keep trying to clear LOOPDEV until we get ENXIO, a quick succession * of attach/detach might not give udev enough time to complete */ for (i = 0; i < 40; i++) { - if (ioctl(dev_fd, LOOP_CLR_FD, 0) == 0) { + ret = ioctl(dev_fd, LOOP_CLR_FD, 0); + + if (ret && (errno == ENXIO)) { close(dev_fd); return; } - if (errno != EBUSY) { - err = errno; - close(dev_fd); - tst_brkm(TBROK, cleanup_fn, - "ioctl(%s, LOOP_CLR_FD, 0) failed: %s", - dev, tst_strerrno(err)); + + if (ret && (errno != EBUSY)) { + tst_resm(TWARN, + "ioctl(%s, LOOP_CLR_FD, 0) unexpectedly failed with: %s", + dev, tst_strerrno(errno)); } + usleep(50000); } close(dev_fd); tst_brkm(TBROK, cleanup_fn, - "ioctl(%s, LOOP_CLR_FD, 0) EBUSY for too long", dev); + "ioctl(%s, LOOP_CLR_FD, 0) no ENXIO for too long", dev); } const char *tst_acquire_device(void (cleanup_fn)(void)) -- 1.7.1 ------------------------------------------------------------------------------ _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list