Commit 498f0103ea13123e007660def9072a0b7dd1c599

Authored by Mike Snitzer
Committed by Alasdair G Kergon
1 parent a6e50b409d

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>

Showing 4 changed files with 147 additions and 112 deletions Side-by-side Diff

drivers/md/dm-crypt.c
... ... @@ -30,7 +30,6 @@
30 30 #include <linux/device-mapper.h>
31 31  
32 32 #define DM_MSG_PREFIX "crypt"
33   -#define MESG_STR(x) x, sizeof(x)
34 33  
35 34 /*
36 35 * context holding the current state of a multi-part conversion
37 36  
... ... @@ -1770,12 +1769,12 @@
1770 1769 if (argc < 2)
1771 1770 goto error;
1772 1771  
1773   - if (!strnicmp(argv[0], MESG_STR("key"))) {
  1772 + if (!strcasecmp(argv[0], "key")) {
1774 1773 if (!test_bit(DM_CRYPT_SUSPENDED, &cc->flags)) {
1775 1774 DMWARN("not suspended during key manipulation.");
1776 1775 return -EINVAL;
1777 1776 }
1778   - if (argc == 3 && !strnicmp(argv[1], MESG_STR("set"))) {
  1777 + if (argc == 3 && !strcasecmp(argv[1], "set")) {
1779 1778 ret = crypt_set_key(cc, argv[2]);
1780 1779 if (ret)
1781 1780 return ret;
... ... @@ -1783,7 +1782,7 @@
1783 1782 ret = cc->iv_gen_ops->init(cc);
1784 1783 return ret;
1785 1784 }
1786   - if (argc == 2 && !strnicmp(argv[1], MESG_STR("wipe"))) {
  1785 + if (argc == 2 && !strcasecmp(argv[1], "wipe")) {
1787 1786 if (cc->iv_gen_ops && cc->iv_gen_ops->wipe) {
1788 1787 ret = cc->iv_gen_ops->wipe(cc);
1789 1788 if (ret)
drivers/md/dm-mpath.c
... ... @@ -22,7 +22,6 @@
22 22 #include <linux/atomic.h>
23 23  
24 24 #define DM_MSG_PREFIX "multipath"
25   -#define MESG_STR(x) x, sizeof(x)
26 25 #define DM_PG_INIT_DELAY_MSECS 2000
27 26 #define DM_PG_INIT_DELAY_DEFAULT ((unsigned) -1)
28 27  
29 28  
30 29  
31 30  
32 31  
... ... @@ -505,80 +504,29 @@
505 504 * <#paths> <#per-path selector args>
506 505 * [<path> [<arg>]* ]+ ]+
507 506 *---------------------------------------------------------------*/
508   -struct param {
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,
  507 +static int parse_path_selector(struct dm_arg_set *as, struct priority_group *pg,
554 508 struct dm_target *ti)
555 509 {
556 510 int r;
557 511 struct path_selector_type *pst;
558 512 unsigned ps_argc;
559 513  
560   - static struct param _params[] = {
  514 + static struct dm_arg _args[] = {
561 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 519 if (!pst) {
566 520 ti->error = "unknown path selector type";
567 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 525 if (r) {
572 526 dm_put_path_selector(pst);
573 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 530 r = pst->create(&pg->ps, ps_argc, as->argv);
583 531 if (r) {
584 532 dm_put_path_selector(pst);
585 533  
... ... @@ -587,12 +535,12 @@
587 535 }
588 536  
589 537 pg->ps.type = pst;
590   - consume(as, ps_argc);
  538 + dm_consume_args(as, ps_argc);
591 539  
592 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 544 struct dm_target *ti)
597 545 {
598 546 int r;
... ... @@ -609,7 +557,7 @@
609 557 if (!p)
610 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 561 &p->path.dev);
614 562 if (r) {
615 563 ti->error = "error getting device";
616 564  
617 565  
... ... @@ -660,16 +608,16 @@
660 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 612 struct multipath *m)
665 613 {
666   - static struct param _params[] = {
  614 + static struct dm_arg _args[] = {
667 615 {1, 1024, "invalid number of paths"},
668 616 {0, 1024, "invalid number of selector args"}
669 617 };
670 618  
671 619 int r;
672   - unsigned i, nr_selector_args, nr_params;
  620 + unsigned i, nr_selector_args, nr_args;
673 621 struct priority_group *pg;
674 622 struct dm_target *ti = m->ti;
675 623  
676 624  
677 625  
678 626  
679 627  
680 628  
... ... @@ -693,26 +641,26 @@
693 641 /*
694 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 645 if (r)
698 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 649 if (r)
702 650 goto bad;
703 651  
704   - nr_params = 1 + nr_selector_args;
  652 + nr_args = 1 + nr_selector_args;
705 653 for (i = 0; i < pg->nr_pgpaths; i++) {
706 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 658 ti->error = "not enough path parameters";
711 659 r = -EINVAL;
712 660 goto bad;
713 661 }
714 662  
715   - path_args.argc = nr_params;
  663 + path_args.argc = nr_args;
716 664 path_args.argv = as->argv;
717 665  
718 666 pgpath = parse_path(&path_args, &pg->ps, ti);
... ... @@ -723,7 +671,7 @@
723 671  
724 672 pgpath->pg = pg;
725 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 677 return pg;
730 678  
731 679  
732 680  
... ... @@ -733,28 +681,23 @@
733 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 686 unsigned hw_argc;
739 687 int ret;
740 688 struct dm_target *ti = m->ti;
741 689  
742   - static struct param _params[] = {
  690 + static struct dm_arg _args[] = {
743 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 695 return -EINVAL;
748 696  
749 697 if (!hw_argc)
750 698 return 0;
751 699  
752   - if (hw_argc > as->argc) {
753   - ti->error = "not enough arguments for hardware handler";
754   - return -EINVAL;
755   - }
756   -
757   - m->hw_handler_name = kstrdup(shift(as), GFP_KERNEL);
  700 + m->hw_handler_name = kstrdup(dm_shift_arg(as), GFP_KERNEL);
758 701 request_module("scsi_dh_%s", m->hw_handler_name);
759 702 if (scsi_dh_handler_exist(m->hw_handler_name) == 0) {
760 703 ti->error = "unknown hardware handler type";
... ... @@ -778,7 +721,7 @@
778 721 for (i = 0, p+=j+1; i <= hw_argc - 2; i++, p+=j+1)
779 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 726 return 0;
784 727 fail:
785 728  
786 729  
787 730  
788 731  
789 732  
790 733  
791 734  
792 735  
793 736  
794 737  
... ... @@ -787,52 +730,45 @@
787 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 735 int r;
793 736 unsigned argc;
794 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 741 {0, 5, "invalid number of feature args"},
799 742 {1, 50, "pg_init_retries must be between 1 and 50"},
800 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 747 if (r)
805 748 return -EINVAL;
806 749  
807 750 if (!argc)
808 751 return 0;
809 752  
810   - if (argc > as->argc) {
811   - ti->error = "not enough arguments for features";
812   - return -EINVAL;
813   - }
814   -
815 753 do {
816   - param_name = shift(as);
  754 + arg_name = dm_shift_arg(as);
817 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 758 r = queue_if_no_path(m, 1, 0);
821 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 763 (argc >= 1)) {
826   - r = read_param(_params + 1, shift(as),
827   - &m->pg_init_retries, &ti->error);
  764 + r = dm_read_arg(_args + 1, as, &m->pg_init_retries, &ti->error);
828 765 argc--;
829 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 770 (argc >= 1)) {
834   - r = read_param(_params + 2, shift(as),
835   - &m->pg_init_delay_msecs, &ti->error);
  771 + r = dm_read_arg(_args + 2, as, &m->pg_init_delay_msecs, &ti->error);
836 772 argc--;
837 773 continue;
838 774 }
839 775  
... ... @@ -847,15 +783,15 @@
847 783 static int multipath_ctr(struct dm_target *ti, unsigned int argc,
848 784 char **argv)
849 785 {
850   - /* target parameters */
851   - static struct param _params[] = {
  786 + /* target arguments */
  787 + static struct dm_arg _args[] = {
852 788 {0, 1024, "invalid number of priority groups"},
853 789 {0, 1024, "invalid initial priority group number"},
854 790 };
855 791  
856 792 int r;
857 793 struct multipath *m;
858   - struct arg_set as;
  794 + struct dm_arg_set as;
859 795 unsigned pg_count = 0;
860 796 unsigned next_pg_num;
861 797  
862 798  
... ... @@ -876,11 +812,11 @@
876 812 if (r)
877 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 816 if (r)
881 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 820 if (r)
885 821 goto bad;
886 822  
887 823  
... ... @@ -1510,10 +1446,10 @@
1510 1446 }
1511 1447  
1512 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 1450 r = queue_if_no_path(m, 1, 0);
1515 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 1453 r = queue_if_no_path(m, 0, 0);
1518 1454 goto out;
1519 1455 }
1520 1456  
1521 1457  
1522 1458  
1523 1459  
... ... @@ -1524,18 +1460,18 @@
1524 1460 goto out;
1525 1461 }
1526 1462  
1527   - if (!strnicmp(argv[0], MESG_STR("disable_group"))) {
  1463 + if (!strcasecmp(argv[0], "disable_group")) {
1528 1464 r = bypass_pg_num(m, argv[1], 1);
1529 1465 goto out;
1530   - } else if (!strnicmp(argv[0], MESG_STR("enable_group"))) {
  1466 + } else if (!strcasecmp(argv[0], "enable_group")) {
1531 1467 r = bypass_pg_num(m, argv[1], 0);
1532 1468 goto out;
1533   - } else if (!strnicmp(argv[0], MESG_STR("switch_group"))) {
  1469 + } else if (!strcasecmp(argv[0], "switch_group")) {
1534 1470 r = switch_pg_num(m, argv[1]);
1535 1471 goto out;
1536   - } else if (!strnicmp(argv[0], MESG_STR("reinstate_path")))
  1472 + } else if (!strcasecmp(argv[0], "reinstate_path"))
1537 1473 action = reinstate_path;
1538   - else if (!strnicmp(argv[0], MESG_STR("fail_path")))
  1474 + else if (!strcasecmp(argv[0], "fail_path"))
1539 1475 action = fail_path;
1540 1476 else {
1541 1477 DMWARN("Unrecognised multipath message received.");
drivers/md/dm-table.c
... ... @@ -797,6 +797,63 @@
797 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 857 static int dm_table_set_type(struct dm_table *t)
801 858 {
802 859 unsigned i;
include/linux/device-mapper.h
... ... @@ -208,6 +208,49 @@
208 208 int dm_register_target(struct target_type *t);
209 209 void dm_unregister_target(struct target_type *t);
210 210  
  211 +/*
  212 + * Target argument parsing.
  213 + */
  214 +struct dm_arg_set {
  215 + unsigned argc;
  216 + char **argv;
  217 +};
  218 +
  219 +/*
  220 + * The minimum and maximum value of a numeric argument, together with
  221 + * the error message to use if the number is found to be outside that range.
  222 + */
  223 +struct dm_arg {
  224 + unsigned min;
  225 + unsigned max;
  226 + char *error;
  227 +};
  228 +
  229 +/*
  230 + * Validate the next argument, either returning it as *value or, if invalid,
  231 + * returning -EINVAL and setting *error.
  232 + */
  233 +int dm_read_arg(struct dm_arg *arg, struct dm_arg_set *arg_set,
  234 + unsigned *value, char **error);
  235 +
  236 +/*
  237 + * Process the next argument as the start of a group containing between
  238 + * arg->min and arg->max further arguments. Either return the size as
  239 + * *num_args or, if invalid, return -EINVAL and set *error.
  240 + */
  241 +int dm_read_arg_group(struct dm_arg *arg, struct dm_arg_set *arg_set,
  242 + unsigned *num_args, char **error);
  243 +
  244 +/*
  245 + * Return the current argument and shift to the next.
  246 + */
  247 +const char *dm_shift_arg(struct dm_arg_set *as);
  248 +
  249 +/*
  250 + * Move through num_args arguments.
  251 + */
  252 +void dm_consume_args(struct dm_arg_set *as, unsigned num_args);
  253 +
211 254 /*-----------------------------------------------------------------
212 255 * Functions for creating and manipulating mapped devices.
213 256 * Drop the reference with dm_put when you finish with the object.