On 01/20/2015 04:12 PM, Jan Stancek wrote:
> 
> 
> 
> 
> ----- Original Message -----
>> From: "Cyril Hrubis" <chru...@suse.cz>
>> To: "Jan Stancek" <jstan...@redhat.com>
>> Cc: ltp-list@lists.sourceforge.net, li...@redhat.com
>> Sent: Tuesday, 20 January, 2015 3:44:03 PM
>> Subject: Re: [PATCH] runltp: export initialized LTP_DEV
>>
>> Hi!
>>> This patch restores behavior from ltp-20140828, where LTP_DEV is exported
>>> and tst_acquire_device() will use that instead of trying to acquire/release
>>> loopdev on its own.
>>
>> Sorry for my confusion. This patch is correct as it moves the export to
>> the right places. I didn't read till it carefully and thought this
>> simply reverts the change, sorry.
>>
>> The change is acked, but I think that it merely avoids the EBUSY from
>> the ioctl() and that there is a real bug somewhere, likely some race
>> condition in kernel.
> 
> I agree, that it looks like kernel bug and patch might only work around that.
> I'll keep exploring the bug path in the meantime as well.

So, it looks like this is not bug after all, but udev rule that keeps
firing "blkid":

/lib/udev/rules.d/60-persistent-storage.rules:84
  KERNEL!="xvd*|sr*", IMPORT{program}="/sbin/blkid -o udev -p $tempnode"
    /sbin/blkid -o udev -p /dev/loop0

If attach/detach happens too quickly, blkid might still hold reference
and loop_clr_fd() then complains with EBUSY:
        if (lo->lo_refcnt > 1)  /* we needed one fd for the ioctl */
                return -EBUSY;

The only idea I have is to sleep/retry for a short period - see attached patch.

Regards,
Jan

>From 0ae0f16500cc48795287076edb2b725025466a0f Mon Sep 17 00:00:00 2001
Message-Id: <0ae0f16500cc48795287076edb2b725025466a0f.1421834144.git.jstan...@redhat.com>
From: Jan Stancek <jstan...@redhat.com>
Date: Tue, 20 Jan 2015 14:35:49 +0100
Subject: [PATCH] tst_device: sleep/retry if LOOP_CLR_FD fails with EBUSY

Rapid succession of device attach/detach may lead to EBUSY
from ioctl(LOOP_CLR_FD), because udev rules might still be
running.

Sleep/retry for a short period if LOOP_CLR_FD fails with EBUSY.

Signed-off-by: Jan Stancek <jstan...@redhat.com>
---
 lib/tst_device.c |   25 ++++++++++++++++++-------
 1 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/lib/tst_device.c b/lib/tst_device.c
index 6dff1ba..edf0bb4 100644
--- a/lib/tst_device.c
+++ b/lib/tst_device.c
@@ -144,19 +144,30 @@ static void attach_device(void (*cleanup_fn)(void),
 
 static void detach_device(void (*cleanup_fn)(void), const char *dev)
 {
-	int dev_fd, err;
+	int dev_fd, err, i;
 
 	dev_fd = SAFE_OPEN(cleanup_fn, dev, O_RDONLY);
 
-	if (ioctl(dev_fd, LOOP_CLR_FD, 0) < 0) {
-		err = errno;
-		close(dev_fd);
-		tst_brkm(TBROK, cleanup_fn,
-		         "ioctl(%s, LOOP_CLR_FD, 0) failed: %s",
-			 dev, tst_strerrno(err));
+	/* keep trying to clear LOOPDEV fd if EBUSY, 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) {
+			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);
 }
 
 const char *tst_acquire_device(void (cleanup_fn)(void))
-- 
1.7.1

------------------------------------------------------------------------------
New Year. New Location. New Benefits. New Data Center in Ashburn, VA.
GigeNET is offering a free month of service with a new server in Ashburn.
Choose from 2 high performing configs, both with 100TB of bandwidth.
Higher redundancy.Lower latency.Increased capacity.Completely compliant.
http://p.sf.net/sfu/gigenet
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list

Reply via email to