summaryrefslogtreecommitdiff
path: root/drivers/block/loop.h
diff options
context:
space:
mode:
authorMing Lei <ming.lei@canonical.com>2015-05-06 07:26:23 +0300
committerJens Axboe <axboe@fb.com>2015-05-20 18:06:09 +0300
commitf8933667953e8e61bb6104f5ca88e32e85656a93 (patch)
tree25f3b20d8c1d27ac856a43f6655d9604c524fa9e /drivers/block/loop.h
parentb816d45fd56c57180b63a03412b9f898d5736c58 (diff)
downloadlinux-f8933667953e8e61bb6104f5ca88e32e85656a93.tar.xz
block: loop: don't hold lo_ctl_mutex in lo_open
The lo_ctl_mutex is held for running all ioctl handlers, and in some ioctl handlers, ioctl_by_bdev(BLKRRPART) is called for rereading partitions, which requires bd_mutex. So it is easy to cause failure because trylock(bd_mutex) may fail inside blkdev_reread_part(), and follows the lock context: blkid or other application: ->open() ->mutex_lock(bd_mutex) ->lo_open() ->mutex_lock(lo_ctl_mutex) losetup(set fd ioctl): ->mutex_lock(lo_ctl_mutex) ->ioctl_by_bdev(BLKRRPART) ->trylock(bd_mutex) This patch trys to eliminate the ABBA lock dependency by removing lo_ctl_mutext in lo_open() with the following approach: 1) make lo_refcnt as atomic_t and avoid acquiring lo_ctl_mutex in lo_open(): - for open vs. add/del loop, no any problem because of loop_index_mutex - freeze request queue during clr_fd, so I/O can't come until clearing fd is completed, like the effect of holding lo_ctl_mutex in lo_open - both open() and release() have been serialized by bd_mutex already 2) don't hold lo_ctl_mutex for decreasing/checking lo_refcnt in lo_release(), then lo_ctl_mutex is only required for the last release. Reviewed-by: Christoph Hellwig <hch@lst.de> Tested-by: Jarod Wilson <jarod@redhat.com> Acked-by: Jarod Wilson <jarod@redhat.com> Signed-off-by: Ming Lei <ming.lei@canonical.com> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/block/loop.h')
-rw-r--r--drivers/block/loop.h2
1 files changed, 1 insertions, 1 deletions
diff --git a/drivers/block/loop.h b/drivers/block/loop.h
index 49564edf5581..25e8997ed246 100644
--- a/drivers/block/loop.h
+++ b/drivers/block/loop.h
@@ -28,7 +28,7 @@ struct loop_func_table;
struct loop_device {
int lo_number;
- int lo_refcnt;
+ atomic_t lo_refcnt;
loff_t lo_offset;
loff_t lo_sizelimit;
int lo_flags;