Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

dm: Allow .prepare_ioctl to handle ioctls directly

This adds a 'bool *forward' parameter to .prepare_ioctl, which allows
device mapper targets to accept ioctls to themselves instead of the
underlying device. If the target already fully handled the ioctl, it
sets *forward to false and device mapper won't forward it to the
underlying device any more.

In order for targets to actually know what the ioctl is about and how to
handle it, pass also cmd and arg.

As long as targets restrict themselves to interpreting ioctls of type
DM_IOCTL, this is a backwards compatible change because previously, any
such ioctl would have been passed down through all device mapper layers
until it reached a device that can't understand the ioctl and would
return an error.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

authored by

Kevin Wolf and committed by
Mikulas Patocka
4862c886 13e79076

+44 -16
+3 -1
drivers/md/dm-dust.c
··· 534 534 } 535 535 } 536 536 537 - static int dust_prepare_ioctl(struct dm_target *ti, struct block_device **bdev) 537 + static int dust_prepare_ioctl(struct dm_target *ti, struct block_device **bdev, 538 + unsigned int cmd, unsigned long arg, 539 + bool *forward) 538 540 { 539 541 struct dust_device *dd = ti->private; 540 542 struct dm_dev *dev = dd->dev;
+2 -1
drivers/md/dm-ebs-target.c
··· 415 415 } 416 416 } 417 417 418 - static int ebs_prepare_ioctl(struct dm_target *ti, struct block_device **bdev) 418 + static int ebs_prepare_ioctl(struct dm_target *ti, struct block_device **bdev, 419 + unsigned int cmd, unsigned long arg, bool *forward) 419 420 { 420 421 struct ebs_c *ec = ti->private; 421 422 struct dm_dev *dev = ec->dev;
+3 -1
drivers/md/dm-flakey.c
··· 648 648 } 649 649 } 650 650 651 - static int flakey_prepare_ioctl(struct dm_target *ti, struct block_device **bdev) 651 + static int flakey_prepare_ioctl(struct dm_target *ti, struct block_device **bdev, 652 + unsigned int cmd, unsigned long arg, 653 + bool *forward) 652 654 { 653 655 struct flakey_c *fc = ti->private; 654 656
+3 -1
drivers/md/dm-linear.c
··· 119 119 } 120 120 } 121 121 122 - static int linear_prepare_ioctl(struct dm_target *ti, struct block_device **bdev) 122 + static int linear_prepare_ioctl(struct dm_target *ti, struct block_device **bdev, 123 + unsigned int cmd, unsigned long arg, 124 + bool *forward) 123 125 { 124 126 struct linear_c *lc = ti->private; 125 127 struct dm_dev *dev = lc->dev;
+3 -1
drivers/md/dm-log-writes.c
··· 818 818 } 819 819 820 820 static int log_writes_prepare_ioctl(struct dm_target *ti, 821 - struct block_device **bdev) 821 + struct block_device **bdev, 822 + unsigned int cmd, unsigned long arg, 823 + bool *forward) 822 824 { 823 825 struct log_writes_c *lc = ti->private; 824 826 struct dm_dev *dev = lc->dev;
+3 -1
drivers/md/dm-mpath.c
··· 2022 2022 } 2023 2023 2024 2024 static int multipath_prepare_ioctl(struct dm_target *ti, 2025 - struct block_device **bdev) 2025 + struct block_device **bdev, 2026 + unsigned int cmd, unsigned long arg, 2027 + bool *forward) 2026 2028 { 2027 2029 struct multipath *m = ti->private; 2028 2030 struct pgpath *pgpath;
+3 -1
drivers/md/dm-switch.c
··· 517 517 * 518 518 * Passthrough all ioctls to the path for sector 0 519 519 */ 520 - static int switch_prepare_ioctl(struct dm_target *ti, struct block_device **bdev) 520 + static int switch_prepare_ioctl(struct dm_target *ti, struct block_device **bdev, 521 + unsigned int cmd, unsigned long arg, 522 + bool *forward) 521 523 { 522 524 struct switch_ctx *sctx = ti->private; 523 525 unsigned int path_nr;
+3 -1
drivers/md/dm-verity-target.c
··· 994 994 } 995 995 } 996 996 997 - static int verity_prepare_ioctl(struct dm_target *ti, struct block_device **bdev) 997 + static int verity_prepare_ioctl(struct dm_target *ti, struct block_device **bdev, 998 + unsigned int cmd, unsigned long arg, 999 + bool *forward) 998 1000 { 999 1001 struct dm_verity *v = ti->private; 1000 1002
+2 -1
drivers/md/dm-zoned-target.c
··· 1015 1015 /* 1016 1016 * Pass on ioctl to the backend device. 1017 1017 */ 1018 - static int dmz_prepare_ioctl(struct dm_target *ti, struct block_device **bdev) 1018 + static int dmz_prepare_ioctl(struct dm_target *ti, struct block_device **bdev, 1019 + unsigned int cmd, unsigned long arg, bool *forward) 1019 1020 { 1020 1021 struct dmz_target *dmz = ti->private; 1021 1022 struct dmz_dev *dev = &dmz->dev[0];
+11 -6
drivers/md/dm.c
··· 411 411 } 412 412 413 413 static int dm_prepare_ioctl(struct mapped_device *md, int *srcu_idx, 414 - struct block_device **bdev) 414 + struct block_device **bdev, unsigned int cmd, 415 + unsigned long arg, bool *forward) 415 416 { 416 417 struct dm_target *ti; 417 418 struct dm_table *map; ··· 435 434 if (dm_suspended_md(md)) 436 435 return -EAGAIN; 437 436 438 - r = ti->type->prepare_ioctl(ti, bdev); 439 - if (r == -ENOTCONN && !fatal_signal_pending(current)) { 437 + r = ti->type->prepare_ioctl(ti, bdev, cmd, arg, forward); 438 + if (r == -ENOTCONN && *forward && !fatal_signal_pending(current)) { 440 439 dm_put_live_table(md, *srcu_idx); 441 440 fsleep(10000); 442 441 goto retry; ··· 455 454 { 456 455 struct mapped_device *md = bdev->bd_disk->private_data; 457 456 int r, srcu_idx; 457 + bool forward = true; 458 458 459 - r = dm_prepare_ioctl(md, &srcu_idx, &bdev); 460 - if (r < 0) 459 + r = dm_prepare_ioctl(md, &srcu_idx, &bdev, cmd, arg, &forward); 460 + if (!forward || r < 0) 461 461 goto out; 462 462 463 463 if (r > 0) { ··· 3632 3630 struct mapped_device *md = bdev->bd_disk->private_data; 3633 3631 const struct pr_ops *ops; 3634 3632 int r, srcu_idx; 3633 + bool forward = true; 3635 3634 3636 - r = dm_prepare_ioctl(md, &srcu_idx, &bdev); 3635 + /* Not a real ioctl, but targets must not interpret non-DM ioctls */ 3636 + r = dm_prepare_ioctl(md, &srcu_idx, &bdev, 0, 0, &forward); 3637 3637 if (r < 0) 3638 3638 goto out; 3639 + WARN_ON_ONCE(!forward); 3639 3640 3640 3641 ops = bdev->bd_disk->fops->pr_ops; 3641 3642 if (ops && ops->pr_clear)
+8 -1
include/linux/device-mapper.h
··· 93 93 typedef int (*dm_message_fn) (struct dm_target *ti, unsigned int argc, char **argv, 94 94 char *result, unsigned int maxlen); 95 95 96 - typedef int (*dm_prepare_ioctl_fn) (struct dm_target *ti, struct block_device **bdev); 96 + /* 97 + * Called with *forward == true. If it remains true, the ioctl should be 98 + * forwarded to bdev. If it is reset to false, the target already fully handled 99 + * the ioctl and the return value is the return value for the whole ioctl. 100 + */ 101 + typedef int (*dm_prepare_ioctl_fn) (struct dm_target *ti, struct block_device **bdev, 102 + unsigned int cmd, unsigned long arg, 103 + bool *forward); 97 104 98 105 #ifdef CONFIG_BLK_DEV_ZONED 99 106 typedef int (*dm_report_zones_fn) (struct dm_target *ti,