aboutsummaryrefslogtreecommitdiff
path: root/drivers/block/loop.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2012-11-08 08:51:52 -0800
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2012-11-08 08:51:52 -0800
commitfa8e2458ecfc959cd627e25ba86d8eddcb63c887 (patch)
treed8c9dec3dac8e97e8591e6507a619959449d6344 /drivers/block/loop.c
parentd56a289be2ce01d1aa426a6cf45dede14a8db41e (diff)
parent3d70f8c617a436c7146ecb81df2265b4626dfe89 (diff)
Merge tag 'v3.7-rc4' into next to sync up Wacom bits
Linux 3.7-rc4
Diffstat (limited to 'drivers/block/loop.c')
-rw-r--r--drivers/block/loop.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index e9d594fd12c..54046e51160 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -976,8 +976,21 @@ static int loop_clr_fd(struct loop_device *lo)
if (lo->lo_state != Lo_bound)
return -ENXIO;
- if (lo->lo_refcnt > 1) /* we needed one fd for the ioctl */
- return -EBUSY;
+ /*
+ * If we've explicitly asked to tear down the loop device,
+ * and it has an elevated reference count, set it for auto-teardown when
+ * the last reference goes away. This stops $!~#$@ udev from
+ * preventing teardown because it decided that it needs to run blkid on
+ * the loopback device whenever they appear. xfstests is notorious for
+ * failing tests because blkid via udev races with a losetup
+ * <dev>/do something like mkfs/losetup -d <dev> causing the losetup -d
+ * command to fail with EBUSY.
+ */
+ if (lo->lo_refcnt > 1) {
+ lo->lo_flags |= LO_FLAGS_AUTOCLEAR;
+ mutex_unlock(&lo->lo_ctl_mutex);
+ return 0;
+ }
if (filp == NULL)
return -EINVAL;