On systems employing the "lazy loop device removal",
kernel commit commit a1ecac3b0656a68259927c234e505804d33a7b83
("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 |   17 ++++++-----------
 1 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/lib/tst_device.c b/lib/tst_device.c
index 3bded53..9a92fc8 100644
--- a/lib/tst_device.c
+++ b/lib/tst_device.c
@@ -150,30 +150,25 @@ 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));
-               }
                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

Reply via email to