diff options
author | Christoph Hellwig <hch@lst.de> | 2021-06-23 16:59:04 +0200 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2021-06-30 15:34:13 -0600 |
commit | f9d107644aa4943b383986a8aa36125379eeaa81 (patch) | |
tree | 5d074ed57ba75e595096916f3fec77e996eeb527 /drivers/block/loop.c | |
parent | 4157fe0b3d16ceca4316674a90c681405cdd23bf (diff) |
loop: split loop_control_ioctl
Split loop_control_ioctl into a helper for each command. This keeps the
code nicely separated for the upcoming locking changes.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
Link: https://lore.kernel.org/r/20210623145908.92973-6-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/block/loop.c')
-rw-r--r-- | drivers/block/loop.c | 93 |
1 files changed, 60 insertions, 33 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 5b77c1e160b5..c3c6cfdcaf34 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -2397,8 +2397,51 @@ static void loop_probe(dev_t dev) mutex_unlock(&loop_ctl_mutex); } -static long loop_control_ioctl(struct file *file, unsigned int cmd, - unsigned long parm) +static int loop_control_add(int idx) +{ + int ret; + + ret = mutex_lock_killable(&loop_ctl_mutex); + if (ret) + return ret; + ret = loop_add(idx); + mutex_unlock(&loop_ctl_mutex); + return ret; +} + +static int loop_control_remove(int idx) +{ + struct loop_device *lo; + int ret; + + ret = mutex_lock_killable(&loop_ctl_mutex); + if (ret) + return ret; + + ret = loop_lookup(&lo, idx); + if (ret < 0) + goto out_unlock_ctrl; + + ret = mutex_lock_killable(&lo->lo_mutex); + if (ret) + goto out_unlock_ctrl; + if (lo->lo_state != Lo_unbound || + atomic_read(&lo->lo_refcnt) > 0) { + mutex_unlock(&lo->lo_mutex); + ret = -EBUSY; + goto out_unlock_ctrl; + } + lo->lo_state = Lo_deleting; + mutex_unlock(&lo->lo_mutex); + + idr_remove(&loop_index_idr, lo->lo_number); + loop_remove(lo); +out_unlock_ctrl: + mutex_unlock(&loop_ctl_mutex); + return ret; +} + +static int loop_control_get_free(int idx) { struct loop_device *lo; int ret; @@ -2406,43 +2449,27 @@ static long loop_control_ioctl(struct file *file, unsigned int cmd, ret = mutex_lock_killable(&loop_ctl_mutex); if (ret) return ret; + ret = loop_lookup(&lo, -1); + if (ret < 0) + ret = loop_add(-1); + mutex_unlock(&loop_ctl_mutex); + + return ret; +} - ret = -ENOSYS; +static long loop_control_ioctl(struct file *file, unsigned int cmd, + unsigned long parm) +{ switch (cmd) { case LOOP_CTL_ADD: - ret = loop_add(parm); - break; + return loop_control_add(parm); case LOOP_CTL_REMOVE: - ret = loop_lookup(&lo, parm); - if (ret < 0) - break; - ret = mutex_lock_killable(&lo->lo_mutex); - if (ret) - break; - if (lo->lo_state != Lo_unbound) { - ret = -EBUSY; - mutex_unlock(&lo->lo_mutex); - break; - } - if (atomic_read(&lo->lo_refcnt) > 0) { - ret = -EBUSY; - mutex_unlock(&lo->lo_mutex); - break; - } - lo->lo_state = Lo_deleting; - mutex_unlock(&lo->lo_mutex); - idr_remove(&loop_index_idr, lo->lo_number); - loop_remove(lo); - break; + return loop_control_remove(parm); case LOOP_CTL_GET_FREE: - ret = loop_lookup(&lo, -1); - if (ret >= 0) - break; - ret = loop_add(-1); + return loop_control_get_free(parm); + default: + return -ENOSYS; } - mutex_unlock(&loop_ctl_mutex); - - return ret; } static const struct file_operations loop_ctl_fops = { |