Whamcloud - gitweb
LU-9480 lnet: cleanup lnetctl and cyaml 49/27349/15
authorSonia <sonia.sharma@intel.com>
Wed, 31 May 2017 08:48:15 +0000 (01:48 -0700)
committerAmir Shehata <amir.shehata@intel.com>
Tue, 22 Aug 2017 16:29:20 +0000 (16:29 +0000)
lnetctl set commands results in segmentation fault
if no values are provided. This patch makes them
show help if no values are provided to with set commands.

Made general cleanups in the lnetctl code to consolidate
where the help is being printed. Created a function
check_cmd() which checks for the expected number of
arguments and for the -h/--help option and prints
the help string if either scenario is encountered.

fixed the fsm transition in cyaml to allow proper
parsing of empty cyaml documents

Change-Id: Ia081e9304ba2d6baa804e4c8890fb1988d860c1c
Test-Parameters: trivial
Signed-off-by: Amir Shehata <amir.shehata@intel.com>
Signed-off-by: Sonia Sharma <sonia.sharma@intel.com>
Reviewed-on: https://review.whamcloud.com/27349
Reviewed-by: Olaf Weber <olaf.weber@hpe.com>
Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com>
lnet/utils/cyaml/cyaml.c
lnet/utils/lnetconfig/liblnetconfig.c
lnet/utils/lnetctl.c

index cd8fac6..fbe0d4f 100644 (file)
@@ -186,6 +186,17 @@ static char *token_type_string[] = {
        [YAML_SCALAR_TOKEN] = "YAML_SCALAR_TOKEN",
 };
 
+static char *state_string[] = {
+       [TREE_STATE_COMPLETE] = "COMPLETE",
+       [TREE_STATE_INITED] = "INITED",
+       [TREE_STATE_TREE_STARTED] = "TREE_STARTED",
+       [TREE_STATE_BLK_STARTED] = "BLK_STARTED",
+       [TREE_STATE_KEY] = "KEY",
+       [TREE_STATE_KEY_FILLED] = "KEY_FILLED",
+       [TREE_STATE_VALUE] = "VALUE",
+       [TREE_STATE_SEQ_START] = "SEQ_START",
+};
+
 static void cYAML_ll_free(struct list_head *ll)
 {
        struct cYAML_ll *node, *tmp;
@@ -475,7 +486,8 @@ static enum cYAML_handler_error yaml_stream_end(yaml_token_t *token,
                                                struct cYAML_tree_node *tree)
 {
        if (tree->state != TREE_STATE_TREE_STARTED &&
-           tree->state != TREE_STATE_COMPLETE)
+           tree->state != TREE_STATE_COMPLETE &&
+           tree->state != TREE_STATE_INITED)
                return CYAML_ERROR_UNEXPECTED_STATE;
 
        tree->state = TREE_STATE_INITED;
@@ -1171,13 +1183,15 @@ struct cYAML *cYAML_build_tree(char *yaml_file,
        /* Read the event sequence. */
        while (!done) {
                /*
-               * Go through the parser and build a cYAML representation
-               * of the passed in YAML text
-               */
+                * Go through the parser and build a cYAML representation
+                * of the passed in YAML text
+                */
                yaml_parser_scan(&parser, &token);
 
                if (debug)
-                       fprintf(stderr, "token.type = %s: %s\n",
+                       fprintf(stderr, "tree.state(%p:%d) = %s, token.type ="
+                                       " %s: %s\n",
+                               &tree, tree.state, state_string[tree.state],
                                token_type_string[token.type],
                                (token.type == YAML_SCALAR_TOKEN) ?
                                (char*)token.data.scalar.value : "");
index c32a494..fb938e4 100644 (file)
@@ -240,6 +240,7 @@ int lustre_lnet_add_intf_descr(struct list_head *list, char *intf, int len)
 void lustre_lnet_init_nw_descr(struct lnet_dlc_network_descr *nw_descr)
 {
        if (nw_descr != NULL) {
+               nw_descr->nw_id = 0;
                INIT_LIST_HEAD(&nw_descr->network_on_rule);
                INIT_LIST_HEAD(&nw_descr->nw_intflist);
        }
@@ -1543,10 +1544,11 @@ int lustre_lnet_config_ni(struct lnet_dlc_network_descr *nw_descr,
 
        snprintf(err_str, sizeof(err_str), "\"success\"");
 
-       if (ip2net == NULL && nw_descr == NULL) {
+       if (ip2net == NULL && (nw_descr == NULL || nw_descr->nw_id == 0 ||
+           list_empty(&nw_descr->nw_intflist))) {
                snprintf(err_str,
                         sizeof(err_str),
-                        "\"mandatory parameters not specified.\"");
+                        "\"missing mandatory parameters\"");
                rc = LUSTRE_CFG_RC_MISSING_PARAM;
                goto out;
        }
@@ -1680,7 +1682,8 @@ int lustre_lnet_del_ni(struct lnet_dlc_network_descr *nw_descr,
 
        snprintf(err_str, sizeof(err_str), "\"success\"");
 
-       if (nw_descr == NULL) {
+       if (nw_descr == NULL || nw_descr->nw_id == 0 ||
+           list_empty(&nw_descr->nw_intflist)) {
                snprintf(err_str,
                         sizeof(err_str),
                         "\"missing mandatory parameter\"");
index 947e5aa..cfd16fe 100644 (file)
@@ -60,6 +60,41 @@ static int jt_set_discovery(int argc, char **argv);
 static int jt_list_peer(int argc, char **argv);
 /*static int jt_show_peer(int argc, char **argv);*/
 static int lnetctl_list_commands(int argc, char **argv);
+static int jt_import(int argc, char **argv);
+static int jt_export(int argc, char **argv);
+static int jt_ping(int argc, char **argv);
+static int jt_discover(int argc, char **argv);
+static int jt_lnet(int argc, char **argv);
+static int jt_route(int argc, char **argv);
+static int jt_net(int argc, char **argv);
+static int jt_routing(int argc, char **argv);
+static int jt_set(int argc, char **argv);
+static int jt_stats(int argc, char **argv);
+static int jt_global(int argc, char **argv);
+static int jt_peers(int argc, char **argv);
+
+
+command_t cmd_list[] = {
+       {"lnet", jt_lnet, 0, "lnet {configure | unconfigure} [--all]"},
+       {"route", jt_route, 0, "route {add | del | show | help}"},
+       {"net", jt_net, 0, "net {add | del | show | help}"},
+       {"routing", jt_routing, 0, "routing {show | help}"},
+       {"set", jt_set, 0, "set {tiny_buffers | small_buffers | large_buffers"
+                          " | routing | numa_range | max_interfaces"
+                          " | discovery}"},
+       {"import", jt_import, 0, "import FILE.yaml"},
+       {"export", jt_export, 0, "export FILE.yaml"},
+       {"stats", jt_stats, 0, "stats {show | help}"},
+       {"global", jt_global, 0, "global {show | help}"},
+       {"peer", jt_peers, 0, "peer {add | del | show | help}"},
+       {"ping", jt_ping, 0, "ping nid,[nid,...]"},
+       {"discover", jt_discover, 0, "discover nid[,nid,...]"},
+       {"help", Parser_help, 0, "help"},
+       {"exit", Parser_quit, 0, "quit"},
+       {"quit", Parser_quit, 0, "quit"},
+       {"--list-commands", lnetctl_list_commands, 0, "list commands"},
+       { 0, 0, 0, NULL }
+};
 
 command_t lnet_cmds[] = {
        {"configure", jt_config_lnet, 0, "configure lnet\n"
@@ -102,7 +137,7 @@ command_t net_cmds[] = {
        {"show", jt_show_net, 0, "show networks\n"
         "\t--net: net name (e.g. tcp0) to filter on\n"
         "\t--verbose: display detailed output per network."
-                      "optional argument of 2 outputs more stats\n"},
+                      " Optional argument of '2' outputs more stats\n"},
        { 0, 0, 0, NULL }
 };
 
@@ -156,7 +191,7 @@ command_t peer_cmds[] = {
        {"show", jt_show_peer, 0, "show peer information\n"
         "\t--nid: NID of peer to filter on.\n"
         "\t--verbose: display detailed output per peer."
-                      "optional argument of 2 outputs more stats\n"},
+                      " Optional argument of '2' outputs more stats\n"},
        {"list", jt_list_peer, 0, "list all peers\n"},
        { 0, 0, 0, NULL }
 };
@@ -183,6 +218,9 @@ static int parse_long(const char *number, long int *value)
 {
        char *end;
 
+       if (!number)
+               return -1;
+
        *value = strtol(number,  &end, 0);
        if (end != NULL && *end != 0)
                return -1;
@@ -190,11 +228,12 @@ static int parse_long(const char *number, long int *value)
        return 0;
 }
 
-static int handle_help(const command_t *cmd_list, const char *cmd,
-                      const char *sub_cmd, int argc, char **argv)
+static int check_cmd(const command_t *cmd_list, const char *cmd,
+                    const char *sub_cmd, const int min_args,
+                    int argc, char **argv)
 {
        int opt;
-       int rc = -1;
+       int rc = 0;
        optind = 0;
        opterr = 0;
 
@@ -204,19 +243,28 @@ static int handle_help(const command_t *cmd_list, const char *cmd,
                { .name = NULL }
        };
 
+       if (argc < min_args) {
+               print_help(cmd_list, cmd, sub_cmd);
+               rc = -1;
+               goto out;
+       } else if (argc > 2) {
+               return 0;
+       }
+
        while ((opt = getopt_long(argc, argv, short_options,
                                  long_options, NULL)) != -1) {
                switch (opt) {
                case 'h':
                        print_help(cmd_list, cmd, sub_cmd);
-                       rc = 0;
+                       rc = 1;
                        break;
                default:
-                       rc = -1;
+                       rc = 0;
                        break;
                }
        }
 
+out:
        opterr = 1;
        optind = 0;
        return rc;
@@ -228,8 +276,9 @@ static int jt_set_max_intf(int argc, char **argv)
        int rc;
        struct cYAML *err_rc = NULL;
 
-       if (handle_help(set_cmds, "set", "max_interfaces", argc, argv) == 0)
-               return 0;
+       rc = check_cmd(set_cmds, "set", "max_interfaces", 2, argc, argv);
+       if (rc)
+               return rc;
 
        rc = parse_long(argv[1], &value);
        if (rc != 0) {
@@ -255,8 +304,9 @@ static int jt_set_numa(int argc, char **argv)
        int rc;
        struct cYAML *err_rc = NULL;
 
-       if (handle_help(set_cmds, "set", "numa_range", argc, argv) == 0)
-               return 0;
+       rc = check_cmd(set_cmds, "set", "numa_range", 2, argc, argv);
+       if (rc)
+               return rc;
 
        rc = parse_long(argv[1], &value);
        if (rc != 0) {
@@ -282,8 +332,9 @@ static int jt_set_discovery(int argc, char **argv)
        int rc;
        struct cYAML *err_rc = NULL;
 
-       if (handle_help(set_cmds, "set", "discovery", argc, argv) == 0)
-               return 0;
+       rc = check_cmd(set_cmds, "set", "discovery", 2, argc, argv);
+       if (rc)
+               return rc;
 
        rc = parse_long(argv[1], &value);
        if (rc != 0) {
@@ -309,8 +360,9 @@ static int jt_set_tiny(int argc, char **argv)
        int rc;
        struct cYAML *err_rc = NULL;
 
-       if (handle_help(set_cmds, "set", "tiny_buffers", argc, argv) == 0)
-               return 0;
+       rc = check_cmd(set_cmds, "set", "tiny_buffers", 2, argc, argv);
+       if (rc)
+               return rc;
 
        rc = parse_long(argv[1], &value);
        if (rc != 0) {
@@ -336,8 +388,9 @@ static int jt_set_small(int argc, char **argv)
        int rc;
        struct cYAML *err_rc = NULL;
 
-       if (handle_help(set_cmds, "set", "small_buffers", argc, argv) == 0)
-               return 0;
+       rc = check_cmd(set_cmds, "set", "small_buffers", 2, argc, argv);
+       if (rc)
+               return rc;
 
        rc = parse_long(argv[1], &value);
        if (rc != 0) {
@@ -363,8 +416,9 @@ static int jt_set_large(int argc, char **argv)
        int rc;
        struct cYAML *err_rc = NULL;
 
-       if (handle_help(set_cmds, "set", "large_buffers", argc, argv) == 0)
-               return 0;
+       rc = check_cmd(set_cmds, "set", "large_buffers", 2, argc, argv);
+       if (rc)
+               return rc;
 
        rc = parse_long(argv[1], &value);
        if (rc != 0) {
@@ -390,8 +444,9 @@ static int jt_set_routing(int argc, char **argv)
        struct cYAML *err_rc = NULL;
        int rc;
 
-       if (handle_help(set_cmds, "set", "routing", argc, argv) == 0)
-               return 0;
+       rc = check_cmd(set_cmds, "set", "routing", 2, argc, argv);
+       if (rc)
+               return rc;
 
        rc = parse_long(argv[1], &value);
        if (rc != 0 || (value != 0 && value != 1)) {
@@ -420,22 +475,22 @@ static int jt_config_lnet(int argc, char **argv)
        bool load_mod_params = false;
        int rc, opt;
 
-       const char *const short_options = "ah";
+       const char *const short_options = "a";
        static const struct option long_options[] = {
                { .name = "all",  .has_arg = no_argument, .val = 'a' },
-               { .name = "help", .has_arg = no_argument, .val = 'h' },
                { .name = NULL }
        };
 
+       rc = check_cmd(lnet_cmds, "lnet", "configure", 0, argc, argv);
+       if (rc)
+               return rc;
+
        while ((opt = getopt_long(argc, argv, short_options,
                                   long_options, NULL)) != -1) {
                switch (opt) {
                case 'a':
                        load_mod_params = true;
                        break;
-               case 'h':
-                       print_help(lnet_cmds, "lnet", "configure");
-                       return 0;
                default:
                        return 0;
                }
@@ -457,8 +512,9 @@ static int jt_unconfig_lnet(int argc, char **argv)
        struct cYAML *err_rc = NULL;
        int rc;
 
-       if (handle_help(lnet_cmds, "lnet", "unconfigure", argc, argv) == 0)
-               return 0;
+       rc = check_cmd(lnet_cmds, "lnet", "unconfigure", 0, argc, argv);
+       if (rc)
+               return rc;
 
        rc = lustre_lnet_config_ni_system(LNET_UNCONFIGURE, 0, -1, &err_rc);
 
@@ -476,15 +532,18 @@ static int jt_add_route(int argc, char **argv)
        struct cYAML *err_rc = NULL;
        int rc, opt;
 
-       const char *const short_options = "n:g:c:p:h";
+       const char *const short_options = "n:g:c:p:";
        static const struct option long_options[] = {
        { .name = "net",       .has_arg = required_argument, .val = 'n' },
        { .name = "gateway",   .has_arg = required_argument, .val = 'g' },
        { .name = "hop-count", .has_arg = required_argument, .val = 'c' },
        { .name = "priority",  .has_arg = required_argument, .val = 'p' },
-       { .name = "help",      .has_arg = no_argument,       .val = 'h' },
        { .name = NULL } };
 
+       rc = check_cmd(route_cmds, "route", "add", 0, argc, argv);
+       if (rc)
+               return rc;
+
        while ((opt = getopt_long(argc, argv, short_options,
                                   long_options, NULL)) != -1) {
                switch (opt) {
@@ -510,9 +569,6 @@ static int jt_add_route(int argc, char **argv)
                                continue;
                        }
                        break;
-               case 'h':
-                       print_help(route_cmds, "route", "add");
-                       return 0;
                default:
                        return 0;
                }
@@ -542,7 +598,7 @@ static int jt_add_ni(int argc, char **argv)
        memset(&tunables, 0, sizeof(tunables));
        lustre_lnet_init_nw_descr(&nw_descr);
 
-       const char *const short_options = "n:i:p:t:c:b:r:s:h";
+       const char *const short_options = "n:i:p:t:c:b:r:s:";
        static const struct option long_options[] = {
        { .name = "net",          .has_arg = required_argument, .val = 'n' },
        { .name = "if",           .has_arg = required_argument, .val = 'i' },
@@ -553,9 +609,12 @@ static int jt_add_ni(int argc, char **argv)
                                  .has_arg = required_argument, .val = 'b' },
        { .name = "credits",      .has_arg = required_argument, .val = 'r' },
        { .name = "cpt",          .has_arg = required_argument, .val = 's' },
-       { .name = "help",         .has_arg = no_argument,       .val = 'h' },
        { .name = NULL } };
 
+       rc = check_cmd(net_cmds, "net", "add", 0, argc, argv);
+       if (rc)
+               return rc;
+
        while ((opt = getopt_long(argc, argv, short_options,
                                   long_options, NULL)) != -1) {
                switch (opt) {
@@ -611,9 +670,6 @@ static int jt_add_ni(int argc, char **argv)
                                                     strlen(optarg), 0,
                                                     UINT_MAX, &global_cpts);
                        break;
-               case 'h':
-                       print_help(net_cmds, "net", "add");
-                       return 0;
                default:
                        return 0;
                }
@@ -650,13 +706,16 @@ static int jt_del_route(int argc, char **argv)
        struct cYAML *err_rc = NULL;
        int rc, opt;
 
-       const char *const short_options = "n:g:h";
+       const char *const short_options = "n:g:";
        static const struct option long_options[] = {
                { .name = "net",     .has_arg = required_argument, .val = 'n' },
                { .name = "gateway", .has_arg = required_argument, .val = 'g' },
-               { .name = "help",    .has_arg = no_argument,       .val = 'h' },
                { .name = NULL } };
 
+       rc = check_cmd(route_cmds, "route", "del", 0, argc, argv);
+       if (rc)
+               return rc;
+
        while ((opt = getopt_long(argc, argv, short_options,
                                   long_options, NULL)) != -1) {
                switch (opt) {
@@ -666,9 +725,6 @@ static int jt_del_route(int argc, char **argv)
                case 'g':
                        gateway = optarg;
                        break;
-               case 'h':
-                       print_help(route_cmds, "route", "del");
-                       return 0;
                default:
                        return 0;
                }
@@ -692,13 +748,16 @@ static int jt_del_ni(int argc, char **argv)
 
        lustre_lnet_init_nw_descr(&nw_descr);
 
-       const char *const short_options = "n:i:h";
+       const char *const short_options = "n:i:";
        static const struct option long_options[] = {
        { .name = "net",        .has_arg = required_argument,   .val = 'n' },
        { .name = "if",         .has_arg = required_argument,   .val = 'i' },
-       { .name = "help",       .has_arg = no_argument,         .val = 'h' },
        { .name = NULL } };
 
+       rc = check_cmd(net_cmds, "net", "del", 0, argc, argv);
+       if (rc)
+               return rc;
+
        while ((opt = getopt_long(argc, argv, short_options,
                                   long_options, NULL)) != -1) {
                switch (opt) {
@@ -714,9 +773,6 @@ static int jt_del_ni(int argc, char **argv)
                                goto out;
                        }
                        break;
-               case 'h':
-                       print_help(net_cmds, "net", "del");
-                       return 0;
                default:
                        return 0;
                }
@@ -740,16 +796,19 @@ static int jt_show_route(int argc, char **argv)
        int detail = 0, rc, opt;
        struct cYAML *err_rc = NULL, *show_rc = NULL;
 
-       const char *const short_options = "n:g:h:p:vh";
+       const char *const short_options = "n:g:h:p:v";
        static const struct option long_options[] = {
        { .name = "net",       .has_arg = required_argument, .val = 'n' },
        { .name = "gateway",   .has_arg = required_argument, .val = 'g' },
        { .name = "hop-count", .has_arg = required_argument, .val = 'c' },
        { .name = "priority",  .has_arg = required_argument, .val = 'p' },
        { .name = "verbose",   .has_arg = no_argument,       .val = 'v' },
-       { .name = "help",      .has_arg = no_argument,       .val = 'h' },
        { .name = NULL } };
 
+       rc = check_cmd(route_cmds, "route", "show", 0, argc, argv);
+       if (rc)
+               return rc;
+
        while ((opt = getopt_long(argc, argv, short_options,
                                   long_options, NULL)) != -1) {
                switch (opt) {
@@ -778,9 +837,6 @@ static int jt_show_route(int argc, char **argv)
                case 'v':
                        detail = 1;
                        break;
-               case 'h':
-                       print_help(route_cmds, "route", "show");
-                       return 0;
                default:
                        return 0;
                }
@@ -807,13 +863,16 @@ static int jt_show_net(int argc, char **argv)
        struct cYAML *err_rc = NULL, *show_rc = NULL;
        long int detail = 0;
 
-       const char *const short_options = "n:vh";
+       const char *const short_options = "n:v";
        static const struct option long_options[] = {
                { .name = "net",     .has_arg = required_argument, .val = 'n' },
                { .name = "verbose", .has_arg = optional_argument, .val = 'v' },
-               { .name = "help",    .has_arg = no_argument,       .val = 'h' },
                { .name = NULL } };
 
+       rc = check_cmd(net_cmds, "net", "show", 0, argc, argv);
+       if (rc)
+               return rc;
+
        while ((opt = getopt_long(argc, argv, short_options,
                                   long_options, NULL)) != -1) {
                switch (opt) {
@@ -829,9 +888,6 @@ static int jt_show_net(int argc, char **argv)
                                detail = 1;
                        }
                        break;
-               case 'h':
-                       print_help(net_cmds, "net", "show");
-                       return 0;
                default:
                        return 0;
                }
@@ -855,8 +911,9 @@ static int jt_show_routing(int argc, char **argv)
        struct cYAML *err_rc = NULL, *show_rc = NULL;
        int rc;
 
-       if (handle_help(routing_cmds, "routing", "show", argc, argv) == 0)
-               return 0;
+       rc = check_cmd(routing_cmds, "routing", "show", 0, argc, argv);
+       if (rc)
+               return rc;
 
        rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc);
 
@@ -876,8 +933,9 @@ static int jt_show_stats(int argc, char **argv)
        int rc;
        struct cYAML *show_rc = NULL, *err_rc = NULL;
 
-       if (handle_help(stats_cmds, "stats", "show", argc, argv) == 0)
-               return 0;
+       rc = check_cmd(stats_cmds, "stats", "show", 0, argc, argv);
+       if (rc)
+               return rc;
 
        rc = lustre_lnet_show_stats(-1, &show_rc, &err_rc);
 
@@ -897,8 +955,9 @@ static int jt_show_global(int argc, char **argv)
        int rc;
        struct cYAML *show_rc = NULL, *err_rc = NULL;
 
-       if (handle_help(global_cmds, "global", "show", argc, argv) == 0)
-               return 0;
+       rc = check_cmd(global_cmds, "global", "show", 0, argc, argv);
+       if (rc)
+               return rc;
 
        rc = lustre_lnet_show_numa_range(-1, &show_rc, &err_rc);
        if (rc != LUSTRE_CFG_RC_NO_ERR) {
@@ -928,98 +987,90 @@ out:
        return rc;
 }
 
-static inline int jt_lnet(int argc, char **argv)
+static int jt_lnet(int argc, char **argv)
 {
-       if (argc < 2)
-               return CMD_HELP;
+       int rc;
 
-       if (argc == 2 &&
-           handle_help(lnet_cmds, "lnet", NULL, argc, argv) == 0)
-               return 0;
+       rc = check_cmd(lnet_cmds, "lnet", NULL, 2, argc, argv);
+       if (rc)
+               return rc;
 
        return Parser_execarg(argc - 1, &argv[1], lnet_cmds);
 }
 
-static inline int jt_route(int argc, char **argv)
+static int jt_route(int argc, char **argv)
 {
-       if (argc < 2)
-               return CMD_HELP;
+       int rc;
 
-       if (argc == 2 &&
-           handle_help(route_cmds, "route", NULL, argc, argv) == 0)
-               return 0;
+       rc = check_cmd(route_cmds, "route", NULL, 2, argc, argv);
+       if (rc)
+               return rc;
 
        return Parser_execarg(argc - 1, &argv[1], route_cmds);
 }
 
-static inline int jt_net(int argc, char **argv)
+static int jt_net(int argc, char **argv)
 {
-       if (argc < 2)
-               return CMD_HELP;
+       int rc;
 
-       if (argc == 2 &&
-           handle_help(net_cmds, "net", NULL, argc, argv) == 0)
-               return 0;
+       rc = check_cmd(net_cmds, "net", NULL, 2, argc, argv);
+       if (rc)
+               return rc;
 
        return Parser_execarg(argc - 1, &argv[1], net_cmds);
 }
 
-static inline int jt_routing(int argc, char **argv)
+static int jt_routing(int argc, char **argv)
 {
-       if (argc < 2)
-               return CMD_HELP;
+       int rc;
 
-       if (argc == 2 &&
-           handle_help(routing_cmds, "routing", NULL, argc, argv) == 0)
-               return 0;
+       rc = check_cmd(routing_cmds, "routing", NULL, 2, argc, argv);
+       if (rc)
+               return rc;
 
        return Parser_execarg(argc - 1, &argv[1], routing_cmds);
 }
 
-static inline int jt_stats(int argc, char **argv)
+static int jt_stats(int argc, char **argv)
 {
-       if (argc < 2)
-               return CMD_HELP;
+       int rc;
 
-       if (argc == 2 &&
-           handle_help(stats_cmds, "stats", NULL, argc, argv) == 0)
-               return 0;
+       rc = check_cmd(stats_cmds, "stats", NULL, 2, argc, argv);
+       if (rc)
+               return rc;
 
        return Parser_execarg(argc - 1, &argv[1], stats_cmds);
 }
 
-static inline int jt_global(int argc, char **argv)
+static int jt_global(int argc, char **argv)
 {
-       if (argc < 2)
-               return CMD_HELP;
+       int rc;
 
-       if (argc == 2 &&
-           handle_help(global_cmds, "global", NULL, argc, argv) == 0)
-               return 0;
+       rc = check_cmd(global_cmds, "global", NULL, 2, argc, argv);
+       if (rc)
+               return rc;
 
        return Parser_execarg(argc - 1, &argv[1], global_cmds);
 }
 
-static inline int jt_peers(int argc, char **argv)
+static int jt_peers(int argc, char **argv)
 {
-       if (argc < 2)
-               return CMD_HELP;
+       int rc;
 
-       if (argc == 2 &&
-           handle_help(peer_cmds, "peer", NULL, argc, argv) == 0)
-               return 0;
+       rc = check_cmd(peer_cmds, "peer", NULL, 2, argc, argv);
+       if (rc)
+               return rc;
 
        return Parser_execarg(argc - 1, &argv[1], peer_cmds);
 }
 
-static inline int jt_set(int argc, char **argv)
+static int jt_set(int argc, char **argv)
 {
-       if (argc < 2)
-               return CMD_HELP;
+       int rc;
 
-       if (argc == 2  &&
-           handle_help(set_cmds, "set", NULL, argc, argv) == 0)
-               return 0;
+       rc = check_cmd(set_cmds, "set", NULL, 2, argc, argv);
+       if (rc)
+               return rc;
 
        return Parser_execarg(argc - 1, &argv[1], set_cmds);
 }
@@ -1032,7 +1083,7 @@ static int jt_import(int argc, char **argv)
        int rc = 0, return_rc = 0, opt, opt_found = 0;
        char cmd = 'a';
 
-       const char *const short_options = "adsh";
+       const char *const short_options = "adseh";
        static const struct option long_options[] = {
                { .name = "add",  .has_arg = no_argument, .val = 'a' },
                { .name = "del",  .has_arg = no_argument, .val = 'd' },
@@ -1111,8 +1162,9 @@ static int jt_export(int argc, char **argv)
 {
        struct cYAML *show_rc = NULL;
        struct cYAML *err_rc = NULL;
-       int rc, opt;
+       int rc;
        FILE *f = NULL;
+       int opt;
 
        const char *const short_options = "h";
        static const struct option long_options[] = {
@@ -1123,8 +1175,7 @@ static int jt_export(int argc, char **argv)
                                   long_options, NULL)) != -1) {
                switch (opt) {
                case 'h':
-                       printf("export FILE\n"
-                              "export > FILE : export configuration\n"
+                       printf("export > FILE.yaml : export configuration\n"
                               "\t--help: display this help\n");
                        return 0;
                default:
@@ -1209,15 +1260,18 @@ static int jt_add_peer_nid(int argc, char **argv)
        int rc = LUSTRE_CFG_RC_NO_ERR, opt, i;
        bool non_mr = false;
 
-       const char *const short_options = "k:n:mh";
+       const char *const short_options = "k:n:m";
        const struct option long_options[] = {
                { "prim_nid", 1, NULL, 'k' },
                { "nid", 1, NULL, 'n' },
                { "non_mr", 0, NULL, 'm'},
-               { "help", 0, NULL, 'h' },
                { NULL, 0, NULL, 0 },
        };
 
+       rc = check_cmd(peer_cmds, "peer", "add", 2, argc, argv);
+       if (rc)
+               return rc;
+
        while ((opt = getopt_long(argc, argv, short_options,
                                  long_options, NULL)) != -1) {
                switch (opt) {
@@ -1235,9 +1289,6 @@ static int jt_add_peer_nid(int argc, char **argv)
                case 'm':
                        non_mr = true;
                        break;
-               case 'h':
-                       print_help(peer_cmds, "peer", "add");
-                       return 0;
                default:
                        return 0;
                }
@@ -1269,14 +1320,17 @@ static int jt_del_peer_nid(int argc, char **argv)
        struct cYAML *err_rc = NULL;
        int rc = LUSTRE_CFG_RC_NO_ERR, opt, i, size = 0;
 
-       const char *const short_options = "k:n:h";
+       const char *const short_options = "k:n:";
        const struct option long_options[] = {
                { "prim_nid", 1, NULL, 'k' },
                { "nid", 1, NULL, 'n' },
-               { "help", 0, NULL, 'h' },
                { NULL, 0, NULL, 0 },
        };
 
+       rc = check_cmd(peer_cmds, "peer", "del", 2, argc, argv);
+       if (rc)
+               return rc;
+
        while ((opt = getopt_long(argc, argv, short_options,
                                  long_options, NULL)) != -1) {
                switch (opt) {
@@ -1291,9 +1345,6 @@ static int jt_del_peer_nid(int argc, char **argv)
                        nids = nids2;
                        rc = LUSTRE_CFG_RC_OUT_OF_MEM;
                        break;
-               case 'h':
-                       print_help(peer_cmds, "peer", "show");
-                       return 0;
                default:
                        return 0;
                }
@@ -1331,6 +1382,10 @@ static int jt_show_peer(int argc, char **argv)
                { NULL, 0, NULL, 0 },
        };
 
+       rc = check_cmd(peer_cmds, "peer", "show", 1, argc, argv);
+       if (rc)
+               return rc;
+
        while ((opt = getopt_long(argc, argv, short_options,
                                  long_options, NULL)) != -1) {
                switch (opt) {
@@ -1346,9 +1401,6 @@ static int jt_show_peer(int argc, char **argv)
                                detail = 1;
                        }
                        break;
-               case 'h':
-                       print_help(peer_cmds, "peer", "show");
-                       return 0;
                default:
                        return 0;
                }
@@ -1369,25 +1421,12 @@ static int jt_show_peer(int argc, char **argv)
 
 static int jt_list_peer(int argc, char **argv)
 {
-       int rc, opt;
+       int rc;
        struct cYAML *err_rc = NULL, *list_rc = NULL;
 
-       const char *const short_options = "h";
-       const struct option long_options[] = {
-               { "help", 0, NULL, 'h' },
-               { NULL, 0, NULL, 0 },
-       };
-
-       while ((opt = getopt_long(argc, argv, short_options,
-                                 long_options, NULL)) != -1) {
-               switch (opt) {
-               case 'h':
-                       print_help(peer_cmds, "peer", "list");
-                       return 0;
-               default:
-                       return 0;
-               }
-       }
+       rc = check_cmd(peer_cmds, "peer", "list", 0, argc, argv);
+       if (rc)
+               return rc;
 
        rc = lustre_lnet_list_peer(-1, &list_rc, &err_rc);
 
@@ -1423,18 +1462,15 @@ static int jt_ping(int argc, char **argv)
                        timeout = 1000 * atol(optarg);
                        break;
                case 'h':
-                       printf("ping: <nid1> <nid2> .. <nidN> (e.g. 10.2.2.2@tcp)\n"
-                              "\t--timeout: timeout(secs)\n"
-                              "\t--help: display this help\n");
+                       printf("ping nid[,nid,...]\n"
+                              "\t --timeout: ping timeout\n"
+                              "\t --help: display this help\n");
                        return 0;
                default:
                        return 0;
                }
        }
 
-       if (argc < 2)
-               return CMD_HELP;
-
        for (; optind < argc; optind++)
                rc = lustre_lnet_ping_nid(argv[optind], timeout, -1, &show_rc, &err_rc);
 
@@ -1471,18 +1507,15 @@ static int jt_discover(int argc, char **argv)
                        force = 1;
                        break;
                case 'h':
-                       printf("discover: nid1 nid2 .. nidN (e.g. 10.2.2.2@tcp)\n"
-                              "\t--force\n"
-                              "\t--help: display this help\n");
+                       printf("discover nid[,nid,...]\n"
+                              "\t --force: force discovery\n"
+                              "\t --help: display this help\n");
                        return 0;
                default:
                        return 0;
                }
        }
 
-       if (argc < 2)
-               return CMD_HELP;
-
        for (; optind < argc; optind++)
                rc = lustre_lnet_discover_nid(argv[optind], force, -1, &show_rc,
                                              &err_rc);
@@ -1499,34 +1532,11 @@ static int jt_discover(int argc, char **argv)
        return rc;
 }
 
-command_t list[] = {
-       {"lnet", jt_lnet, 0, "lnet {configure | unconfigure} [--all]"},
-       {"route", jt_route, 0, "route {add | del | show | help}"},
-       {"net", jt_net, 0, "net {add | del | show | help}"},
-       {"routing", jt_routing, 0, "routing {show | help}"},
-       {"set", jt_set, 0, "set {tiny_buffers | small_buffers | large_buffers"
-                          " | routing | numa_range | max_interfaces"
-                          " | discovery}"},
-       {"import", jt_import, 0, "import {--add | --del | --show | "
-                                "--exec | --help} FILE.yaml"},
-       {"export", jt_export, 0, "export {--help} FILE.yaml"},
-       {"stats", jt_stats, 0, "stats {show | help}"},
-       {"global", jt_global, 0, "global {show | help}"},
-       {"peer", jt_peers, 0, "peer {add | del | show | help}"},
-       {"ping", jt_ping, 0, "ping {--help}"},
-       {"discover", jt_discover, 0, "discover {--help}"},
-       {"help", Parser_help, 0, "help"},
-       {"exit", Parser_quit, 0, "quit"},
-       {"quit", Parser_quit, 0, "quit"},
-       {"--list-commands", lnetctl_list_commands, 0, "list commands"},
-       { 0, 0, 0, NULL }
-};
-
 static int lnetctl_list_commands(int argc, char **argv)
 {
        char buffer[81] = ""; /* 80 printable chars + terminating NUL */
 
-       Parser_list_commands(list, buffer, sizeof(buffer), NULL, 0, 4);
+       Parser_list_commands(cmd_list, buffer, sizeof(buffer), NULL, 0, 4);
 
        return 0;
 }
@@ -1544,9 +1554,9 @@ int main(int argc, char **argv)
                return rc;
        }
 
-       Parser_init("lnetctl > ", list);
+       Parser_init("lnetctl > ", cmd_list);
        if (argc > 1) {
-               rc = Parser_execarg(argc - 1, &argv[1], list);
+               rc = Parser_execarg(argc - 1, &argv[1], cmd_list);
                goto errorout;
        }