Skip to content

Commit e56f81e

Browse files
Christoph Hellwigsnitm
authored andcommitted
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 <[email protected]> Signed-off-by: Mike Snitzer <[email protected]>
1 parent 4779693 commit e56f81e

File tree

8 files changed

+94
-75
lines changed

8 files changed

+94
-75
lines changed

drivers/md/dm-flakey.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -373,20 +373,20 @@ static void flakey_status(struct dm_target *ti, status_type_t type,
373373
}
374374
}
375375

376-
static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg)
376+
static int flakey_prepare_ioctl(struct dm_target *ti,
377+
struct block_device **bdev, fmode_t *mode)
377378
{
378379
struct flakey_c *fc = ti->private;
379-
struct dm_dev *dev = fc->dev;
380-
int r = 0;
380+
381+
*bdev = fc->dev->bdev;
381382

382383
/*
383384
* Only pass ioctls through if the device sizes match exactly.
384385
*/
385386
if (fc->start ||
386-
ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
387-
r = scsi_verify_blk_ioctl(NULL, cmd);
388-
389-
return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
387+
ti->len != i_size_read((*bdev)->bd_inode) >> SECTOR_SHIFT)
388+
return 1;
389+
return 0;
390390
}
391391

392392
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 = {
405405
.map = flakey_map,
406406
.end_io = flakey_end_io,
407407
.status = flakey_status,
408-
.ioctl = flakey_ioctl,
408+
.prepare_ioctl = flakey_prepare_ioctl,
409409
.iterate_devices = flakey_iterate_devices,
410410
};
411411

drivers/md/dm-linear.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,21 +116,21 @@ static void linear_status(struct dm_target *ti, status_type_t type,
116116
}
117117
}
118118

119-
static int linear_ioctl(struct dm_target *ti, unsigned int cmd,
120-
unsigned long arg)
119+
static int linear_prepare_ioctl(struct dm_target *ti,
120+
struct block_device **bdev, fmode_t *mode)
121121
{
122122
struct linear_c *lc = (struct linear_c *) ti->private;
123123
struct dm_dev *dev = lc->dev;
124-
int r = 0;
124+
125+
*bdev = dev->bdev;
125126

126127
/*
127128
* Only pass ioctls through if the device sizes match exactly.
128129
*/
129130
if (lc->start ||
130131
ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
131-
r = scsi_verify_blk_ioctl(NULL, cmd);
132-
133-
return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
132+
return 1;
133+
return 0;
134134
}
135135

136136
static int linear_iterate_devices(struct dm_target *ti,
@@ -149,7 +149,7 @@ static struct target_type linear_target = {
149149
.dtr = linear_dtr,
150150
.map = linear_map,
151151
.status = linear_status,
152-
.ioctl = linear_ioctl,
152+
.prepare_ioctl = linear_prepare_ioctl,
153153
.iterate_devices = linear_iterate_devices,
154154
};
155155

drivers/md/dm-log-writes.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -714,20 +714,19 @@ static void log_writes_status(struct dm_target *ti, status_type_t type,
714714
}
715715
}
716716

717-
static int log_writes_ioctl(struct dm_target *ti, unsigned int cmd,
718-
unsigned long arg)
717+
static int log_writes_prepare_ioctl(struct dm_target *ti,
718+
struct block_device **bdev, fmode_t *mode)
719719
{
720720
struct log_writes_c *lc = ti->private;
721721
struct dm_dev *dev = lc->dev;
722-
int r = 0;
723722

723+
*bdev = dev->bdev;
724724
/*
725725
* Only pass ioctls through if the device sizes match exactly.
726726
*/
727727
if (ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
728-
r = scsi_verify_blk_ioctl(NULL, cmd);
729-
730-
return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
728+
return 1;
729+
return 0;
731730
}
732731

733732
static int log_writes_iterate_devices(struct dm_target *ti,
@@ -782,7 +781,7 @@ static struct target_type log_writes_target = {
782781
.map = log_writes_map,
783782
.end_io = normal_end_io,
784783
.status = log_writes_status,
785-
.ioctl = log_writes_ioctl,
784+
.prepare_ioctl = log_writes_prepare_ioctl,
786785
.message = log_writes_message,
787786
.iterate_devices = log_writes_iterate_devices,
788787
.io_hints = log_writes_io_hints,

drivers/md/dm-mpath.c

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,18 +1533,14 @@ static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
15331533
return r;
15341534
}
15351535

1536-
static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
1537-
unsigned long arg)
1536+
static int multipath_prepare_ioctl(struct dm_target *ti,
1537+
struct block_device **bdev, fmode_t *mode)
15381538
{
15391539
struct multipath *m = ti->private;
15401540
struct pgpath *pgpath;
1541-
struct block_device *bdev;
1542-
fmode_t mode;
15431541
unsigned long flags;
15441542
int r;
15451543

1546-
bdev = NULL;
1547-
mode = 0;
15481544
r = 0;
15491545

15501546
spin_lock_irqsave(&m->lock, flags);
@@ -1555,23 +1551,17 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
15551551
pgpath = m->current_pgpath;
15561552

15571553
if (pgpath) {
1558-
bdev = pgpath->path.dev->bdev;
1559-
mode = pgpath->path.dev->mode;
1554+
*bdev = pgpath->path.dev->bdev;
1555+
*mode = pgpath->path.dev->mode;
15601556
}
15611557

15621558
if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path))
15631559
r = -ENOTCONN;
1564-
else if (!bdev)
1560+
else if (!*bdev)
15651561
r = -EIO;
15661562

15671563
spin_unlock_irqrestore(&m->lock, flags);
15681564

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-
15751565
if (r == -ENOTCONN && !fatal_signal_pending(current)) {
15761566
spin_lock_irqsave(&m->lock, flags);
15771567
if (!m->current_pg) {
@@ -1584,7 +1574,12 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
15841574
dm_table_run_md_queue_async(m->ti->table);
15851575
}
15861576

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;
15881583
}
15891584

15901585
static int multipath_iterate_devices(struct dm_target *ti,
@@ -1700,7 +1695,7 @@ static struct target_type multipath_target = {
17001695
.resume = multipath_resume,
17011696
.status = multipath_status,
17021697
.message = multipath_message,
1703-
.ioctl = multipath_ioctl,
1698+
.prepare_ioctl = multipath_prepare_ioctl,
17041699
.iterate_devices = multipath_iterate_devices,
17051700
.busy = multipath_busy,
17061701
};

drivers/md/dm-switch.c

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -511,27 +511,24 @@ static void switch_status(struct dm_target *ti, status_type_t type,
511511
*
512512
* Passthrough all ioctls to the path for sector 0
513513
*/
514-
static int switch_ioctl(struct dm_target *ti, unsigned cmd,
515-
unsigned long arg)
514+
static int switch_prepare_ioctl(struct dm_target *ti,
515+
struct block_device **bdev, fmode_t *mode)
516516
{
517517
struct switch_ctx *sctx = ti->private;
518-
struct block_device *bdev;
519-
fmode_t mode;
520518
unsigned path_nr;
521-
int r = 0;
522519

523520
path_nr = switch_get_path_nr(sctx, 0);
524521

525-
bdev = sctx->path_list[path_nr].dmdev->bdev;
526-
mode = sctx->path_list[path_nr].dmdev->mode;
522+
*bdev = sctx->path_list[path_nr].dmdev->bdev;
523+
*mode = sctx->path_list[path_nr].dmdev->mode;
527524

528525
/*
529526
* Only pass ioctls through if the device sizes match exactly.
530527
*/
531-
if (ti->len + sctx->path_list[path_nr].start != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT)
532-
r = scsi_verify_blk_ioctl(NULL, cmd);
533-
534-
return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg);
528+
if (ti->len + sctx->path_list[path_nr].start !=
529+
i_size_read((*bdev)->bd_inode) >> SECTOR_SHIFT)
530+
return 1;
531+
return 0;
535532
}
536533

537534
static int switch_iterate_devices(struct dm_target *ti,
@@ -560,7 +557,7 @@ static struct target_type switch_target = {
560557
.map = switch_map,
561558
.message = switch_message,
562559
.status = switch_status,
563-
.ioctl = switch_ioctl,
560+
.prepare_ioctl = switch_prepare_ioctl,
564561
.iterate_devices = switch_iterate_devices,
565562
};
566563

drivers/md/dm-verity.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -631,18 +631,17 @@ static void verity_status(struct dm_target *ti, status_type_t type,
631631
}
632632
}
633633

634-
static int verity_ioctl(struct dm_target *ti, unsigned cmd,
635-
unsigned long arg)
634+
static int verity_prepare_ioctl(struct dm_target *ti,
635+
struct block_device **bdev, fmode_t *mode)
636636
{
637637
struct dm_verity *v = ti->private;
638-
int r = 0;
638+
639+
*bdev = v->data_dev->bdev;
639640

640641
if (v->data_start ||
641642
ti->len != i_size_read(v->data_dev->bdev->bd_inode) >> SECTOR_SHIFT)
642-
r = scsi_verify_blk_ioctl(NULL, cmd);
643-
644-
return r ? : __blkdev_driver_ioctl(v->data_dev->bdev, v->data_dev->mode,
645-
cmd, arg);
643+
return 1;
644+
return 0;
646645
}
647646

648647
static int verity_iterate_devices(struct dm_target *ti,
@@ -965,7 +964,7 @@ static struct target_type verity_target = {
965964
.dtr = verity_dtr,
966965
.map = verity_map,
967966
.status = verity_status,
968-
.ioctl = verity_ioctl,
967+
.prepare_ioctl = verity_prepare_ioctl,
969968
.iterate_devices = verity_iterate_devices,
970969
.io_hints = verity_io_hints,
971970
};

drivers/md/dm.c

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -555,44 +555,73 @@ static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
555555
return dm_get_geometry(md, geo);
556556
}
557557

558-
static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
559-
unsigned int cmd, unsigned long arg)
558+
static int dm_get_live_table_for_ioctl(struct mapped_device *md,
559+
struct dm_target **tgt, struct block_device **bdev,
560+
fmode_t *mode, int *srcu_idx)
560561
{
561-
struct mapped_device *md = bdev->bd_disk->private_data;
562-
int srcu_idx;
563562
struct dm_table *map;
564-
struct dm_target *tgt;
565-
int r = -ENOTTY;
563+
int r;
566564

567565
retry:
568-
map = dm_get_live_table(md, &srcu_idx);
569-
566+
r = -ENOTTY;
567+
map = dm_get_live_table(md, srcu_idx);
570568
if (!map || !dm_table_get_size(map))
571569
goto out;
572570

573571
/* We only support devices that have a single target */
574572
if (dm_table_get_num_targets(map) != 1)
575573
goto out;
576574

577-
tgt = dm_table_get_target(map, 0);
578-
if (!tgt->type->ioctl)
575+
*tgt = dm_table_get_target(map, 0);
576+
577+
if (!(*tgt)->type->prepare_ioctl)
579578
goto out;
580579

581580
if (dm_suspended_md(md)) {
582581
r = -EAGAIN;
583582
goto out;
584583
}
585584

586-
r = tgt->type->ioctl(tgt, cmd, arg);
585+
r = (*tgt)->type->prepare_ioctl(*tgt, bdev, mode);
586+
if (r < 0)
587+
goto out;
587588

588-
out:
589-
dm_put_live_table(md, srcu_idx);
589+
return r;
590590

591+
out:
592+
dm_put_live_table(md, *srcu_idx);
591593
if (r == -ENOTCONN) {
592594
msleep(10);
593595
goto retry;
594596
}
597+
return r;
598+
}
599+
600+
static 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+
}
595621

622+
r = __blkdev_driver_ioctl(bdev, mode, cmd, arg);
623+
out:
624+
dm_put_live_table(md, srcu_idx);
596625
return r;
597626
}
598627

include/linux/device-mapper.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ typedef void (*dm_status_fn) (struct dm_target *ti, status_type_t status_type,
7979

8080
typedef int (*dm_message_fn) (struct dm_target *ti, unsigned argc, char **argv);
8181

82-
typedef int (*dm_ioctl_fn) (struct dm_target *ti, unsigned int cmd,
83-
unsigned long arg);
82+
typedef int (*dm_prepare_ioctl_fn) (struct dm_target *ti,
83+
struct block_device **bdev, fmode_t *mode);
8484

8585
/*
8686
* These iteration functions are typically used to check (and combine)
@@ -156,7 +156,7 @@ struct target_type {
156156
dm_resume_fn resume;
157157
dm_status_fn status;
158158
dm_message_fn message;
159-
dm_ioctl_fn ioctl;
159+
dm_prepare_ioctl_fn prepare_ioctl;
160160
dm_busy_fn busy;
161161
dm_iterate_devices_fn iterate_devices;
162162
dm_io_hints_fn io_hints;

0 commit comments

Comments
 (0)