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 e9d594fd12cb..54046e51160a 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
| @@ -976,8 +976,21 @@ static int loop_clr_fd(struct loop_device *lo) | |||
| 976 | if (lo->lo_state != Lo_bound) | 976 | if (lo->lo_state != Lo_bound) |
| 977 | return -ENXIO; | 977 | return -ENXIO; |
| 978 | 978 | ||
| 979 | if (lo->lo_refcnt > 1) /* we needed one fd for the ioctl */ | 979 | /* |
| 980 | return -EBUSY; | 980 | * If we've explicitly asked to tear down the loop device, |
| 981 | * and it has an elevated reference count, set it for auto-teardown when | ||
| 982 | * the last reference goes away. This stops $!~#$@ udev from | ||
| 983 | * preventing teardown because it decided that it needs to run blkid on | ||
| 984 | * the loopback device whenever they appear. xfstests is notorious for | ||
| 985 | * failing tests because blkid via udev races with a losetup | ||
| 986 | * <dev>/do something like mkfs/losetup -d <dev> causing the losetup -d | ||
| 987 | * command to fail with EBUSY. | ||
| 988 | */ | ||
| 989 | if (lo->lo_refcnt > 1) { | ||
| 990 | lo->lo_flags |= LO_FLAGS_AUTOCLEAR; | ||
| 991 | mutex_unlock(&lo->lo_ctl_mutex); | ||
| 992 | return 0; | ||
| 993 | } | ||
| 981 | 994 | ||
| 982 | if (filp == NULL) | 995 | if (filp == NULL) |
| 983 | return -EINVAL; | 996 | return -EINVAL; |
