]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
dm: refactor ioctl handling
authorChristoph Hellwig <hch@lst.de>
Thu, 15 Oct 2015 12:10:50 +0000 (14:10 +0200)
committerMike Snitzer <snitzer@redhat.com>
Sat, 31 Oct 2015 23:05:59 +0000 (19:05 -0400)
This moves the call to blkdev_ioctl and the argument checking to DM core
code, and only leaves a callout to find the block device to operate on
in the targets.  This simplifies the code and allows us to pass through
ioctl-like command using other methods in the next patch.

Also split out a helper around calling the prepare_ioctl method that
will be reused for persistent reservation handling.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
drivers/md/dm-flakey.c
drivers/md/dm-linear.c
drivers/md/dm-log-writes.c
drivers/md/dm-mpath.c
drivers/md/dm-switch.c
drivers/md/dm-verity.c
drivers/md/dm.c
include/linux/device-mapper.h

index 645e8b4f808eee3f1f63e2432bf12cf8cbcde961..09e2afcafd2ddc2575d552e14eb4f469505300f2 100644 (file)
@@ -373,20 +373,20 @@ static void flakey_status(struct dm_target *ti, status_type_t type,
        }
 }
 
-static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg)
+static int flakey_prepare_ioctl(struct dm_target *ti,
+               struct block_device **bdev, fmode_t *mode)
 {
        struct flakey_c *fc = ti->private;
-       struct dm_dev *dev = fc->dev;
-       int r = 0;
+
+       *bdev = fc->dev->bdev;
 
        /*
         * Only pass ioctls through if the device sizes match exactly.
         */
        if (fc->start ||
-           ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
-               r = scsi_verify_blk_ioctl(NULL, cmd);
-
-       return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
+           ti->len != i_size_read((*bdev)->bd_inode) >> SECTOR_SHIFT)
+               return 1;
+       return 0;
 }
 
 static int flakey_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data)
@@ -405,7 +405,7 @@ static struct target_type flakey_target = {
        .map    = flakey_map,
        .end_io = flakey_end_io,
        .status = flakey_status,
-       .ioctl  = flakey_ioctl,
+       .prepare_ioctl = flakey_prepare_ioctl,
        .iterate_devices = flakey_iterate_devices,
 };
 
index 436f5c9b6aea56dd6652696cc3eac489690c1e8e..de52864d60fa63852596f0b943b6804c5f92e47e 100644 (file)
@@ -116,21 +116,21 @@ static void linear_status(struct dm_target *ti, status_type_t type,
        }
 }
 
-static int linear_ioctl(struct dm_target *ti, unsigned int cmd,
-                       unsigned long arg)
+static int linear_prepare_ioctl(struct dm_target *ti,
+               struct block_device **bdev, fmode_t *mode)
 {
        struct linear_c *lc = (struct linear_c *) ti->private;
        struct dm_dev *dev = lc->dev;
-       int r = 0;
+
+       *bdev = dev->bdev;
 
        /*
         * Only pass ioctls through if the device sizes match exactly.
         */
        if (lc->start ||
            ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
-               r = scsi_verify_blk_ioctl(NULL, cmd);
-
-       return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
+               return 1;
+       return 0;
 }
 
 static int linear_iterate_devices(struct dm_target *ti,
@@ -149,7 +149,7 @@ static struct target_type linear_target = {
        .dtr    = linear_dtr,
        .map    = linear_map,
        .status = linear_status,
-       .ioctl  = linear_ioctl,
+       .prepare_ioctl = linear_prepare_ioctl,
        .iterate_devices = linear_iterate_devices,
 };
 
index b2912dbac8bce7356f06eebc8063317c6bc411b0..624589d51c2cb67828567ad34b02d283e5965956 100644 (file)
@@ -714,20 +714,19 @@ static void log_writes_status(struct dm_target *ti, status_type_t type,
        }
 }
 
-static int log_writes_ioctl(struct dm_target *ti, unsigned int cmd,
-                           unsigned long arg)
+static int log_writes_prepare_ioctl(struct dm_target *ti,
+               struct block_device **bdev, fmode_t *mode)
 {
        struct log_writes_c *lc = ti->private;
        struct dm_dev *dev = lc->dev;
-       int r = 0;
 
+       *bdev = dev->bdev;
        /*
         * Only pass ioctls through if the device sizes match exactly.
         */
        if (ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
-               r = scsi_verify_blk_ioctl(NULL, cmd);
-
-       return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
+               return 1;
+       return 0;
 }
 
 static int log_writes_iterate_devices(struct dm_target *ti,
@@ -782,7 +781,7 @@ static struct target_type log_writes_target = {
        .map    = log_writes_map,
        .end_io = normal_end_io,
        .status = log_writes_status,
-       .ioctl  = log_writes_ioctl,
+       .prepare_ioctl = log_writes_prepare_ioctl,
        .message = log_writes_message,
        .iterate_devices = log_writes_iterate_devices,
        .io_hints = log_writes_io_hints,
index bdc96cd838b8869544036f8f9e07b2cc02a133ba..77066a1999844935abfdb972fecefb6e21e98514 100644 (file)
@@ -1533,18 +1533,14 @@ out:
        return r;
 }
 
-static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
-                          unsigned long arg)
+static int multipath_prepare_ioctl(struct dm_target *ti,
+               struct block_device **bdev, fmode_t *mode)
 {
        struct multipath *m = ti->private;
        struct pgpath *pgpath;
-       struct block_device *bdev;
-       fmode_t mode;
        unsigned long flags;
        int r;
 
-       bdev = NULL;
-       mode = 0;
        r = 0;
 
        spin_lock_irqsave(&m->lock, flags);
@@ -1555,23 +1551,17 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
        pgpath = m->current_pgpath;
 
        if (pgpath) {
-               bdev = pgpath->path.dev->bdev;
-               mode = pgpath->path.dev->mode;
+               *bdev = pgpath->path.dev->bdev;
+               *mode = pgpath->path.dev->mode;
        }
 
        if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path))
                r = -ENOTCONN;
-       else if (!bdev)
+       else if (!*bdev)
                r = -EIO;
 
        spin_unlock_irqrestore(&m->lock, flags);
 
-       /*
-        * Only pass ioctls through if the device sizes match exactly.
-        */
-       if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT)
-               r = scsi_verify_blk_ioctl(NULL, cmd);
-
        if (r == -ENOTCONN && !fatal_signal_pending(current)) {
                spin_lock_irqsave(&m->lock, flags);
                if (!m->current_pg) {
@@ -1584,7 +1574,12 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
                dm_table_run_md_queue_async(m->ti->table);
        }
 
-       return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg);
+       /*
+        * Only pass ioctls through if the device sizes match exactly.
+        */
+       if (!r && ti->len != i_size_read((*bdev)->bd_inode) >> SECTOR_SHIFT)
+               return 1;
+       return r;
 }
 
 static int multipath_iterate_devices(struct dm_target *ti,
@@ -1700,7 +1695,7 @@ static struct target_type multipath_target = {
        .resume = multipath_resume,
        .status = multipath_status,
        .message = multipath_message,
-       .ioctl  = multipath_ioctl,
+       .prepare_ioctl = multipath_prepare_ioctl,
        .iterate_devices = multipath_iterate_devices,
        .busy = multipath_busy,
 };
index 50fca469cafd92b3dac8c4455391cf24419de7ac..b1285753a5d44b87dd4dd4d8b1a60ea6403783bb 100644 (file)
@@ -511,27 +511,24 @@ static void switch_status(struct dm_target *ti, status_type_t type,
  *
  * Passthrough all ioctls to the path for sector 0
  */
-static int switch_ioctl(struct dm_target *ti, unsigned cmd,
-                       unsigned long arg)
+static int switch_prepare_ioctl(struct dm_target *ti,
+               struct block_device **bdev, fmode_t *mode)
 {
        struct switch_ctx *sctx = ti->private;
-       struct block_device *bdev;
-       fmode_t mode;
        unsigned path_nr;
-       int r = 0;
 
        path_nr = switch_get_path_nr(sctx, 0);
 
-       bdev = sctx->path_list[path_nr].dmdev->bdev;
-       mode = sctx->path_list[path_nr].dmdev->mode;
+       *bdev = sctx->path_list[path_nr].dmdev->bdev;
+       *mode = sctx->path_list[path_nr].dmdev->mode;
 
        /*
         * Only pass ioctls through if the device sizes match exactly.
         */
-       if (ti->len + sctx->path_list[path_nr].start != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT)
-               r = scsi_verify_blk_ioctl(NULL, cmd);
-
-       return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg);
+       if (ti->len + sctx->path_list[path_nr].start !=
+           i_size_read((*bdev)->bd_inode) >> SECTOR_SHIFT)
+               return 1;
+       return 0;
 }
 
 static int switch_iterate_devices(struct dm_target *ti,
@@ -560,7 +557,7 @@ static struct target_type switch_target = {
        .map = switch_map,
        .message = switch_message,
        .status = switch_status,
-       .ioctl = switch_ioctl,
+       .prepare_ioctl = switch_prepare_ioctl,
        .iterate_devices = switch_iterate_devices,
 };
 
index edc624bccf9aa841dc76073208735bd2455e12a8..ccf41886ebcf49790fe7fddb4aa7f9e581f0bbe3 100644 (file)
@@ -631,18 +631,17 @@ static void verity_status(struct dm_target *ti, status_type_t type,
        }
 }
 
-static int verity_ioctl(struct dm_target *ti, unsigned cmd,
-                       unsigned long arg)
+static int verity_prepare_ioctl(struct dm_target *ti,
+               struct block_device **bdev, fmode_t *mode)
 {
        struct dm_verity *v = ti->private;
-       int r = 0;
+
+       *bdev = v->data_dev->bdev;
 
        if (v->data_start ||
            ti->len != i_size_read(v->data_dev->bdev->bd_inode) >> SECTOR_SHIFT)
-               r = scsi_verify_blk_ioctl(NULL, cmd);
-
-       return r ? : __blkdev_driver_ioctl(v->data_dev->bdev, v->data_dev->mode,
-                                    cmd, arg);
+               return 1;
+       return 0;
 }
 
 static int verity_iterate_devices(struct dm_target *ti,
@@ -965,7 +964,7 @@ static struct target_type verity_target = {
        .dtr            = verity_dtr,
        .map            = verity_map,
        .status         = verity_status,
-       .ioctl          = verity_ioctl,
+       .prepare_ioctl  = verity_prepare_ioctl,
        .iterate_devices = verity_iterate_devices,
        .io_hints       = verity_io_hints,
 };
index 77ebb985154c39cf8643286dc943c18f55ead97c..9b3fe5be0cee5013d53bab2b2e5e5dea1cf7cc04 100644 (file)
@@ -555,18 +555,16 @@ static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
        return dm_get_geometry(md, geo);
 }
 
-static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
-                       unsigned int cmd, unsigned long arg)
+static int dm_get_live_table_for_ioctl(struct mapped_device *md,
+               struct dm_target **tgt, struct block_device **bdev,
+               fmode_t *mode, int *srcu_idx)
 {
-       struct mapped_device *md = bdev->bd_disk->private_data;
-       int srcu_idx;
        struct dm_table *map;
-       struct dm_target *tgt;
-       int r = -ENOTTY;
+       int r;
 
 retry:
-       map = dm_get_live_table(md, &srcu_idx);
-
+       r = -ENOTTY;
+       map = dm_get_live_table(md, srcu_idx);
        if (!map || !dm_table_get_size(map))
                goto out;
 
@@ -574,8 +572,9 @@ retry:
        if (dm_table_get_num_targets(map) != 1)
                goto out;
 
-       tgt = dm_table_get_target(map, 0);
-       if (!tgt->type->ioctl)
+       *tgt = dm_table_get_target(map, 0);
+
+       if (!(*tgt)->type->prepare_ioctl)
                goto out;
 
        if (dm_suspended_md(md)) {
@@ -583,16 +582,46 @@ retry:
                goto out;
        }
 
-       r = tgt->type->ioctl(tgt, cmd, arg);
+       r = (*tgt)->type->prepare_ioctl(*tgt, bdev, mode);
+       if (r < 0)
+               goto out;
 
-out:
-       dm_put_live_table(md, srcu_idx);
+       return r;
 
+out:
+       dm_put_live_table(md, *srcu_idx);
        if (r == -ENOTCONN) {
                msleep(10);
                goto retry;
        }
+       return r;
+}
+
+static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
+                       unsigned int cmd, unsigned long arg)
+{
+       struct mapped_device *md = bdev->bd_disk->private_data;
+       struct dm_target *tgt;
+       int srcu_idx, r;
+
+       r = dm_get_live_table_for_ioctl(md, &tgt, &bdev, &mode, &srcu_idx);
+       if (r < 0)
+               return r;
+
+       if (r > 0) {
+               /*
+                * Target determined this ioctl is being issued against
+                * a logical partition of the parent bdev; so extra
+                * validation is needed.
+                */
+               r = scsi_verify_blk_ioctl(NULL, cmd);
+               if (r)
+                       goto out;
+       }
 
+       r =  __blkdev_driver_ioctl(bdev, mode, cmd, arg);
+out:
+       dm_put_live_table(md, srcu_idx);
        return r;
 }
 
index 76d23fa8c7d3a21ba294e62be223f5a6992132a8..ec1c61c87d8974897af2be54af23588f14746777 100644 (file)
@@ -79,8 +79,8 @@ typedef void (*dm_status_fn) (struct dm_target *ti, status_type_t status_type,
 
 typedef int (*dm_message_fn) (struct dm_target *ti, unsigned argc, char **argv);
 
-typedef int (*dm_ioctl_fn) (struct dm_target *ti, unsigned int cmd,
-                           unsigned long arg);
+typedef int (*dm_prepare_ioctl_fn) (struct dm_target *ti,
+                           struct block_device **bdev, fmode_t *mode);
 
 /*
  * These iteration functions are typically used to check (and combine)
@@ -156,7 +156,7 @@ struct target_type {
        dm_resume_fn resume;
        dm_status_fn status;
        dm_message_fn message;
-       dm_ioctl_fn ioctl;
+       dm_prepare_ioctl_fn prepare_ioctl;
        dm_busy_fn busy;
        dm_iterate_devices_fn iterate_devices;
        dm_io_hints_fn io_hints;