summaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-ioctl.c
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2019-09-16 05:55:42 -0400
committerMike Snitzer <snitzer@redhat.com>2019-09-16 10:18:01 -0400
commitafa179eb603847494aa5061d4f501224a30dd187 (patch)
treec68a8f38bd6994c93dceddc76d05113ca624baa1 /drivers/md/dm-ioctl.c
parent6e913b28cd279212c4580dbd8b2cf9dcd4740cfb (diff)
dm: introduce DM_GET_TARGET_VERSION
This commit introduces a new ioctl DM_GET_TARGET_VERSION. It will load a target that is specified in the "name" entry in the parameter structure and return its version. This functionality is intended to be used by cryptsetup, so that it can query kernel capabilities before activating the device. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md/dm-ioctl.c')
-rw-r--r--drivers/md/dm-ioctl.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index fb6f8fb1f13d..ac83f5002ce5 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -601,17 +601,27 @@ static void list_version_get_info(struct target_type *tt, void *param)
601 info->vers = align_ptr(((void *) ++info->vers) + strlen(tt->name) + 1); 601 info->vers = align_ptr(((void *) ++info->vers) + strlen(tt->name) + 1);
602} 602}
603 603
604static int list_versions(struct file *filp, struct dm_ioctl *param, size_t param_size) 604static int __list_versions(struct dm_ioctl *param, size_t param_size, const char *name)
605{ 605{
606 size_t len, needed = 0; 606 size_t len, needed = 0;
607 struct dm_target_versions *vers; 607 struct dm_target_versions *vers;
608 struct vers_iter iter_info; 608 struct vers_iter iter_info;
609 struct target_type *tt = NULL;
610
611 if (name) {
612 tt = dm_get_target_type(name);
613 if (!tt)
614 return -EINVAL;
615 }
609 616
610 /* 617 /*
611 * Loop through all the devices working out how much 618 * Loop through all the devices working out how much
612 * space we need. 619 * space we need.
613 */ 620 */
614 dm_target_iterate(list_version_get_needed, &needed); 621 if (!tt)
622 dm_target_iterate(list_version_get_needed, &needed);
623 else
624 list_version_get_needed(tt, &needed);
615 625
616 /* 626 /*
617 * Grab our output buffer. 627 * Grab our output buffer.
@@ -632,13 +642,28 @@ static int list_versions(struct file *filp, struct dm_ioctl *param, size_t param
632 /* 642 /*
633 * Now loop through filling out the names & versions. 643 * Now loop through filling out the names & versions.
634 */ 644 */
635 dm_target_iterate(list_version_get_info, &iter_info); 645 if (!tt)
646 dm_target_iterate(list_version_get_info, &iter_info);
647 else
648 list_version_get_info(tt, &iter_info);
636 param->flags |= iter_info.flags; 649 param->flags |= iter_info.flags;
637 650
638 out: 651 out:
652 if (tt)
653 dm_put_target_type(tt);
639 return 0; 654 return 0;
640} 655}
641 656
657static int list_versions(struct file *filp, struct dm_ioctl *param, size_t param_size)
658{
659 return __list_versions(param, param_size, NULL);
660}
661
662static int get_target_version(struct file *filp, struct dm_ioctl *param, size_t param_size)
663{
664 return __list_versions(param, param_size, param->name);
665}
666
642static int check_name(const char *name) 667static int check_name(const char *name)
643{ 668{
644 if (strchr(name, '/')) { 669 if (strchr(name, '/')) {
@@ -1664,6 +1689,7 @@ static ioctl_fn lookup_ioctl(unsigned int cmd, int *ioctl_flags)
1664 {DM_TARGET_MSG_CMD, 0, target_message}, 1689 {DM_TARGET_MSG_CMD, 0, target_message},
1665 {DM_DEV_SET_GEOMETRY_CMD, 0, dev_set_geometry}, 1690 {DM_DEV_SET_GEOMETRY_CMD, 0, dev_set_geometry},
1666 {DM_DEV_ARM_POLL, IOCTL_FLAGS_NO_PARAMS, dev_arm_poll}, 1691 {DM_DEV_ARM_POLL, IOCTL_FLAGS_NO_PARAMS, dev_arm_poll},
1692 {DM_GET_TARGET_VERSION, 0, get_target_version},
1667 }; 1693 };
1668 1694
1669 if (unlikely(cmd >= ARRAY_SIZE(_ioctls))) 1695 if (unlikely(cmd >= ARRAY_SIZE(_ioctls)))