summaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm-ioctl.c')
-rw-r--r--drivers/md/dm-ioctl.c34
1 files changed, 30 insertions, 4 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 1e03bc89e20f..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, '/')) {
@@ -1592,7 +1617,7 @@ static int target_message(struct file *filp, struct dm_ioctl *param, size_t para
1592 } 1617 }
1593 1618
1594 ti = dm_table_find_target(table, tmsg->sector); 1619 ti = dm_table_find_target(table, tmsg->sector);
1595 if (!dm_target_is_valid(ti)) { 1620 if (!ti) {
1596 DMWARN("Target message sector outside device."); 1621 DMWARN("Target message sector outside device.");
1597 r = -EINVAL; 1622 r = -EINVAL;
1598 } else if (ti->type->message) 1623 } else if (ti->type->message)
@@ -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)))