diff options
Diffstat (limited to 'drivers/block/loop.c')
-rw-r--r-- | drivers/block/loop.c | 48 |
1 files changed, 44 insertions, 4 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index bf0345577672..2621ed2ce6d2 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
@@ -474,10 +474,35 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio) | |||
474 | int ret; | 474 | int ret; |
475 | 475 | ||
476 | pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset; | 476 | pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset; |
477 | if (bio_rw(bio) == WRITE) | 477 | |
478 | if (bio_rw(bio) == WRITE) { | ||
479 | int barrier = bio_barrier(bio); | ||
480 | struct file *file = lo->lo_backing_file; | ||
481 | |||
482 | if (barrier) { | ||
483 | if (unlikely(!file->f_op->fsync)) { | ||
484 | ret = -EOPNOTSUPP; | ||
485 | goto out; | ||
486 | } | ||
487 | |||
488 | ret = vfs_fsync(file, file->f_path.dentry, 0); | ||
489 | if (unlikely(ret)) { | ||
490 | ret = -EIO; | ||
491 | goto out; | ||
492 | } | ||
493 | } | ||
494 | |||
478 | ret = lo_send(lo, bio, pos); | 495 | ret = lo_send(lo, bio, pos); |
479 | else | 496 | |
497 | if (barrier && !ret) { | ||
498 | ret = vfs_fsync(file, file->f_path.dentry, 0); | ||
499 | if (unlikely(ret)) | ||
500 | ret = -EIO; | ||
501 | } | ||
502 | } else | ||
480 | ret = lo_receive(lo, bio, lo->lo_blocksize, pos); | 503 | ret = lo_receive(lo, bio, lo->lo_blocksize, pos); |
504 | |||
505 | out: | ||
481 | return ret; | 506 | return ret; |
482 | } | 507 | } |
483 | 508 | ||
@@ -826,6 +851,9 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, | |||
826 | lo->lo_queue->queuedata = lo; | 851 | lo->lo_queue->queuedata = lo; |
827 | lo->lo_queue->unplug_fn = loop_unplug; | 852 | lo->lo_queue->unplug_fn = loop_unplug; |
828 | 853 | ||
854 | if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync) | ||
855 | blk_queue_ordered(lo->lo_queue, QUEUE_ORDERED_DRAIN, NULL); | ||
856 | |||
829 | set_capacity(lo->lo_disk, size); | 857 | set_capacity(lo->lo_disk, size); |
830 | bd_set_size(bdev, size << 9); | 858 | bd_set_size(bdev, size << 9); |
831 | 859 | ||
@@ -941,11 +969,18 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) | |||
941 | bd_set_size(bdev, 0); | 969 | bd_set_size(bdev, 0); |
942 | mapping_set_gfp_mask(filp->f_mapping, gfp); | 970 | mapping_set_gfp_mask(filp->f_mapping, gfp); |
943 | lo->lo_state = Lo_unbound; | 971 | lo->lo_state = Lo_unbound; |
944 | fput(filp); | ||
945 | /* This is safe: open() is still holding a reference. */ | 972 | /* This is safe: open() is still holding a reference. */ |
946 | module_put(THIS_MODULE); | 973 | module_put(THIS_MODULE); |
947 | if (max_part > 0) | 974 | if (max_part > 0) |
948 | 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); | ||
949 | return 0; | 984 | return 0; |
950 | } | 985 | } |
951 | 986 | ||
@@ -1163,7 +1198,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, | |||
1163 | struct loop_device *lo = bdev->bd_disk->private_data; | 1198 | struct loop_device *lo = bdev->bd_disk->private_data; |
1164 | int err; | 1199 | int err; |
1165 | 1200 | ||
1166 | mutex_lock(&lo->lo_ctl_mutex); | 1201 | mutex_lock_nested(&lo->lo_ctl_mutex, 1); |
1167 | switch (cmd) { | 1202 | switch (cmd) { |
1168 | case LOOP_SET_FD: | 1203 | case LOOP_SET_FD: |
1169 | err = loop_set_fd(lo, mode, bdev, arg); | 1204 | err = loop_set_fd(lo, mode, bdev, arg); |
@@ -1172,7 +1207,10 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, | |||
1172 | err = loop_change_fd(lo, bdev, arg); | 1207 | err = loop_change_fd(lo, bdev, arg); |
1173 | break; | 1208 | break; |
1174 | case LOOP_CLR_FD: | 1209 | case LOOP_CLR_FD: |
1210 | /* loop_clr_fd would have unlocked lo_ctl_mutex on success */ | ||
1175 | err = loop_clr_fd(lo, bdev); | 1211 | err = loop_clr_fd(lo, bdev); |
1212 | if (!err) | ||
1213 | goto out_unlocked; | ||
1176 | break; | 1214 | break; |
1177 | case LOOP_SET_STATUS: | 1215 | case LOOP_SET_STATUS: |
1178 | err = loop_set_status_old(lo, (struct loop_info __user *) arg); | 1216 | err = loop_set_status_old(lo, (struct loop_info __user *) arg); |
@@ -1190,6 +1228,8 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, | |||
1190 | err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; | 1228 | err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; |
1191 | } | 1229 | } |
1192 | mutex_unlock(&lo->lo_ctl_mutex); | 1230 | mutex_unlock(&lo->lo_ctl_mutex); |
1231 | |||
1232 | out_unlocked: | ||
1193 | return err; | 1233 | return err; |
1194 | } | 1234 | } |
1195 | 1235 | ||