diff options
Diffstat (limited to 'drivers/block/loop.c')
-rw-r--r-- | drivers/block/loop.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 9721d100caf1..2621ed2ce6d2 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
@@ -969,11 +969,18 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) | |||
969 | bd_set_size(bdev, 0); | 969 | bd_set_size(bdev, 0); |
970 | mapping_set_gfp_mask(filp->f_mapping, gfp); | 970 | mapping_set_gfp_mask(filp->f_mapping, gfp); |
971 | lo->lo_state = Lo_unbound; | 971 | lo->lo_state = Lo_unbound; |
972 | fput(filp); | ||
973 | /* This is safe: open() is still holding a reference. */ | 972 | /* This is safe: open() is still holding a reference. */ |
974 | module_put(THIS_MODULE); | 973 | module_put(THIS_MODULE); |
975 | if (max_part > 0) | 974 | if (max_part > 0) |
976 | ioctl_by_bdev(bdev, BLKRRPART, 0); | 975 | ioctl_by_bdev(bdev, BLKRRPART, 0); |
976 | mutex_unlock(&lo->lo_ctl_mutex); | ||
977 | /* | ||
978 | * Need not hold lo_ctl_mutex to fput backing file. | ||
979 | * Calling fput holding lo_ctl_mutex triggers a circular | ||
980 | * lock dependency possibility warning as fput can take | ||
981 | * bd_mutex which is usually taken before lo_ctl_mutex. | ||
982 | */ | ||
983 | fput(filp); | ||
977 | return 0; | 984 | return 0; |
978 | } | 985 | } |
979 | 986 | ||
@@ -1191,7 +1198,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, | |||
1191 | struct loop_device *lo = bdev->bd_disk->private_data; | 1198 | struct loop_device *lo = bdev->bd_disk->private_data; |
1192 | int err; | 1199 | int err; |
1193 | 1200 | ||
1194 | mutex_lock(&lo->lo_ctl_mutex); | 1201 | mutex_lock_nested(&lo->lo_ctl_mutex, 1); |
1195 | switch (cmd) { | 1202 | switch (cmd) { |
1196 | case LOOP_SET_FD: | 1203 | case LOOP_SET_FD: |
1197 | err = loop_set_fd(lo, mode, bdev, arg); | 1204 | err = loop_set_fd(lo, mode, bdev, arg); |
@@ -1200,7 +1207,10 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, | |||
1200 | err = loop_change_fd(lo, bdev, arg); | 1207 | err = loop_change_fd(lo, bdev, arg); |
1201 | break; | 1208 | break; |
1202 | case LOOP_CLR_FD: | 1209 | case LOOP_CLR_FD: |
1210 | /* loop_clr_fd would have unlocked lo_ctl_mutex on success */ | ||
1203 | err = loop_clr_fd(lo, bdev); | 1211 | err = loop_clr_fd(lo, bdev); |
1212 | if (!err) | ||
1213 | goto out_unlocked; | ||
1204 | break; | 1214 | break; |
1205 | case LOOP_SET_STATUS: | 1215 | case LOOP_SET_STATUS: |
1206 | err = loop_set_status_old(lo, (struct loop_info __user *) arg); | 1216 | err = loop_set_status_old(lo, (struct loop_info __user *) arg); |
@@ -1218,6 +1228,8 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, | |||
1218 | err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; | 1228 | err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; |
1219 | } | 1229 | } |
1220 | mutex_unlock(&lo->lo_ctl_mutex); | 1230 | mutex_unlock(&lo->lo_ctl_mutex); |
1231 | |||
1232 | out_unlocked: | ||
1221 | return err; | 1233 | return err; |
1222 | } | 1234 | } |
1223 | 1235 | ||