diff options
Diffstat (limited to 'drivers/block/loop.c')
| -rw-r--r-- | drivers/block/loop.c | 17 | 
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;  |