loop: split loop_control_ioctl
authorChristoph Hellwig <hch@lst.de>
Wed, 23 Jun 2021 14:59:04 +0000 (16:59 +0200)
committerJens Axboe <axboe@kernel.dk>
Wed, 30 Jun 2021 21:34:13 +0000 (15:34 -0600)
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>
drivers/block/loop.c

index 5b77c1e..c3c6cfd 100644 (file)
@@ -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 = {