From: Olaf Weber Date: Thu, 6 Apr 2017 09:43:20 +0000 (+0200) Subject: LU-9480 lnet: add "lnetctl ping" command X-Git-Tag: 2.10.53~72^2~5 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=refs%2Fchanges%2F91%2F25791%2F31;p=fs%2Flustre-release.git LU-9480 lnet: add "lnetctl ping" command Adds function jt_ping() in lnetctl.c and lustre_lnet_ping_nid() in liblnetconfig.c file. The output of "lnetctl ping" is similar to "lnetctl peer show". Function jt_ping() in lnetctl.c calls lustre_lnet_ping_nid() to implement "lnetctl ping". Adds a function infra_ping_nid() to be later reused for the ping similar lnetctl commands. Uses a new ioctl call, IOC_LIBCFS_PING_PEER for "lnetctl ping". With "lnetctl ping", multiple nids can be pinged. Uses a new struct(lnet_ioctl_ping_data in lib-dlc.h) to pass the data from kernel to user space for ping. Also changes lnet_ping() function and its input parameters in lnet/lnet/api-ni.c Test-Parameters: trivial Signed-off-by: Sonia Sharma Signed-off-by: Olaf Weber Change-Id: I67024d87fa5cca6aa7ff7a8099d4400a795f3a83 Reviewed-on: https://review.whamcloud.com/25791 Reviewed-by: Amir Shehata Tested-by: Amir Shehata --- diff --git a/lnet/include/lnet/lib-lnet.h b/lnet/include/lnet/lib-lnet.h index 4f04751..7159bd5 100644 --- a/lnet/include/lnet/lib-lnet.h +++ b/lnet/include/lnet/lib-lnet.h @@ -73,8 +73,8 @@ extern struct lnet the_lnet; /* THE network */ /** exclusive lock */ #define LNET_LOCK_EX CFS_PERCPT_LOCK_EX -/* Discovery timeout - same as default peer_timeout */ -#define DISCOVERY_TIMEOUT 180 +/* default timeout */ +#define DEFAULT_PEER_TIMEOUT 180 static inline int lnet_is_route_alive(struct lnet_route *route) { @@ -871,6 +871,7 @@ struct lnet_peer_ni *lnet_nid2peerni_locked(lnet_nid_t nid, lnet_nid_t pref, int cpt); struct lnet_peer_ni *lnet_nid2peerni_ex(lnet_nid_t nid, int cpt); struct lnet_peer_ni *lnet_find_peer_ni_locked(lnet_nid_t nid); +struct lnet_peer *lnet_find_peer(lnet_nid_t nid); void lnet_peer_net_added(struct lnet_net *net); lnet_nid_t lnet_peer_primary_nid_locked(lnet_nid_t nid); int lnet_discover_peer_locked(struct lnet_peer_ni *lpni, int cpt, bool block); diff --git a/lnet/include/uapi/linux/lnet/libcfs_ioctl.h b/lnet/include/uapi/linux/lnet/libcfs_ioctl.h index 95b080d..fd24a9a 100644 --- a/lnet/include/uapi/linux/lnet/libcfs_ioctl.h +++ b/lnet/include/uapi/linux/lnet/libcfs_ioctl.h @@ -102,7 +102,7 @@ struct libcfs_debug_ioctl_data { #define IOC_LIBCFS_CONFIGURE _IOWR('e', 59, IOCTL_LIBCFS_TYPE) #define IOC_LIBCFS_TESTPROTOCOMPAT _IOWR('e', 60, IOCTL_LIBCFS_TYPE) #define IOC_LIBCFS_PING _IOWR('e', 61, IOCTL_LIBCFS_TYPE) -/* IOC_LIBCFS_DEBUG_PEER _IOWR('e', 62, IOCTL_LIBCFS_TYPE) */ +#define IOC_LIBCFS_PING_PEER _IOWR('e', 62, IOCTL_LIBCFS_TYPE) #define IOC_LIBCFS_LNETST _IOWR('e', 63, IOCTL_LIBCFS_TYPE) #define IOC_LIBCFS_LNET_FAULT _IOWR('e', 64, IOCTL_LIBCFS_TYPE) /* lnd ioctls */ diff --git a/lnet/klnds/o2iblnd/o2iblnd_modparams.c b/lnet/klnds/o2iblnd/o2iblnd_modparams.c index 72cb50e..e5a4b98 100644 --- a/lnet/klnds/o2iblnd/o2iblnd_modparams.c +++ b/lnet/klnds/o2iblnd/o2iblnd_modparams.c @@ -82,7 +82,7 @@ static int peer_buffer_credits = 0; module_param(peer_buffer_credits, int, 0444); MODULE_PARM_DESC(peer_buffer_credits, "# per-peer router buffer credits"); -static int peer_timeout = 180; +static int peer_timeout = DEFAULT_PEER_TIMEOUT; module_param(peer_timeout, int, 0444); MODULE_PARM_DESC(peer_timeout, "Seconds without aliveness news to declare peer dead (<=0 to disable)"); diff --git a/lnet/klnds/socklnd/socklnd_modparams.c b/lnet/klnds/socklnd/socklnd_modparams.c index 49bf88c..df9d96e 100644 --- a/lnet/klnds/socklnd/socklnd_modparams.c +++ b/lnet/klnds/socklnd/socklnd_modparams.c @@ -37,7 +37,7 @@ static int peer_buffer_credits; module_param(peer_buffer_credits, int, 0444); MODULE_PARM_DESC(peer_buffer_credits, "# per-peer router buffer credits"); -static int peer_timeout = 180; +static int peer_timeout = DEFAULT_PEER_TIMEOUT; module_param(peer_timeout, int, 0444); MODULE_PARM_DESC(peer_timeout, "Seconds without aliveness news to declare peer dead (<=0 to disable)"); diff --git a/lnet/lnet/api-ni.c b/lnet/lnet/api-ni.c index 16d95173a..c1a3398 100644 --- a/lnet/lnet/api-ni.c +++ b/lnet/lnet/api-ni.c @@ -3250,24 +3250,50 @@ LNetCtl(unsigned int cmd, void *arg) id.nid = data->ioc_nid; id.pid = data->ioc_u32[0]; - /* Don't block longer than 2 minutes */ - if (data->ioc_u32[1] > 120 * MSEC_PER_SEC) - return -EINVAL; - - /* If timestamp is negative then disable timeout */ - if ((s32)data->ioc_u32[1] < 0) - timeout = MAX_SCHEDULE_TIMEOUT; + /* If timeout is negative then set default of 3 minutes */ + if (((s32)data->ioc_u32[1] <= 0) || + data->ioc_u32[1] > (DEFAULT_PEER_TIMEOUT * MSEC_PER_SEC)) + timeout = msecs_to_jiffies(DEFAULT_PEER_TIMEOUT * MSEC_PER_SEC); else timeout = msecs_to_jiffies(data->ioc_u32[1]); rc = lnet_ping(id, timeout, data->ioc_pbuf1, data->ioc_plen1 / sizeof(struct lnet_process_id)); + if (rc < 0) return rc; + data->ioc_count = rc; return 0; } + case IOC_LIBCFS_PING_PEER: { + struct lnet_ioctl_ping_data *ping = arg; + struct lnet_peer *lp; + signed long timeout; + + /* If timeout is negative then set default of 3 minutes */ + if (((s32)ping->op_param) <= 0 || + ping->op_param > (DEFAULT_PEER_TIMEOUT * MSEC_PER_SEC)) + timeout = msecs_to_jiffies(DEFAULT_PEER_TIMEOUT * MSEC_PER_SEC); + else + timeout = msecs_to_jiffies(ping->op_param); + + rc = lnet_ping(ping->ping_id, timeout, + ping->ping_buf, + ping->ping_count); + if (rc < 0) + return rc; + + lp = lnet_find_peer(ping->ping_id.nid); + if (lp) { + ping->ping_id.nid = lp->lp_primary_nid; + ping->mr_info = lnet_peer_is_multi_rail(lp); + } + ping->ping_count = rc; + return 0; + } + default: ni = lnet_net2ni_addref(data->ioc_net); if (ni == NULL) @@ -3400,7 +3426,7 @@ static int lnet_ping(struct lnet_process_id id, signed long timeout, /* initialize md content */ md.start = &pbuf->pb_info; md.length = LNET_PING_INFO_SIZE(n_ids); - md.threshold = 2; /*GET/REPLY*/ + md.threshold = 2; /* GET/REPLY */ md.max_size = 0; md.options = LNET_MD_TRUNCATE; md.user_ptr = NULL; @@ -3418,7 +3444,6 @@ static int lnet_ping(struct lnet_process_id id, signed long timeout, if (rc != 0) { /* Don't CERROR; this could be deliberate! */ - rc2 = LNetMDUnlink(mdh); LASSERT(rc2 == 0); @@ -3466,7 +3491,6 @@ static int lnet_ping(struct lnet_process_id id, signed long timeout, replied = 1; rc = event.mlength; } - } while (rc2 <= 0 || !event.unlinked); if (!replied) { @@ -3480,10 +3504,9 @@ static int lnet_ping(struct lnet_process_id id, signed long timeout, nob = rc; LASSERT(nob >= 0 && nob <= LNET_PING_INFO_SIZE(n_ids)); - rc = -EPROTO; /* if I can't parse... */ + rc = -EPROTO; /* if I can't parse... */ if (nob < 8) { - /* can't check magic/version */ CERROR("%s: ping info too short %d\n", libcfs_id2str(id), nob); goto fail_free_eq; @@ -3504,7 +3527,8 @@ static int lnet_ping(struct lnet_process_id id, signed long timeout, } if (nob < LNET_PING_INFO_SIZE(0)) { - CERROR("%s: Short reply %d(%d min)\n", libcfs_id2str(id), + CERROR("%s: Short reply %d(%d min)\n", + libcfs_id2str(id), nob, (int)LNET_PING_INFO_SIZE(0)); goto fail_free_eq; } @@ -3513,12 +3537,13 @@ static int lnet_ping(struct lnet_process_id id, signed long timeout, n_ids = pbuf->pb_info.pi_nnis; if (nob < LNET_PING_INFO_SIZE(n_ids)) { - CERROR("%s: Short reply %d(%d expected)\n", libcfs_id2str(id), + CERROR("%s: Short reply %d(%d expected)\n", + libcfs_id2str(id), nob, (int)LNET_PING_INFO_SIZE(n_ids)); goto fail_free_eq; } - rc = -EFAULT; /* If I SEGV... */ + rc = -EFAULT; /* if I segv in copy_to_user()... */ memset(&tmpid, 0, sizeof(tmpid)); for (i = 0; i < n_ids; i++) { diff --git a/lnet/lnet/peer.c b/lnet/lnet/peer.c index 2af27a1..0a626fb 100644 --- a/lnet/lnet/peer.c +++ b/lnet/lnet/peer.c @@ -2907,7 +2907,7 @@ static struct lnet_peer *lnet_peer_dc_timed_out(time64_t now) return NULL; lp = list_first_entry(&the_lnet.ln_dc_working, struct lnet_peer, lp_dc_list); - if (now < lp->lp_last_queued + DISCOVERY_TIMEOUT) + if (now < lp->lp_last_queued + DEFAULT_PEER_TIMEOUT) return NULL; return lp; } diff --git a/lnet/utils/lnetconfig/liblnetconfig.c b/lnet/utils/lnetconfig/liblnetconfig.c index bb35de5..bee4a29 100644 --- a/lnet/utils/lnetconfig/liblnetconfig.c +++ b/lnet/utils/lnetconfig/liblnetconfig.c @@ -59,6 +59,7 @@ #define DEL_CMD "del" #define SHOW_CMD "show" #define DBG_CMD "dbg" +#define MANAGE_CMD "manage" #define modparam_path "/sys/module/lnet/parameters/" @@ -486,6 +487,188 @@ static int dispatch_peer_ni_cmd(lnet_nid_t pnid, lnet_nid_t nid, __u32 cmd, return rc; } +static int infra_ping_nid(char *ping_nids, char *oper, int param, int ioc_call, + int seq_no, struct cYAML **show_rc, + struct cYAML **err_rc) +{ + void *data = NULL; + struct lnet_ioctl_ping_data ping; + struct cYAML *root = NULL, *ping_node = NULL, *item = NULL, + *first_seq = NULL, *tmp = NULL, *peer_ni = NULL; + lnet_process_id_t id; + char err_str[LNET_MAX_STR_LEN] = {0}; + char *sep, *token, *end; + char buf[6]; + size_t len; + int rc = LUSTRE_CFG_RC_OUT_OF_MEM; + int i; + bool flag = false; + + len = (sizeof(lnet_process_id_t) * LNET_INTERFACES_MAX_DEFAULT); + + data = calloc(1, len); + if (data == NULL) + goto out; + + /* create struct cYAML root object */ + root = cYAML_create_object(NULL, NULL); + if (root == NULL) + goto out; + + ping_node = cYAML_create_seq(root, oper); + if (ping_node == NULL) + goto out; + + /* tokenise each nid in string ping_nids */ + token = strtok(ping_nids, ","); + + do { + item = cYAML_create_seq_item(ping_node); + if (item == NULL) + goto out; + + if (first_seq == NULL) + first_seq = item; + + /* check if '-' is a part of NID, token */ + sep = strchr(token, '-'); + if (sep == NULL) { + id.pid = LNET_PID_ANY; + /* if no net is specified, libcfs_str2nid() will assume tcp */ + id.nid = libcfs_str2nid(token); + if (id.nid == LNET_NID_ANY) { + snprintf(err_str, sizeof(err_str), + "\"cannot parse NID '%s'\"", + token); + rc = LUSTRE_CFG_RC_BAD_PARAM; + cYAML_build_error(rc, seq_no, MANAGE_CMD, + oper, err_str, err_rc); + continue; + } + } else { + if (token[0] == 'u' || token[0] == 'U') + id.pid = (strtoul(&token[1], &end, 0) | + (LNET_PID_USERFLAG)); + else + id.pid = strtoul(token, &end, 0); + + /* assuming '-' is part of hostname */ + if (end != sep) { + id.pid = LNET_PID_ANY; + id.nid = libcfs_str2nid(token); + if (id.nid == LNET_NID_ANY) { + snprintf(err_str, sizeof(err_str), + "\"cannot parse NID '%s'\"", + token); + rc = LUSTRE_CFG_RC_BAD_PARAM; + cYAML_build_error(rc, seq_no, MANAGE_CMD, + oper, err_str, + err_rc); + continue; + } + } else { + id.nid = libcfs_str2nid(sep + 1); + if (id.nid == LNET_NID_ANY) { + snprintf(err_str, sizeof(err_str), + "\"cannot parse NID '%s'\"", + token); + rc = LUSTRE_CFG_RC_BAD_PARAM; + cYAML_build_error(rc, seq_no, MANAGE_CMD, + oper, err_str, + err_rc); + continue; + } + } + } + LIBCFS_IOC_INIT_V2(ping, ping_hdr); + ping.ping_hdr.ioc_len = sizeof(ping); + ping.ping_id = id; + ping.op_param = param; + ping.ping_count = LNET_INTERFACES_MAX_DEFAULT; + ping.ping_buf = data; + + rc = l_ioctl(LNET_DEV_ID, ioc_call, &ping); + if (rc != 0) { + snprintf(err_str, + sizeof(err_str), "failed to %s %s: %s\n", oper, + id.pid == LNET_PID_ANY ? + libcfs_nid2str(id.nid) : + libcfs_id2str(id), strerror(errno)); + rc = LUSTRE_CFG_RC_BAD_PARAM; + cYAML_build_error(rc, seq_no, MANAGE_CMD, + oper, err_str, err_rc); + continue; + } + + if (cYAML_create_string(item, "primary nid", + libcfs_nid2str(ping.ping_id.nid)) == NULL) + goto out; + + if (cYAML_create_string(item, "Multi-Rail", ping.mr_info ? "True" : + "False") == NULL) + goto out; + + tmp = cYAML_create_seq(item, "peer ni"); + if (tmp == NULL) + goto out; + + for (i = 0; i < ping.ping_count; i++) { + if (!strcmp(libcfs_nid2str(ping.ping_buf[i].nid), + "0@lo")) + continue; + peer_ni = cYAML_create_seq_item(tmp); + if (peer_ni == NULL) + goto out; + memset(buf, 0, sizeof buf); + snprintf(buf, sizeof buf, "nid"); + if (cYAML_create_string(peer_ni, buf, + libcfs_nid2str(ping.ping_buf[i].nid)) == NULL) + goto out; + } + + flag = true; + + } while ((token = strtok(NULL, ",")) != NULL); + + if (flag) + rc = LUSTRE_CFG_RC_NO_ERR; + +out: + if (data) + free(data); + if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR) { + cYAML_free_tree(root); + } else if (show_rc != NULL && *show_rc != NULL) { + struct cYAML *show_node; + show_node = cYAML_get_object_item(*show_rc, oper); + if (show_node != NULL && cYAML_is_sequence(show_node)) { + cYAML_insert_child(show_node, first_seq); + free(ping_node); + free(root); + } else if (show_node == NULL) { + cYAML_insert_sibling((*show_rc)->cy_child, + ping_node); + free(root); + } else { + cYAML_free_tree(root); + } + } else { + *show_rc = root; + } + + return rc; +} + +int lustre_lnet_ping_nid(char *ping_nids, int timeout, int seq_no, + struct cYAML **show_rc, struct cYAML **err_rc) +{ + int rc; + + rc = infra_ping_nid(ping_nids, "ping", timeout, IOC_LIBCFS_PING_PEER, + seq_no, show_rc, err_rc); + return rc; +} + int lustre_lnet_config_peer_nid(char *pnid, char **nid, int num_nids, bool mr, int seq_no, struct cYAML **err_rc) { @@ -3501,6 +3684,26 @@ static int handle_yaml_show_global_settings(struct cYAML *tree, return rc; } +static int handle_yaml_ping(struct cYAML *tree, struct cYAML **show_rc, + struct cYAML **err_rc) +{ + struct cYAML *seq_no, *nid, *timeout; + + seq_no = cYAML_get_object_item(tree, "seq_no"); + nid = cYAML_get_object_item(tree, "primary nid"); + timeout = cYAML_get_object_item(tree, "timeout"); + + return lustre_lnet_ping_nid((nid) ? nid->cy_valuestring : NULL, + (timeout) ? timeout->cy_valueint : 1000, + (seq_no) ? seq_no->cy_valueint : -1, + show_rc, err_rc); +} + +static int handle_yaml_no_op() +{ + return LUSTRE_CFG_RC_NO_ERR; +} + struct lookup_cmd_hdlr_tbl { char *name; cmd_handler_t cb; @@ -3513,25 +3716,45 @@ static struct lookup_cmd_hdlr_tbl lookup_config_tbl[] = { { .name = "peer", .cb = handle_yaml_config_peer }, { .name = "routing", .cb = handle_yaml_config_routing }, { .name = "buffers", .cb = handle_yaml_config_buffers }, + { .name = "statistics", .cb = handle_yaml_no_op }, { .name = "global", .cb = handle_yaml_config_global_settings}, + { .name = "ping", .cb = handle_yaml_no_op }, { .name = NULL } }; static struct lookup_cmd_hdlr_tbl lookup_del_tbl[] = { { .name = "route", .cb = handle_yaml_del_route }, { .name = "net", .cb = handle_yaml_del_ni }, + { .name = "ip2nets", .cb = handle_yaml_no_op }, { .name = "peer", .cb = handle_yaml_del_peer }, { .name = "routing", .cb = handle_yaml_del_routing }, + { .name = "buffers", .cb = handle_yaml_no_op }, + { .name = "statistics", .cb = handle_yaml_no_op }, { .name = "global", .cb = handle_yaml_del_global_settings}, + { .name = "ping", .cb = handle_yaml_no_op }, { .name = NULL } }; static struct lookup_cmd_hdlr_tbl lookup_show_tbl[] = { { .name = "route", .cb = handle_yaml_show_route }, { .name = "net", .cb = handle_yaml_show_net }, - { .name = "buffers", .cb = handle_yaml_show_routing }, - { .name = "routing", .cb = handle_yaml_show_routing }, { .name = "peer", .cb = handle_yaml_show_peers }, + { .name = "ip2nets", .cb = handle_yaml_no_op }, + { .name = "routing", .cb = handle_yaml_show_routing }, + { .name = "buffers", .cb = handle_yaml_show_routing }, { .name = "statistics", .cb = handle_yaml_show_stats }, { .name = "global", .cb = handle_yaml_show_global_settings}, + { .name = "ping", .cb = handle_yaml_no_op }, + { .name = NULL } }; + +static struct lookup_cmd_hdlr_tbl lookup_exec_tbl[] = { + { .name = "route", .cb = handle_yaml_no_op }, + { .name = "net", .cb = handle_yaml_no_op }, + { .name = "peer", .cb = handle_yaml_no_op }, + { .name = "ip2nets", .cb = handle_yaml_no_op }, + { .name = "routing", .cb = handle_yaml_no_op }, + { .name = "buffers", .cb = handle_yaml_no_op }, + { .name = "statistics", .cb = handle_yaml_no_op }, + { .name = "global", .cb = handle_yaml_no_op }, + { .name = "ping", .cb = handle_yaml_ping }, { .name = NULL } }; static cmd_handler_t lookup_fn(char *key, @@ -3613,3 +3836,8 @@ int lustre_yaml_show(char *f, struct cYAML **show_rc, struct cYAML **err_rc) show_rc, err_rc); } +int lustre_yaml_exec(char *f, struct cYAML **show_rc, struct cYAML **err_rc) +{ + return lustre_yaml_cb_helper(f, lookup_exec_tbl, + show_rc, err_rc); +} diff --git a/lnet/utils/lnetconfig/liblnetconfig.h b/lnet/utils/lnetconfig/liblnetconfig.h index 68758d6..3909f3b 100644 --- a/lnet/utils/lnetconfig/liblnetconfig.h +++ b/lnet/utils/lnetconfig/liblnetconfig.h @@ -368,6 +368,19 @@ int lustre_lnet_show_peer(char *knid, int detail, int seq_no, int lustre_lnet_list_peer(int seq_no, struct cYAML **show_rc, struct cYAML **err_rc); +/* lustre_lnet_ping_nid + * Ping the nid list, pnids. + * + * pnids - NID list to ping. + * timeout - timeout(seconds) for ping. + * seq_no - sequence number of the command. + * show_rc - YAML structure of the resultant show. + * err_rc - YAML strucutre of the resultant return code. + * + */ +int lustre_lnet_ping_nid(char *pnid, int timeout, int seq_no, + struct cYAML **show_rc, struct cYAML **err_rc); + /* * lustre_yaml_config * Parses the provided YAML file and then calls the specific APIs @@ -401,6 +414,18 @@ int lustre_yaml_show(char *f, struct cYAML **show_rc, struct cYAML **err_rc); /* + * lustre_yaml_exec + * Parses the provided YAML file and then calls the specific APIs + * to execute the entities identified in the file + * + * f - YAML file + * show_rc - [OUT] The show output in YAML. Must be freed by caller. + * err_rc - [OUT] struct cYAML tree describing the error. Freed by caller + */ +int lustre_yaml_exec(char *f, struct cYAML **show_rc, + struct cYAML **err_rc); + +/* * lustre_lnet_init_nw_descr * initialize the network descriptor structure for use */ diff --git a/lnet/utils/lnetctl.c b/lnet/utils/lnetctl.c index 6bc66a2..969faed 100644 --- a/lnet/utils/lnetctl.c +++ b/lnet/utils/lnetctl.c @@ -1020,7 +1020,7 @@ static int jt_import(int argc, char **argv) char *file = NULL; struct cYAML *err_rc = NULL; struct cYAML *show_rc = NULL; - int rc = 0, opt, opt_found = 0; + int rc = 0, return_rc = 0, opt, opt_found = 0; char cmd = 'a'; const char *const short_options = "adsh"; @@ -1028,6 +1028,7 @@ static int jt_import(int argc, char **argv) { .name = "add", .has_arg = no_argument, .val = 'a' }, { .name = "del", .has_arg = no_argument, .val = 'd' }, { .name = "show", .has_arg = no_argument, .val = 's' }, + { .name = "exec", .has_arg = no_argument, .val = 'e' }, { .name = "help", .has_arg = no_argument, .val = 'h' }, { .name = NULL } }; @@ -1036,16 +1037,22 @@ static int jt_import(int argc, char **argv) opt_found = 1; switch (opt) { case 'a': + cmd = opt; + break; case 'd': case 's': cmd = opt; break; + case 'e': + cmd = opt; + break; case 'h': printf("import FILE\n" "import < FILE : import a file\n" "\t--add: add configuration\n" "\t--del: delete configuration\n" "\t--show: show configuration\n" + "\t--exec: execute command\n" "\t--help: display this help\n" "If no command option is given then --add" " is assumed by default\n"); @@ -1064,6 +1071,9 @@ static int jt_import(int argc, char **argv) switch (cmd) { case 'a': rc = lustre_yaml_config(file, &err_rc); + return_rc = lustre_yaml_exec(file, &show_rc, &err_rc); + cYAML_print_tree(show_rc); + cYAML_free_tree(show_rc); break; case 'd': rc = lustre_yaml_del(file, &err_rc); @@ -1073,11 +1083,17 @@ static int jt_import(int argc, char **argv) cYAML_print_tree(show_rc); cYAML_free_tree(show_rc); break; + case 'e': + rc = lustre_yaml_exec(file, &show_rc, &err_rc); + cYAML_print_tree(show_rc); + cYAML_free_tree(show_rc); + break; } - cYAML_print_tree2file(stderr, err_rc); - - cYAML_free_tree(err_rc); + if (rc || return_rc) { + cYAML_print_tree2file(stderr, err_rc); + cYAML_free_tree(err_rc); + } return rc; } @@ -1358,6 +1374,54 @@ static int jt_list_peer(int argc, char **argv) return rc; } +static int jt_ping(int argc, char **argv) +{ + struct cYAML *err_rc = NULL; + struct cYAML *show_rc = NULL; + int timeout = 1000; + int rc = 0, opt; + + const char *const short_options = "t:h"; + const struct option long_options[] = { + { "timeout", 1, NULL, 't' }, + { "help", 0, NULL, 'h' }, + { NULL, 0, NULL, 0 }, + }; + + while ((opt = getopt_long(argc, argv, short_options, + long_options, NULL)) != -1) { + switch (opt) { + case 't': + timeout = 1000 * atol(optarg); + break; + case 'h': + printf("ping: .. (e.g. 10.2.2.2@tcp)\n" + "\t--timeout: timeout(secs)\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); + + if (show_rc) + cYAML_print_tree(show_rc); + + if (err_rc) + cYAML_print_tree2file(stderr, err_rc); + + cYAML_free_tree(err_rc); + cYAML_free_tree(show_rc); + + return rc; +} + command_t list[] = { {"lnet", jt_lnet, 0, "lnet {configure | unconfigure} [--all]"}, {"route", jt_route, 0, "route {add | del | show | help}"}, @@ -1367,11 +1431,12 @@ command_t list[] = { " | routing | numa_range | max_interfaces" " | discovery}"}, {"import", jt_import, 0, "import {--add | --del | --show | " - "--help} FILE.yaml"}, + "--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}"}, {"help", Parser_help, 0, "help"}, {"exit", Parser_quit, 0, "quit"}, {"quit", Parser_quit, 0, "quit"},