]> www.infradead.org Git - users/hch/block.git/commitdiff
loop: split loop_control_ioctl
authorChristoph Hellwig <hch@lst.de>
Thu, 17 Jun 2021 05:41:13 +0000 (07:41 +0200)
committerChristoph Hellwig <hch@lst.de>
Thu, 17 Jun 2021 07:24:33 +0000 (09:24 +0200)
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>
drivers/block/loop.c

index 23e2d01ad02bd9e8c48ba9e6be5f005ac4267b72..57f6930246ce884e781565a6ff3333a0cee53119 100644 (file)
@@ -2234,8 +2234,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;
@@ -2243,43 +2286,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 = {