From f9d107644aa4943b383986a8aa36125379eeaa81 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 23 Jun 2021 16:59:04 +0200 Subject: 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 Reviewed-by: Chaitanya Kulkarni Link: https://lore.kernel.org/r/20210623145908.92973-6-hch@lst.de Signed-off-by: Jens Axboe --- drivers/block/loop.c | 93 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 33 deletions(-) (limited to 'drivers/block') 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 = { -- cgit v1.2.3