diff options
author | Mike Snitzer <snitzer@redhat.com> | 2011-08-02 07:32:04 -0400 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2011-08-02 07:32:04 -0400 |
commit | 498f0103ea13123e007660def9072a0b7dd1c599 (patch) | |
tree | 3940ca8e50f13c3ed3a79c1939bacbc841ecb179 /drivers/md | |
parent | a6e50b409d3f9e0833e69c3c9cca822e8fa4adbb (diff) |
dm table: share target argument parsing functions
Move multipath target argument parsing code into dm-table so other
targets can share it.
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/dm-crypt.c | 7 | ||||
-rw-r--r-- | drivers/md/dm-mpath.c | 152 | ||||
-rw-r--r-- | drivers/md/dm-table.c | 57 |
3 files changed, 104 insertions, 112 deletions
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index f5406766ece3..b79e7472a9b3 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/device-mapper.h> | 30 | #include <linux/device-mapper.h> |
31 | 31 | ||
32 | #define DM_MSG_PREFIX "crypt" | 32 | #define DM_MSG_PREFIX "crypt" |
33 | #define MESG_STR(x) x, sizeof(x) | ||
34 | 33 | ||
35 | /* | 34 | /* |
36 | * context holding the current state of a multi-part conversion | 35 | * context holding the current state of a multi-part conversion |
@@ -1770,12 +1769,12 @@ static int crypt_message(struct dm_target *ti, unsigned argc, char **argv) | |||
1770 | if (argc < 2) | 1769 | if (argc < 2) |
1771 | goto error; | 1770 | goto error; |
1772 | 1771 | ||
1773 | if (!strnicmp(argv[0], MESG_STR("key"))) { | 1772 | if (!strcasecmp(argv[0], "key")) { |
1774 | if (!test_bit(DM_CRYPT_SUSPENDED, &cc->flags)) { | 1773 | if (!test_bit(DM_CRYPT_SUSPENDED, &cc->flags)) { |
1775 | DMWARN("not suspended during key manipulation."); | 1774 | DMWARN("not suspended during key manipulation."); |
1776 | return -EINVAL; | 1775 | return -EINVAL; |
1777 | } | 1776 | } |
1778 | if (argc == 3 && !strnicmp(argv[1], MESG_STR("set"))) { | 1777 | if (argc == 3 && !strcasecmp(argv[1], "set")) { |
1779 | ret = crypt_set_key(cc, argv[2]); | 1778 | ret = crypt_set_key(cc, argv[2]); |
1780 | if (ret) | 1779 | if (ret) |
1781 | return ret; | 1780 | return ret; |
@@ -1783,7 +1782,7 @@ static int crypt_message(struct dm_target *ti, unsigned argc, char **argv) | |||
1783 | ret = cc->iv_gen_ops->init(cc); | 1782 | ret = cc->iv_gen_ops->init(cc); |
1784 | return ret; | 1783 | return ret; |
1785 | } | 1784 | } |
1786 | if (argc == 2 && !strnicmp(argv[1], MESG_STR("wipe"))) { | 1785 | if (argc == 2 && !strcasecmp(argv[1], "wipe")) { |
1787 | if (cc->iv_gen_ops && cc->iv_gen_ops->wipe) { | 1786 | if (cc->iv_gen_ops && cc->iv_gen_ops->wipe) { |
1788 | ret = cc->iv_gen_ops->wipe(cc); | 1787 | ret = cc->iv_gen_ops->wipe(cc); |
1789 | if (ret) | 1788 | if (ret) |
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index adf851a081bd..5e0090ef4182 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/atomic.h> | 22 | #include <linux/atomic.h> |
23 | 23 | ||
24 | #define DM_MSG_PREFIX "multipath" | 24 | #define DM_MSG_PREFIX "multipath" |
25 | #define MESG_STR(x) x, sizeof(x) | ||
26 | #define DM_PG_INIT_DELAY_MSECS 2000 | 25 | #define DM_PG_INIT_DELAY_MSECS 2000 |
27 | #define DM_PG_INIT_DELAY_DEFAULT ((unsigned) -1) | 26 | #define DM_PG_INIT_DELAY_DEFAULT ((unsigned) -1) |
28 | 27 | ||
@@ -505,80 +504,29 @@ static void trigger_event(struct work_struct *work) | |||
505 | * <#paths> <#per-path selector args> | 504 | * <#paths> <#per-path selector args> |
506 | * [<path> [<arg>]* ]+ ]+ | 505 | * [<path> [<arg>]* ]+ ]+ |
507 | *---------------------------------------------------------------*/ | 506 | *---------------------------------------------------------------*/ |
508 | struct param { | 507 | static int parse_path_selector(struct dm_arg_set *as, struct priority_group *pg, |
509 | unsigned min; | ||
510 | unsigned max; | ||
511 | char *error; | ||
512 | }; | ||
513 | |||
514 | static int read_param(struct param *param, char *str, unsigned *v, char **error) | ||
515 | { | ||
516 | if (!str || | ||
517 | (sscanf(str, "%u", v) != 1) || | ||
518 | (*v < param->min) || | ||
519 | (*v > param->max)) { | ||
520 | *error = param->error; | ||
521 | return -EINVAL; | ||
522 | } | ||
523 | |||
524 | return 0; | ||
525 | } | ||
526 | |||
527 | struct arg_set { | ||
528 | unsigned argc; | ||
529 | char **argv; | ||
530 | }; | ||
531 | |||
532 | static char *shift(struct arg_set *as) | ||
533 | { | ||
534 | char *r; | ||
535 | |||
536 | if (as->argc) { | ||
537 | as->argc--; | ||
538 | r = *as->argv; | ||
539 | as->argv++; | ||
540 | return r; | ||
541 | } | ||
542 | |||
543 | return NULL; | ||
544 | } | ||
545 | |||
546 | static void consume(struct arg_set *as, unsigned n) | ||
547 | { | ||
548 | BUG_ON (as->argc < n); | ||
549 | as->argc -= n; | ||
550 | as->argv += n; | ||
551 | } | ||
552 | |||
553 | static int parse_path_selector(struct arg_set *as, struct priority_group *pg, | ||
554 | struct dm_target *ti) | 508 | struct dm_target *ti) |
555 | { | 509 | { |
556 | int r; | 510 | int r; |
557 | struct path_selector_type *pst; | 511 | struct path_selector_type *pst; |
558 | unsigned ps_argc; | 512 | unsigned ps_argc; |
559 | 513 | ||
560 | static struct param _params[] = { | 514 | static struct dm_arg _args[] = { |
561 | {0, 1024, "invalid number of path selector args"}, | 515 | {0, 1024, "invalid number of path selector args"}, |
562 | }; | 516 | }; |
563 | 517 | ||
564 | pst = dm_get_path_selector(shift(as)); | 518 | pst = dm_get_path_selector(dm_shift_arg(as)); |
565 | if (!pst) { | 519 | if (!pst) { |
566 | ti->error = "unknown path selector type"; | 520 | ti->error = "unknown path selector type"; |
567 | return -EINVAL; | 521 | return -EINVAL; |
568 | } | 522 | } |
569 | 523 | ||
570 | r = read_param(_params, shift(as), &ps_argc, &ti->error); | 524 | r = dm_read_arg_group(_args, as, &ps_argc, &ti->error); |
571 | if (r) { | 525 | if (r) { |
572 | dm_put_path_selector(pst); | 526 | dm_put_path_selector(pst); |
573 | return -EINVAL; | 527 | return -EINVAL; |
574 | } | 528 | } |
575 | 529 | ||
576 | if (ps_argc > as->argc) { | ||
577 | dm_put_path_selector(pst); | ||
578 | ti->error = "not enough arguments for path selector"; | ||
579 | return -EINVAL; | ||
580 | } | ||
581 | |||
582 | r = pst->create(&pg->ps, ps_argc, as->argv); | 530 | r = pst->create(&pg->ps, ps_argc, as->argv); |
583 | if (r) { | 531 | if (r) { |
584 | dm_put_path_selector(pst); | 532 | dm_put_path_selector(pst); |
@@ -587,12 +535,12 @@ static int parse_path_selector(struct arg_set *as, struct priority_group *pg, | |||
587 | } | 535 | } |
588 | 536 | ||
589 | pg->ps.type = pst; | 537 | pg->ps.type = pst; |
590 | consume(as, ps_argc); | 538 | dm_consume_args(as, ps_argc); |
591 | 539 | ||
592 | return 0; | 540 | return 0; |
593 | } | 541 | } |
594 | 542 | ||
595 | static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps, | 543 | static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps, |
596 | struct dm_target *ti) | 544 | struct dm_target *ti) |
597 | { | 545 | { |
598 | int r; | 546 | int r; |
@@ -609,7 +557,7 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps, | |||
609 | if (!p) | 557 | if (!p) |
610 | return ERR_PTR(-ENOMEM); | 558 | return ERR_PTR(-ENOMEM); |
611 | 559 | ||
612 | r = dm_get_device(ti, shift(as), dm_table_get_mode(ti->table), | 560 | r = dm_get_device(ti, dm_shift_arg(as), dm_table_get_mode(ti->table), |
613 | &p->path.dev); | 561 | &p->path.dev); |
614 | if (r) { | 562 | if (r) { |
615 | ti->error = "error getting device"; | 563 | ti->error = "error getting device"; |
@@ -660,16 +608,16 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps, | |||
660 | return ERR_PTR(r); | 608 | return ERR_PTR(r); |
661 | } | 609 | } |
662 | 610 | ||
663 | static struct priority_group *parse_priority_group(struct arg_set *as, | 611 | static struct priority_group *parse_priority_group(struct dm_arg_set *as, |
664 | struct multipath *m) | 612 | struct multipath *m) |
665 | { | 613 | { |
666 | static struct param _params[] = { | 614 | static struct dm_arg _args[] = { |
667 | {1, 1024, "invalid number of paths"}, | 615 | {1, 1024, "invalid number of paths"}, |
668 | {0, 1024, "invalid number of selector args"} | 616 | {0, 1024, "invalid number of selector args"} |
669 | }; | 617 | }; |
670 | 618 | ||
671 | int r; | 619 | int r; |
672 | unsigned i, nr_selector_args, nr_params; | 620 | unsigned i, nr_selector_args, nr_args; |
673 | struct priority_group *pg; | 621 | struct priority_group *pg; |
674 | struct dm_target *ti = m->ti; | 622 | struct dm_target *ti = m->ti; |
675 | 623 | ||
@@ -693,26 +641,26 @@ static struct priority_group *parse_priority_group(struct arg_set *as, | |||
693 | /* | 641 | /* |
694 | * read the paths | 642 | * read the paths |
695 | */ | 643 | */ |
696 | r = read_param(_params, shift(as), &pg->nr_pgpaths, &ti->error); | 644 | r = dm_read_arg(_args, as, &pg->nr_pgpaths, &ti->error); |
697 | if (r) | 645 | if (r) |
698 | goto bad; | 646 | goto bad; |
699 | 647 | ||
700 | r = read_param(_params + 1, shift(as), &nr_selector_args, &ti->error); | 648 | r = dm_read_arg(_args + 1, as, &nr_selector_args, &ti->error); |
701 | if (r) | 649 | if (r) |
702 | goto bad; | 650 | goto bad; |
703 | 651 | ||
704 | nr_params = 1 + nr_selector_args; | 652 | nr_args = 1 + nr_selector_args; |
705 | for (i = 0; i < pg->nr_pgpaths; i++) { | 653 | for (i = 0; i < pg->nr_pgpaths; i++) { |
706 | struct pgpath *pgpath; | 654 | struct pgpath *pgpath; |
707 | struct arg_set path_args; | 655 | struct dm_arg_set path_args; |
708 | 656 | ||
709 | if (as->argc < nr_params) { | 657 | if (as->argc < nr_args) { |
710 | ti->error = "not enough path parameters"; | 658 | ti->error = "not enough path parameters"; |
711 | r = -EINVAL; | 659 | r = -EINVAL; |
712 | goto bad; | 660 | goto bad; |
713 | } | 661 | } |
714 | 662 | ||
715 | path_args.argc = nr_params; | 663 | path_args.argc = nr_args; |
716 | path_args.argv = as->argv; | 664 | path_args.argv = as->argv; |
717 | 665 | ||
718 | pgpath = parse_path(&path_args, &pg->ps, ti); | 666 | pgpath = parse_path(&path_args, &pg->ps, ti); |
@@ -723,7 +671,7 @@ static struct priority_group *parse_priority_group(struct arg_set *as, | |||
723 | 671 | ||
724 | pgpath->pg = pg; | 672 | pgpath->pg = pg; |
725 | list_add_tail(&pgpath->list, &pg->pgpaths); | 673 | list_add_tail(&pgpath->list, &pg->pgpaths); |
726 | consume(as, nr_params); | 674 | dm_consume_args(as, nr_args); |
727 | } | 675 | } |
728 | 676 | ||
729 | return pg; | 677 | return pg; |
@@ -733,28 +681,23 @@ static struct priority_group *parse_priority_group(struct arg_set *as, | |||
733 | return ERR_PTR(r); | 681 | return ERR_PTR(r); |
734 | } | 682 | } |
735 | 683 | ||
736 | static int parse_hw_handler(struct arg_set *as, struct multipath *m) | 684 | static int parse_hw_handler(struct dm_arg_set *as, struct multipath *m) |
737 | { | 685 | { |
738 | unsigned hw_argc; | 686 | unsigned hw_argc; |
739 | int ret; | 687 | int ret; |
740 | struct dm_target *ti = m->ti; | 688 | struct dm_target *ti = m->ti; |
741 | 689 | ||
742 | static struct param _params[] = { | 690 | static struct dm_arg _args[] = { |
743 | {0, 1024, "invalid number of hardware handler args"}, | 691 | {0, 1024, "invalid number of hardware handler args"}, |
744 | }; | 692 | }; |
745 | 693 | ||
746 | if (read_param(_params, shift(as), &hw_argc, &ti->error)) | 694 | if (dm_read_arg_group(_args, as, &hw_argc, &ti->error)) |
747 | return -EINVAL; | 695 | return -EINVAL; |
748 | 696 | ||
749 | if (!hw_argc) | 697 | if (!hw_argc) |
750 | return 0; | 698 | return 0; |
751 | 699 | ||
752 | if (hw_argc > as->argc) { | 700 | m->hw_handler_name = kstrdup(dm_shift_arg(as), GFP_KERNEL); |
753 | ti->error = "not enough arguments for hardware handler"; | ||
754 | return -EINVAL; | ||
755 | } | ||
756 | |||
757 | m->hw_handler_name = kstrdup(shift(as), GFP_KERNEL); | ||
758 | request_module("scsi_dh_%s", m->hw_handler_name); | 701 | request_module("scsi_dh_%s", m->hw_handler_name); |
759 | if (scsi_dh_handler_exist(m->hw_handler_name) == 0) { | 702 | if (scsi_dh_handler_exist(m->hw_handler_name) == 0) { |
760 | ti->error = "unknown hardware handler type"; | 703 | ti->error = "unknown hardware handler type"; |
@@ -778,7 +721,7 @@ static int parse_hw_handler(struct arg_set *as, struct multipath *m) | |||
778 | for (i = 0, p+=j+1; i <= hw_argc - 2; i++, p+=j+1) | 721 | for (i = 0, p+=j+1; i <= hw_argc - 2; i++, p+=j+1) |
779 | j = sprintf(p, "%s", as->argv[i]); | 722 | j = sprintf(p, "%s", as->argv[i]); |
780 | } | 723 | } |
781 | consume(as, hw_argc - 1); | 724 | dm_consume_args(as, hw_argc - 1); |
782 | 725 | ||
783 | return 0; | 726 | return 0; |
784 | fail: | 727 | fail: |
@@ -787,52 +730,45 @@ fail: | |||
787 | return ret; | 730 | return ret; |
788 | } | 731 | } |
789 | 732 | ||
790 | static int parse_features(struct arg_set *as, struct multipath *m) | 733 | static int parse_features(struct dm_arg_set *as, struct multipath *m) |
791 | { | 734 | { |
792 | int r; | 735 | int r; |
793 | unsigned argc; | 736 | unsigned argc; |
794 | struct dm_target *ti = m->ti; | 737 | struct dm_target *ti = m->ti; |
795 | const char *param_name; | 738 | const char *arg_name; |
796 | 739 | ||
797 | static struct param _params[] = { | 740 | static struct dm_arg _args[] = { |
798 | {0, 5, "invalid number of feature args"}, | 741 | {0, 5, "invalid number of feature args"}, |
799 | {1, 50, "pg_init_retries must be between 1 and 50"}, | 742 | {1, 50, "pg_init_retries must be between 1 and 50"}, |
800 | {0, 60000, "pg_init_delay_msecs must be between 0 and 60000"}, | 743 | {0, 60000, "pg_init_delay_msecs must be between 0 and 60000"}, |
801 | }; | 744 | }; |
802 | 745 | ||
803 | r = read_param(_params, shift(as), &argc, &ti->error); | 746 | r = dm_read_arg_group(_args, as, &argc, &ti->error); |
804 | if (r) | 747 | if (r) |
805 | return -EINVAL; | 748 | return -EINVAL; |
806 | 749 | ||
807 | if (!argc) | 750 | if (!argc) |
808 | return 0; | 751 | return 0; |
809 | 752 | ||
810 | if (argc > as->argc) { | ||
811 | ti->error = "not enough arguments for features"; | ||
812 | return -EINVAL; | ||
813 | } | ||
814 | |||
815 | do { | 753 | do { |
816 | param_name = shift(as); | 754 | arg_name = dm_shift_arg(as); |
817 | argc--; | 755 | argc--; |
818 | 756 | ||
819 | if (!strnicmp(param_name, MESG_STR("queue_if_no_path"))) { | 757 | if (!strcasecmp(arg_name, "queue_if_no_path")) { |
820 | r = queue_if_no_path(m, 1, 0); | 758 | r = queue_if_no_path(m, 1, 0); |
821 | continue; | 759 | continue; |
822 | } | 760 | } |
823 | 761 | ||
824 | if (!strnicmp(param_name, MESG_STR("pg_init_retries")) && | 762 | if (!strcasecmp(arg_name, "pg_init_retries") && |
825 | (argc >= 1)) { | 763 | (argc >= 1)) { |
826 | r = read_param(_params + 1, shift(as), | 764 | r = dm_read_arg(_args + 1, as, &m->pg_init_retries, &ti->error); |
827 | &m->pg_init_retries, &ti->error); | ||
828 | argc--; | 765 | argc--; |
829 | continue; | 766 | continue; |
830 | } | 767 | } |
831 | 768 | ||
832 | if (!strnicmp(param_name, MESG_STR("pg_init_delay_msecs")) && | 769 | if (!strcasecmp(arg_name, "pg_init_delay_msecs") && |
833 | (argc >= 1)) { | 770 | (argc >= 1)) { |
834 | r = read_param(_params + 2, shift(as), | 771 | r = dm_read_arg(_args + 2, as, &m->pg_init_delay_msecs, &ti->error); |
835 | &m->pg_init_delay_msecs, &ti->error); | ||
836 | argc--; | 772 | argc--; |
837 | continue; | 773 | continue; |
838 | } | 774 | } |
@@ -847,15 +783,15 @@ static int parse_features(struct arg_set *as, struct multipath *m) | |||
847 | static int multipath_ctr(struct dm_target *ti, unsigned int argc, | 783 | static int multipath_ctr(struct dm_target *ti, unsigned int argc, |
848 | char **argv) | 784 | char **argv) |
849 | { | 785 | { |
850 | /* target parameters */ | 786 | /* target arguments */ |
851 | static struct param _params[] = { | 787 | static struct dm_arg _args[] = { |
852 | {0, 1024, "invalid number of priority groups"}, | 788 | {0, 1024, "invalid number of priority groups"}, |
853 | {0, 1024, "invalid initial priority group number"}, | 789 | {0, 1024, "invalid initial priority group number"}, |
854 | }; | 790 | }; |
855 | 791 | ||
856 | int r; | 792 | int r; |
857 | struct multipath *m; | 793 | struct multipath *m; |
858 | struct arg_set as; | 794 | struct dm_arg_set as; |
859 | unsigned pg_count = 0; | 795 | unsigned pg_count = 0; |
860 | unsigned next_pg_num; | 796 | unsigned next_pg_num; |
861 | 797 | ||
@@ -876,11 +812,11 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc, | |||
876 | if (r) | 812 | if (r) |
877 | goto bad; | 813 | goto bad; |
878 | 814 | ||
879 | r = read_param(_params, shift(&as), &m->nr_priority_groups, &ti->error); | 815 | r = dm_read_arg(_args, &as, &m->nr_priority_groups, &ti->error); |
880 | if (r) | 816 | if (r) |
881 | goto bad; | 817 | goto bad; |
882 | 818 | ||
883 | r = read_param(_params + 1, shift(&as), &next_pg_num, &ti->error); | 819 | r = dm_read_arg(_args + 1, &as, &next_pg_num, &ti->error); |
884 | if (r) | 820 | if (r) |
885 | goto bad; | 821 | goto bad; |
886 | 822 | ||
@@ -1510,10 +1446,10 @@ static int multipath_message(struct dm_target *ti, unsigned argc, char **argv) | |||
1510 | } | 1446 | } |
1511 | 1447 | ||
1512 | if (argc == 1) { | 1448 | if (argc == 1) { |
1513 | if (!strnicmp(argv[0], MESG_STR("queue_if_no_path"))) { | 1449 | if (!strcasecmp(argv[0], "queue_if_no_path")) { |
1514 | r = queue_if_no_path(m, 1, 0); | 1450 | r = queue_if_no_path(m, 1, 0); |
1515 | goto out; | 1451 | goto out; |
1516 | } else if (!strnicmp(argv[0], MESG_STR("fail_if_no_path"))) { | 1452 | } else if (!strcasecmp(argv[0], "fail_if_no_path")) { |
1517 | r = queue_if_no_path(m, 0, 0); | 1453 | r = queue_if_no_path(m, 0, 0); |
1518 | goto out; | 1454 | goto out; |
1519 | } | 1455 | } |
@@ -1524,18 +1460,18 @@ static int multipath_message(struct dm_target *ti, unsigned argc, char **argv) | |||
1524 | goto out; | 1460 | goto out; |
1525 | } | 1461 | } |
1526 | 1462 | ||
1527 | if (!strnicmp(argv[0], MESG_STR("disable_group"))) { | 1463 | if (!strcasecmp(argv[0], "disable_group")) { |
1528 | r = bypass_pg_num(m, argv[1], 1); | 1464 | r = bypass_pg_num(m, argv[1], 1); |
1529 | goto out; | 1465 | goto out; |
1530 | } else if (!strnicmp(argv[0], MESG_STR("enable_group"))) { | 1466 | } else if (!strcasecmp(argv[0], "enable_group")) { |
1531 | r = bypass_pg_num(m, argv[1], 0); | 1467 | r = bypass_pg_num(m, argv[1], 0); |
1532 | goto out; | 1468 | goto out; |
1533 | } else if (!strnicmp(argv[0], MESG_STR("switch_group"))) { | 1469 | } else if (!strcasecmp(argv[0], "switch_group")) { |
1534 | r = switch_pg_num(m, argv[1]); | 1470 | r = switch_pg_num(m, argv[1]); |
1535 | goto out; | 1471 | goto out; |
1536 | } else if (!strnicmp(argv[0], MESG_STR("reinstate_path"))) | 1472 | } else if (!strcasecmp(argv[0], "reinstate_path")) |
1537 | action = reinstate_path; | 1473 | action = reinstate_path; |
1538 | else if (!strnicmp(argv[0], MESG_STR("fail_path"))) | 1474 | else if (!strcasecmp(argv[0], "fail_path")) |
1539 | action = fail_path; | 1475 | action = fail_path; |
1540 | else { | 1476 | else { |
1541 | DMWARN("Unrecognised multipath message received."); | 1477 | DMWARN("Unrecognised multipath message received."); |
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 03516c7f5be1..259ce99302fc 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
@@ -797,6 +797,63 @@ int dm_table_add_target(struct dm_table *t, const char *type, | |||
797 | return r; | 797 | return r; |
798 | } | 798 | } |
799 | 799 | ||
800 | /* | ||
801 | * Target argument parsing helpers. | ||
802 | */ | ||
803 | static int validate_next_arg(struct dm_arg *arg, struct dm_arg_set *arg_set, | ||
804 | unsigned *value, char **error, unsigned grouped) | ||
805 | { | ||
806 | const char *arg_str = dm_shift_arg(arg_set); | ||
807 | |||
808 | if (!arg_str || | ||
809 | (sscanf(arg_str, "%u", value) != 1) || | ||
810 | (*value < arg->min) || | ||
811 | (*value > arg->max) || | ||
812 | (grouped && arg_set->argc < *value)) { | ||
813 | *error = arg->error; | ||
814 | return -EINVAL; | ||
815 | } | ||
816 | |||
817 | return 0; | ||
818 | } | ||
819 | |||
820 | int dm_read_arg(struct dm_arg *arg, struct dm_arg_set *arg_set, | ||
821 | unsigned *value, char **error) | ||
822 | { | ||
823 | return validate_next_arg(arg, arg_set, value, error, 0); | ||
824 | } | ||
825 | EXPORT_SYMBOL(dm_read_arg); | ||
826 | |||
827 | int dm_read_arg_group(struct dm_arg *arg, struct dm_arg_set *arg_set, | ||
828 | unsigned *value, char **error) | ||
829 | { | ||
830 | return validate_next_arg(arg, arg_set, value, error, 1); | ||
831 | } | ||
832 | EXPORT_SYMBOL(dm_read_arg_group); | ||
833 | |||
834 | const char *dm_shift_arg(struct dm_arg_set *as) | ||
835 | { | ||
836 | char *r; | ||
837 | |||
838 | if (as->argc) { | ||
839 | as->argc--; | ||
840 | r = *as->argv; | ||
841 | as->argv++; | ||
842 | return r; | ||
843 | } | ||
844 | |||
845 | return NULL; | ||
846 | } | ||
847 | EXPORT_SYMBOL(dm_shift_arg); | ||
848 | |||
849 | void dm_consume_args(struct dm_arg_set *as, unsigned num_args) | ||
850 | { | ||
851 | BUG_ON(as->argc < num_args); | ||
852 | as->argc -= num_args; | ||
853 | as->argv += num_args; | ||
854 | } | ||
855 | EXPORT_SYMBOL(dm_consume_args); | ||
856 | |||
800 | static int dm_table_set_type(struct dm_table *t) | 857 | static int dm_table_set_type(struct dm_table *t) |
801 | { | 858 | { |
802 | unsigned i; | 859 | unsigned i; |