summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2015-10-15 08:10:50 -0400
committerMike Snitzer <snitzer@redhat.com>2015-10-31 19:05:59 -0400
commite56f81e0b01ef4e45292d8c1e19edd4d09724e14 (patch)
tree68b1faed3589d00b7a473ce856532e321f9e4908
parent47796938c46b943d157ac8a6f9ed4e3b98b83cf4 (diff)
dm: refactor ioctl handling
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>
-rw-r--r--drivers/md/dm-flakey.c16
-rw-r--r--drivers/md/dm-linear.c14
-rw-r--r--drivers/md/dm-log-writes.c13
-rw-r--r--drivers/md/dm-mpath.c29
-rw-r--r--drivers/md/dm-switch.c21
-rw-r--r--drivers/md/dm-verity.c15
-rw-r--r--drivers/md/dm.c55
-rw-r--r--include/linux/device-mapper.h6
8 files changed, 94 insertions, 75 deletions
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
index 645e8b4f808e..09e2afcafd2d 100644
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -373,20 +373,20 @@ static void flakey_status(struct dm_target *ti, status_type_t type,
373 } 373 }
374} 374}
375 375
376static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg) 376static int flakey_prepare_ioctl(struct dm_target *ti,
377 struct block_device **bdev, fmode_t *mode)
377{ 378{
378 struct flakey_c *fc = ti->private; 379 struct flakey_c *fc = ti->private;
379 struct dm_dev *dev = fc->dev; 380
380 int r = 0; 381 *bdev = fc->dev->bdev;
381 382
382 /* 383 /*
383 * Only pass ioctls through if the device sizes match exactly. 384 * Only pass ioctls through if the device sizes match exactly.
384 */ 385 */
385 if (fc->start || 386 if (fc->start ||
386 ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT) 387 ti->len != i_size_read((*bdev)->bd_inode) >> SECTOR_SHIFT)
387 r = scsi_verify_blk_ioctl(NULL, cmd); 388 return 1;
388 389 return 0;
389 return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
390} 390}
391 391
392static int flakey_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data) 392static 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 = {
405 .map = flakey_map, 405 .map = flakey_map,
406 .end_io = flakey_end_io, 406 .end_io = flakey_end_io,
407 .status = flakey_status, 407 .status = flakey_status,
408 .ioctl = flakey_ioctl, 408 .prepare_ioctl = flakey_prepare_ioctl,
409 .iterate_devices = flakey_iterate_devices, 409 .iterate_devices = flakey_iterate_devices,
410}; 410};
411 411
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 436f5c9b6aea..de52864d60fa 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -116,21 +116,21 @@ static void linear_status(struct dm_target *ti, status_type_t type,
116 } 116 }
117} 117}
118 118
119static int linear_ioctl(struct dm_target *ti, unsigned int cmd, 119static int linear_prepare_ioctl(struct dm_target *ti,
120 unsigned long arg) 120 struct block_device **bdev, fmode_t *mode)
121{ 121{
122 struct linear_c *lc = (struct linear_c *) ti->private; 122 struct linear_c *lc = (struct linear_c *) ti->private;
123 struct dm_dev *dev = lc->dev; 123 struct dm_dev *dev = lc->dev;
124 int r = 0; 124
125 *bdev = dev->bdev;
125 126
126 /* 127 /*
127 * Only pass ioctls through if the device sizes match exactly. 128 * Only pass ioctls through if the device sizes match exactly.
128 */ 129 */
129 if (lc->start || 130 if (lc->start ||
130 ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT) 131 ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
131 r = scsi_verify_blk_ioctl(NULL, cmd); 132 return 1;
132 133 return 0;
133 return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
134} 134}
135 135
136static int linear_iterate_devices(struct dm_target *ti, 136static int linear_iterate_devices(struct dm_target *ti,
@@ -149,7 +149,7 @@ static struct target_type linear_target = {
149 .dtr = linear_dtr, 149 .dtr = linear_dtr,
150 .map = linear_map, 150 .map = linear_map,
151 .status = linear_status, 151 .status = linear_status,
152 .ioctl = linear_ioctl, 152 .prepare_ioctl = linear_prepare_ioctl,
153 .iterate_devices = linear_iterate_devices, 153 .iterate_devices = linear_iterate_devices,
154}; 154};
155 155
diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c
index b2912dbac8bc..624589d51c2c 100644
--- a/drivers/md/dm-log-writes.c
+++ b/drivers/md/dm-log-writes.c
@@ -714,20 +714,19 @@ static void log_writes_status(struct dm_target *ti, status_type_t type,
714 } 714 }
715} 715}
716 716
717static int log_writes_ioctl(struct dm_target *ti, unsigned int cmd, 717static int log_writes_prepare_ioctl(struct dm_target *ti,
718 unsigned long arg) 718 struct block_device **bdev, fmode_t *mode)
719{ 719{
720 struct log_writes_c *lc = ti->private; 720 struct log_writes_c *lc = ti->private;
721 struct dm_dev *dev = lc->dev; 721 struct dm_dev *dev = lc->dev;
722 int r = 0;
723 722
723 *bdev = dev->bdev;
724 /* 724 /*
725 * Only pass ioctls through if the device sizes match exactly. 725 * Only pass ioctls through if the device sizes match exactly.
726 */ 726 */
727 if (ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT) 727 if (ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
728 r = scsi_verify_blk_ioctl(NULL, cmd); 728 return 1;
729 729 return 0;
730 return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
731} 730}
732 731
733static int log_writes_iterate_devices(struct dm_target *ti, 732static int log_writes_iterate_devices(struct dm_target *ti,
@@ -782,7 +781,7 @@ static struct target_type log_writes_target = {
782 .map = log_writes_map, 781 .map = log_writes_map,
783 .end_io = normal_end_io, 782 .end_io = normal_end_io,
784 .status = log_writes_status, 783 .status = log_writes_status,
785 .ioctl = log_writes_ioctl, 784 .prepare_ioctl = log_writes_prepare_ioctl,
786 .message = log_writes_message, 785 .message = log_writes_message,
787 .iterate_devices = log_writes_iterate_devices, 786 .iterate_devices = log_writes_iterate_devices,
788 .io_hints = log_writes_io_hints, 787 .io_hints = log_writes_io_hints,
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index bdc96cd838b8..77066a199984 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -1533,18 +1533,14 @@ out:
1533 return r; 1533 return r;
1534} 1534}
1535 1535
1536static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, 1536static int multipath_prepare_ioctl(struct dm_target *ti,
1537 unsigned long arg) 1537 struct block_device **bdev, fmode_t *mode)
1538{ 1538{
1539 struct multipath *m = ti->private; 1539 struct multipath *m = ti->private;
1540 struct pgpath *pgpath; 1540 struct pgpath *pgpath;
1541 struct block_device *bdev;
1542 fmode_t mode;
1543 unsigned long flags; 1541 unsigned long flags;
1544 int r; 1542 int r;
1545 1543
1546 bdev = NULL;
1547 mode = 0;
1548 r = 0; 1544 r = 0;
1549 1545
1550 spin_lock_irqsave(&m->lock, flags); 1546 spin_lock_irqsave(&m->lock, flags);
@@ -1555,23 +1551,17 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
1555 pgpath = m->current_pgpath; 1551 pgpath = m->current_pgpath;
1556 1552
1557 if (pgpath) { 1553 if (pgpath) {
1558 bdev = pgpath->path.dev->bdev; 1554 *bdev = pgpath->path.dev->bdev;
1559 mode = pgpath->path.dev->mode; 1555 *mode = pgpath->path.dev->mode;
1560 } 1556 }
1561 1557
1562 if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path)) 1558 if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path))
1563 r = -ENOTCONN; 1559 r = -ENOTCONN;
1564 else if (!bdev) 1560 else if (!*bdev)
1565 r = -EIO; 1561 r = -EIO;
1566 1562
1567 spin_unlock_irqrestore(&m->lock, flags); 1563 spin_unlock_irqrestore(&m->lock, flags);
1568 1564
1569 /*
1570 * Only pass ioctls through if the device sizes match exactly.
1571 */
1572 if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT)
1573 r = scsi_verify_blk_ioctl(NULL, cmd);
1574
1575 if (r == -ENOTCONN && !fatal_signal_pending(current)) { 1565 if (r == -ENOTCONN && !fatal_signal_pending(current)) {
1576 spin_lock_irqsave(&m->lock, flags); 1566 spin_lock_irqsave(&m->lock, flags);
1577 if (!m->current_pg) { 1567 if (!m->current_pg) {
@@ -1584,7 +1574,12 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
1584 dm_table_run_md_queue_async(m->ti->table); 1574 dm_table_run_md_queue_async(m->ti->table);
1585 } 1575 }
1586 1576
1587 return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg); 1577 /*
1578 * Only pass ioctls through if the device sizes match exactly.
1579 */
1580 if (!r && ti->len != i_size_read((*bdev)->bd_inode) >> SECTOR_SHIFT)
1581 return 1;
1582 return r;
1588} 1583}
1589 1584
1590static int multipath_iterate_devices(struct dm_target *ti, 1585static int multipath_iterate_devices(struct dm_target *ti,
@@ -1700,7 +1695,7 @@ static struct target_type multipath_target = {
1700 .resume = multipath_resume, 1695 .resume = multipath_resume,
1701 .status = multipath_status, 1696 .status = multipath_status,
1702 .message = multipath_message, 1697 .message = multipath_message,
1703 .ioctl = multipath_ioctl, 1698 .prepare_ioctl = multipath_prepare_ioctl,
1704 .iterate_devices = multipath_iterate_devices, 1699 .iterate_devices = multipath_iterate_devices,
1705 .busy = multipath_busy, 1700 .busy = multipath_busy,
1706}; 1701};
diff --git a/drivers/md/dm-switch.c b/drivers/md/dm-switch.c
index 50fca469cafd..b1285753a5d4 100644
--- a/drivers/md/dm-switch.c
+++ b/drivers/md/dm-switch.c
@@ -511,27 +511,24 @@ static void switch_status(struct dm_target *ti, status_type_t type,
511 * 511 *
512 * Passthrough all ioctls to the path for sector 0 512 * Passthrough all ioctls to the path for sector 0
513 */ 513 */
514static int switch_ioctl(struct dm_target *ti, unsigned cmd, 514static int switch_prepare_ioctl(struct dm_target *ti,
515 unsigned long arg) 515 struct block_device **bdev, fmode_t *mode)
516{ 516{
517 struct switch_ctx *sctx = ti->private; 517 struct switch_ctx *sctx = ti->private;
518 struct block_device *bdev;
519 fmode_t mode;
520 unsigned path_nr; 518 unsigned path_nr;
521 int r = 0;
522 519
523 path_nr = switch_get_path_nr(sctx, 0); 520 path_nr = switch_get_path_nr(sctx, 0);
524 521
525 bdev = sctx->path_list[path_nr].dmdev->bdev; 522 *bdev = sctx->path_list[path_nr].dmdev->bdev;
526 mode = sctx->path_list[path_nr].dmdev->mode; 523 *mode = sctx->path_list[path_nr].dmdev->mode;
527 524
528 /* 525 /*
529 * Only pass ioctls through if the device sizes match exactly. 526 * Only pass ioctls through if the device sizes match exactly.
530 */ 527 */
531 if (ti->len + sctx->path_list[path_nr].start != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) 528 if (ti->len + sctx->path_list[path_nr].start !=
532 r = scsi_verify_blk_ioctl(NULL, cmd); 529 i_size_read((*bdev)->bd_inode) >> SECTOR_SHIFT)
533 530 return 1;
534 return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg); 531 return 0;
535} 532}
536 533
537static int switch_iterate_devices(struct dm_target *ti, 534static int switch_iterate_devices(struct dm_target *ti,
@@ -560,7 +557,7 @@ static struct target_type switch_target = {
560 .map = switch_map, 557 .map = switch_map,
561 .message = switch_message, 558 .message = switch_message,
562 .status = switch_status, 559 .status = switch_status,
563 .ioctl = switch_ioctl, 560 .prepare_ioctl = switch_prepare_ioctl,
564 .iterate_devices = switch_iterate_devices, 561 .iterate_devices = switch_iterate_devices,
565}; 562};
566 563
diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c
index edc624bccf9a..ccf41886ebcf 100644
--- a/drivers/md/dm-verity.c
+++ b/drivers/md/dm-verity.c
@@ -631,18 +631,17 @@ static void verity_status(struct dm_target *ti, status_type_t type,
631 } 631 }
632} 632}
633 633
634static int verity_ioctl(struct dm_target *ti, unsigned cmd, 634static int verity_prepare_ioctl(struct dm_target *ti,
635 unsigned long arg) 635 struct block_device **bdev, fmode_t *mode)
636{ 636{
637 struct dm_verity *v = ti->private; 637 struct dm_verity *v = ti->private;
638 int r = 0; 638
639 *bdev = v->data_dev->bdev;
639 640
640 if (v->data_start || 641 if (v->data_start ||
641 ti->len != i_size_read(v->data_dev->bdev->bd_inode) >> SECTOR_SHIFT) 642 ti->len != i_size_read(v->data_dev->bdev->bd_inode) >> SECTOR_SHIFT)
642 r = scsi_verify_blk_ioctl(NULL, cmd); 643 return 1;
643 644 return 0;
644 return r ? : __blkdev_driver_ioctl(v->data_dev->bdev, v->data_dev->mode,
645 cmd, arg);
646} 645}
647 646
648static int verity_iterate_devices(struct dm_target *ti, 647static int verity_iterate_devices(struct dm_target *ti,
@@ -965,7 +964,7 @@ static struct target_type verity_target = {
965 .dtr = verity_dtr, 964 .dtr = verity_dtr,
966 .map = verity_map, 965 .map = verity_map,
967 .status = verity_status, 966 .status = verity_status,
968 .ioctl = verity_ioctl, 967 .prepare_ioctl = verity_prepare_ioctl,
969 .iterate_devices = verity_iterate_devices, 968 .iterate_devices = verity_iterate_devices,
970 .io_hints = verity_io_hints, 969 .io_hints = verity_io_hints,
971}; 970};
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 77ebb985154c..9b3fe5be0cee 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -555,18 +555,16 @@ static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
555 return dm_get_geometry(md, geo); 555 return dm_get_geometry(md, geo);
556} 556}
557 557
558static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode, 558static int dm_get_live_table_for_ioctl(struct mapped_device *md,
559 unsigned int cmd, unsigned long arg) 559 struct dm_target **tgt, struct block_device **bdev,
560 fmode_t *mode, int *srcu_idx)
560{ 561{
561 struct mapped_device *md = bdev->bd_disk->private_data;
562 int srcu_idx;
563 struct dm_table *map; 562 struct dm_table *map;
564 struct dm_target *tgt; 563 int r;
565 int r = -ENOTTY;
566 564
567retry: 565retry:
568 map = dm_get_live_table(md, &srcu_idx); 566 r = -ENOTTY;
569 567 map = dm_get_live_table(md, srcu_idx);
570 if (!map || !dm_table_get_size(map)) 568 if (!map || !dm_table_get_size(map))
571 goto out; 569 goto out;
572 570
@@ -574,8 +572,9 @@ retry:
574 if (dm_table_get_num_targets(map) != 1) 572 if (dm_table_get_num_targets(map) != 1)
575 goto out; 573 goto out;
576 574
577 tgt = dm_table_get_target(map, 0); 575 *tgt = dm_table_get_target(map, 0);
578 if (!tgt->type->ioctl) 576
577 if (!(*tgt)->type->prepare_ioctl)
579 goto out; 578 goto out;
580 579
581 if (dm_suspended_md(md)) { 580 if (dm_suspended_md(md)) {
@@ -583,16 +582,46 @@ retry:
583 goto out; 582 goto out;
584 } 583 }
585 584
586 r = tgt->type->ioctl(tgt, cmd, arg); 585 r = (*tgt)->type->prepare_ioctl(*tgt, bdev, mode);
586 if (r < 0)
587 goto out;
587 588
588out: 589 return r;
589 dm_put_live_table(md, srcu_idx);
590 590
591out:
592 dm_put_live_table(md, *srcu_idx);
591 if (r == -ENOTCONN) { 593 if (r == -ENOTCONN) {
592 msleep(10); 594 msleep(10);
593 goto retry; 595 goto retry;
594 } 596 }
597 return r;
598}
599
600static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
601 unsigned int cmd, unsigned long arg)
602{
603 struct mapped_device *md = bdev->bd_disk->private_data;
604 struct dm_target *tgt;
605 int srcu_idx, r;
606
607 r = dm_get_live_table_for_ioctl(md, &tgt, &bdev, &mode, &srcu_idx);
608 if (r < 0)
609 return r;
610
611 if (r > 0) {
612 /*
613 * Target determined this ioctl is being issued against
614 * a logical partition of the parent bdev; so extra
615 * validation is needed.
616 */
617 r = scsi_verify_blk_ioctl(NULL, cmd);
618 if (r)
619 goto out;
620 }
595 621
622 r = __blkdev_driver_ioctl(bdev, mode, cmd, arg);
623out:
624 dm_put_live_table(md, srcu_idx);
596 return r; 625 return r;
597} 626}
598 627
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 76d23fa8c7d3..ec1c61c87d89 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -79,8 +79,8 @@ typedef void (*dm_status_fn) (struct dm_target *ti, status_type_t status_type,
79 79
80typedef int (*dm_message_fn) (struct dm_target *ti, unsigned argc, char **argv); 80typedef int (*dm_message_fn) (struct dm_target *ti, unsigned argc, char **argv);
81 81
82typedef int (*dm_ioctl_fn) (struct dm_target *ti, unsigned int cmd, 82typedef int (*dm_prepare_ioctl_fn) (struct dm_target *ti,
83 unsigned long arg); 83 struct block_device **bdev, fmode_t *mode);
84 84
85/* 85/*
86 * These iteration functions are typically used to check (and combine) 86 * These iteration functions are typically used to check (and combine)
@@ -156,7 +156,7 @@ struct target_type {
156 dm_resume_fn resume; 156 dm_resume_fn resume;
157 dm_status_fn status; 157 dm_status_fn status;
158 dm_message_fn message; 158 dm_message_fn message;
159 dm_ioctl_fn ioctl; 159 dm_prepare_ioctl_fn prepare_ioctl;
160 dm_busy_fn busy; 160 dm_busy_fn busy;
161 dm_iterate_devices_fn iterate_devices; 161 dm_iterate_devices_fn iterate_devices;
162 dm_io_hints_fn io_hints; 162 dm_io_hints_fn io_hints;