extern int lnet_get_peer_list(__u32 *countp, __u32 *sizep,
struct lnet_process_id __user *ids);
-extern void lnet_peer_ni_set_healthv(lnet_nid_t nid, int value, bool all);
+void lnet_peer_ni_set_healthv(struct lnet_nid *nid, int value, bool all);
extern void lnet_peer_ni_add_to_recoveryq_locked(struct lnet_peer_ni *lpni,
struct list_head *queue,
time64_t now);
case IOC_LIBCFS_SET_HEALHV: {
struct lnet_ioctl_reset_health_cfg *cfg = arg;
int value;
+
if (cfg->rh_hdr.ioc_len < sizeof(*cfg))
return -EINVAL;
if (cfg->rh_value < 0 ||
CDEBUG(D_NET, "Manually setting healthv to %d for %s:%s. all = %d\n",
value, (cfg->rh_type == LNET_HEALTH_TYPE_LOCAL_NI) ?
"local" : "peer", libcfs_nid2str(cfg->rh_nid), cfg->rh_all);
+ lnet_nid4_to_nid(cfg->rh_nid, &nid);
mutex_lock(&the_lnet.ln_api_mutex);
if (cfg->rh_type == LNET_HEALTH_TYPE_LOCAL_NI)
lnet_ni_set_healthv(cfg->rh_nid, value,
cfg->rh_all);
else
- lnet_peer_ni_set_healthv(cfg->rh_nid, value,
- cfg->rh_all);
+ lnet_peer_ni_set_healthv(&nid, value, cfg->rh_all);
mutex_unlock(&the_lnet.ln_api_mutex);
return 0;
}
return rc;
}
+/* Called with ln_api_mutex */
+static int lnet_parse_peer_nis(struct nlattr *rlist, struct lnet_nid *pnid,
+ bool mr, struct genl_info *info)
+{
+ struct lnet_nid snid = LNET_ANY_NID;
+ struct nlattr *props;
+ bool all = false;
+ int rem, rc = 0;
+ s64 num = -1;
+
+ nla_for_each_nested(props, rlist, rem) {
+ if (nla_type(props) != LN_SCALAR_ATTR_VALUE)
+ continue;
+
+ if (nla_strcmp(props, "nid") == 0) {
+ char nidstr[LNET_NIDSTR_SIZE];
+
+ props = nla_next(props, &rem);
+ if (nla_type(props) != LN_SCALAR_ATTR_VALUE) {
+ GENL_SET_ERR_MSG(info,
+ "invalid secondary NID");
+ GOTO(report_err, rc = -EINVAL);
+ }
+
+ rc = nla_strscpy(nidstr, props, sizeof(nidstr));
+ if (rc < 0) {
+ GENL_SET_ERR_MSG(info,
+ "failed to get secondary NID");
+ GOTO(report_err, rc);
+ }
+
+ rc = libcfs_strnid(&snid, strim(nidstr));
+ if (rc < 0) {
+ GENL_SET_ERR_MSG(info, "unsupported secondary NID");
+ GOTO(report_err, rc);
+ }
+
+ if (LNET_NID_IS_ANY(&snid))
+ all = true;
+ } else if (nla_strcmp(props, "health stats") == 0) {
+ struct nlattr *health;
+ int rem2;
+
+ props = nla_next(props, &rem);
+ if (nla_type(props) !=
+ LN_SCALAR_ATTR_LIST) {
+ GENL_SET_ERR_MSG(info,
+ "invalid health configuration");
+ GOTO(report_err, rc = -EINVAL);
+ }
+
+ nla_for_each_nested(health, props, rem2) {
+ if (nla_type(health) != LN_SCALAR_ATTR_VALUE ||
+ nla_strcmp(health, "health value") != 0) {
+ GENL_SET_ERR_MSG(info,
+ "wrong health config format");
+ GOTO(report_err, rc = -EINVAL);
+ }
+
+ health = nla_next(health, &rem2);
+ if (nla_type(health) !=
+ LN_SCALAR_ATTR_INT_VALUE) {
+ GENL_SET_ERR_MSG(info,
+ "invalid health config format");
+ GOTO(report_err, rc = -EINVAL);
+ }
+
+ num = nla_get_s64(health);
+ clamp_t(s64, num, 0, LNET_MAX_HEALTH_VALUE);
+ }
+ }
+ }
+
+ if (info->nlhdr->nlmsg_flags & NLM_F_REPLACE && num != -1) {
+ lnet_peer_ni_set_healthv(pnid, num, all);
+ } else if (info->nlhdr->nlmsg_flags & NLM_F_CREATE) {
+ bool lock_prim = info->nlhdr->nlmsg_flags & NLM_F_EXCL;
+
+ rc = lnet_user_add_peer_ni(pnid, &snid, mr, lock_prim);
+ if (rc < 0)
+ GENL_SET_ERR_MSG(info,
+ "failed to add peer");
+ } else if (!(info->nlhdr->nlmsg_flags & NLM_F_CREATE)) {
+ bool force = info->nlhdr->nlmsg_flags & NLM_F_EXCL;
+
+ rc = lnet_del_peer_ni(pnid, &snid, force);
+ if (rc < 0)
+ GENL_SET_ERR_MSG(info,
+ "failed to del peer");
+ }
+report_err:
+ return rc;
+}
+
+static int lnet_peer_ni_cmd(struct sk_buff *skb, struct genl_info *info)
+{
+ struct nlmsghdr *nlh = nlmsg_hdr(skb);
+ struct genlmsghdr *gnlh = nlmsg_data(nlh);
+ struct nlattr *params = genlmsg_data(gnlh);
+ int msg_len, rem, rc = 0;
+ struct nlattr *attr;
+
+ mutex_lock(&the_lnet.ln_api_mutex);
+ if (the_lnet.ln_state != LNET_STATE_RUNNING) {
+ GENL_SET_ERR_MSG(info, "Network is down");
+ mutex_unlock(&the_lnet.ln_api_mutex);
+ return -ENETDOWN;
+ }
+
+ msg_len = genlmsg_len(gnlh);
+ if (!msg_len) {
+ GENL_SET_ERR_MSG(info, "no configuration");
+ mutex_unlock(&the_lnet.ln_api_mutex);
+ return -ENOMSG;
+ }
+
+ if (!(nla_type(params) & LN_SCALAR_ATTR_LIST)) {
+ GENL_SET_ERR_MSG(info, "invalid configuration");
+ mutex_unlock(&the_lnet.ln_api_mutex);
+ return -EINVAL;
+ }
+
+ nla_for_each_nested(attr, params, rem) {
+ struct lnet_nid pnid = LNET_ANY_NID;
+ bool parse_peer_nis = false;
+ struct nlattr *pnid_prop;
+ int rem2;
+
+ if (nla_type(attr) != LN_SCALAR_ATTR_LIST)
+ continue;
+
+ nla_for_each_nested(pnid_prop, attr, rem2) {
+ bool mr = true;
+
+ if (nla_type(pnid_prop) != LN_SCALAR_ATTR_VALUE)
+ continue;
+
+ if (nla_strcmp(pnid_prop, "primary nid") == 0) {
+ char nidstr[LNET_NIDSTR_SIZE];
+
+ pnid_prop = nla_next(pnid_prop, &rem2);
+ if (nla_type(pnid_prop) !=
+ LN_SCALAR_ATTR_VALUE) {
+ GENL_SET_ERR_MSG(info,
+ "invalid primary NID type");
+ GOTO(report_err, rc = -EINVAL);
+ }
+
+ rc = nla_strscpy(nidstr, pnid_prop,
+ sizeof(nidstr));
+ if (rc < 0) {
+ GENL_SET_ERR_MSG(info,
+ "failed to get primary NID");
+ GOTO(report_err, rc);
+ }
+
+ rc = libcfs_strnid(&pnid, strim(nidstr));
+ if (rc < 0) {
+ GENL_SET_ERR_MSG(info,
+ "unsupported primary NID");
+ GOTO(report_err, rc);
+ }
+
+ /* we must create primary NID for peer ni
+ * creation
+ */
+ if (info->nlhdr->nlmsg_flags & NLM_F_CREATE) {
+ bool lock_prim;
+
+ lock_prim = info->nlhdr->nlmsg_flags & NLM_F_EXCL;
+ rc = lnet_user_add_peer_ni(&pnid,
+ &LNET_ANY_NID,
+ true, lock_prim);
+ if (rc < 0) {
+ GENL_SET_ERR_MSG(info,
+ "failed to add primary peer");
+ GOTO(report_err, rc);
+ }
+ }
+ } else if (nla_strcmp(pnid_prop, "Multi-Rail") == 0) {
+ pnid_prop = nla_next(pnid_prop, &rem2);
+ if (nla_type(pnid_prop) !=
+ LN_SCALAR_ATTR_INT_VALUE) {
+ GENL_SET_ERR_MSG(info,
+ "invalid MR flag param");
+ GOTO(report_err, rc = -EINVAL);
+ }
+
+ if (nla_get_s64(pnid_prop) == 0)
+ mr = false;
+ } else if (nla_strcmp(pnid_prop, "peer state") == 0) {
+ struct lnet_peer_ni *lpni;
+ struct lnet_peer *lp;
+
+ pnid_prop = nla_next(pnid_prop, &rem2);
+ if (nla_type(pnid_prop) !=
+ LN_SCALAR_ATTR_INT_VALUE) {
+ GENL_SET_ERR_MSG(info,
+ "invalid peer state param");
+ GOTO(report_err, rc = -EINVAL);
+ }
+
+ lpni = lnet_peer_ni_find_locked(&pnid);
+ if (!lpni) {
+ GENL_SET_ERR_MSG(info,
+ "invalid peer state param");
+ GOTO(report_err, rc = -ENOENT);
+ }
+ lnet_peer_ni_decref_locked(lpni);
+ lp = lpni->lpni_peer_net->lpn_peer;
+ lp->lp_state = nla_get_s64(pnid_prop);
+ } else if (nla_strcmp(pnid_prop, "peer ni") == 0) {
+ struct nlattr *rlist;
+ int rem3;
+
+ if (LNET_NID_IS_ANY(&pnid)) {
+ GENL_SET_ERR_MSG(info,
+ "missing required primary NID");
+ GOTO(report_err, rc);
+ }
+
+ pnid_prop = nla_next(pnid_prop, &rem2);
+ if (nla_type(pnid_prop) !=
+ LN_SCALAR_ATTR_LIST) {
+ GENL_SET_ERR_MSG(info,
+ "invalid NIDs list");
+ GOTO(report_err, rc = -EINVAL);
+ }
+
+ nla_for_each_nested(rlist, pnid_prop, rem3) {
+ rc = lnet_parse_peer_nis(rlist, &pnid,
+ mr, info);
+ if (rc < 0)
+ GOTO(report_err, rc);
+ }
+ parse_peer_nis = true;
+ }
+ }
+
+ /* If we have remote peer ni's we already add /del peers */
+ if (parse_peer_nis)
+ continue;
+
+ if (LNET_NID_IS_ANY(&pnid)) {
+ GENL_SET_ERR_MSG(info, "missing primary NID");
+ GOTO(report_err, rc);
+ }
+
+ if (!(info->nlhdr->nlmsg_flags & NLM_F_CREATE)) {
+ bool force = info->nlhdr->nlmsg_flags & NLM_F_EXCL;
+
+ rc = lnet_del_peer_ni(&pnid, &LNET_ANY_NID,
+ force);
+ if (rc < 0) {
+ GENL_SET_ERR_MSG(info,
+ "failed to del peer");
+ GOTO(report_err, rc);
+ }
+ }
+ }
+report_err:
+ mutex_unlock(&the_lnet.ln_api_mutex);
+
+ return rc;
+}
+
/** LNet route handling */
/* We can't use struct lnet_ioctl_config_data since it lacks
},
{
.cmd = LNET_CMD_PEERS,
+ .flags = GENL_ADMIN_PERM,
#ifdef HAVE_NETLINK_CALLBACK_START
.start = lnet_peer_ni_show_start,
.dumpit = lnet_peer_ni_show_dump,
.dumpit = lnet_old_peer_ni_show_dump,
#endif
.done = lnet_peer_ni_show_done,
+ .doit = lnet_peer_ni_cmd,
},
{
.cmd = LNET_CMD_ROUTES,
if (nf == NULL)
return -EINVAL;
} else {
+ if (strcmp(str, "<?>") == 0) {
+ memcpy(nid, &LNET_ANY_NID, sizeof(*nid));
+ return 0;
+ }
sep = str + strlen(str);
net = LNET_MKNET(SOCKLND, 0);
nf = libcfs_lnd2netstrfns(SOCKLND);
/* Call with the ln_api_mutex held */
void
-lnet_peer_ni_set_healthv(lnet_nid_t nid4, int value, bool all)
+lnet_peer_ni_set_healthv(struct lnet_nid *nid, int value, bool all)
{
struct lnet_peer_table *ptable;
struct lnet_peer *lp;
struct lnet_peer_net *lpn;
struct lnet_peer_ni *lpni;
- struct lnet_nid nid;
int lncpt;
int cpt;
time64_t now;
if (the_lnet.ln_state != LNET_STATE_RUNNING)
return;
- lnet_nid4_to_nid(nid4, &nid);
now = ktime_get_seconds();
if (!all) {
lnet_net_lock(LNET_LOCK_EX);
- lpni = lnet_peer_ni_find_locked(&nid);
+ lpni = lnet_peer_ni_find_locked(nid);
if (!lpni) {
lnet_net_unlock(LNET_LOCK_EX);
return;
* 2. APIs that take a YAML file and parses out the information there and
* calls the APIs mentioned in 1
*/
-
+#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <byteswap.h>
return rc;
}
+void lustre_lnet_free_list(struct nid_node *head)
+{
+ struct nid_node *entry, *tmp;
+
+ nl_list_for_each_entry_safe(entry, tmp, &head->children, list) {
+ nl_list_del(&entry->list);
+ free(entry);
+ }
+}
+
+static int unroll_nid_range_scan(struct nid_node *list, const char *nid,
+ char *tmp, char *tmp2, char *nidstr,
+ const char **errmsg)
+{
+ unsigned int first = 0, last = 0, off = 0, inc = 1;
+ bool slash = false, hyphen = false;
+ char num[INT_STRING_LEN] = "";
+ char *range = tmp + 1;
+ int base = 10;
+ int rc;
+
+ if (!tmp && !tmp2) {
+ *errmsg = "Unable to parse nidlist: [] are missing";
+ return -ERANGE;
+ }
+
+ if ((tmp && !tmp2) || (!tmp && tmp2)) {
+ *errmsg = "Unable to parse nidlist: incomplete bracket set";
+ return -EINVAL;
+ }
+
+ if (range > tmp2) {
+ *errmsg = "Unable to parse nidlist: improper bracket ordering";
+ return -EINVAL;
+ }
+
+ if (strchr(nid, ':'))
+ base = 16;
+
+ while (range < tmp2) {
+ if (isxdigit(*range)) {
+ if (off > INT_STRING_LEN)
+ return -E2BIG;
+ num[off++] = *range++;
+ } else if (*range == ':') {
+ /* skip ':' for IPv6 and IB GUID */
+ range++;
+ } else if (*range == '-') {
+ range++;
+ if (!isxdigit(*range)) {
+ *errmsg = "Unable to parse nidlist: range needs number after -";
+ return -ERANGE;
+ }
+
+ first = strtoul(num, NULL, base);
+ memset(num, 0, sizeof(num));
+ hyphen = true;
+ off = 0;
+ } else if (*range == '/') {
+ range++;
+ if (!isdigit(*range)) {
+ *errmsg = "Unable to parse nidlist: range needs number after /";
+ return -ERANGE;
+ }
+
+ /* Don't lose last number. This should be the very last item */
+ if (strlen(num)) {
+ last = strtoul(num, NULL, base);
+ memset(num, 0, sizeof(num));
+ slash = true;
+ off = 0;
+ }
+ } else if (*range == ',') {
+ char *end = strchr(nidstr, ',');
+ int count = strlen(tmp2 + 1);
+ struct nid_node *item;
+ int len = tmp - nid;
+
+ range++;
+ if (!isxdigit(*range)) {
+ *errmsg = "Unable to parse nidlist: range needs number after ,";
+ return -ERANGE;
+ }
+
+ /* If hyphen is true then we have the foramt '[first - last],' format.
+ * The other format is just x, y, z, ... format.
+ */
+ if (hyphen) {
+ if (slash)
+ inc = strtoul(num, NULL, base);
+ else
+ last = strtoul(num, NULL, base);
+
+ if (first > last) {
+ *errmsg = "Unable to parse nidlist: range is wrong order";
+ return -ERANGE;
+ }
+
+ while (last >= first) {
+ char hdr[LNET_MAX_STR_LEN], *next;
+
+ snprintf(hdr, sizeof(hdr), "%.*s%d%.*s",
+ len, nid, first, count,
+ tmp2 + 1);
+ next = strchr(hdr, '[');
+ if (next && strchr(next, ']')) {
+ rc = unroll_nid_range_scan(list, hdr, next,
+ strchr(next, ']'),
+ nidstr, errmsg);
+ if (rc < 0)
+ return rc;
+ } else {
+ item = calloc(1, sizeof(struct nid_node));
+ if (!item) {
+ *errmsg = "Unable to parse nidlist: allocation failed";
+ return -ENOMEM;
+ }
+ snprintf(item->nidstr, sizeof(item->nidstr),
+ "%s@%s", hdr, nidstr);
+ nl_init_list_head(&item->list);
+ nl_list_add_tail(&item->list, &list->children);
+ }
+ first += inc;
+ }
+ /* reset slash / hyphen handing */
+ hyphen = false;
+ slash = false;
+ inc = 1;
+ } else {
+ int end_len = end ? end - nidstr : strlen(nidstr);
+
+ item = calloc(1, sizeof(struct nid_node));
+ if (!item) {
+ *errmsg = "Unable to parse nidlist: allocation failed";
+ return -ENOMEM;
+ }
+ snprintf(item->nidstr, sizeof(item->nidstr),
+ "%.*s%s%.*s@%.*s", len, nid, num,
+ count, tmp2 + 1, end_len, nidstr);
+ nl_init_list_head(&item->list);
+ nl_list_add_tail(&item->list, &list->children);
+ }
+
+ memset(num, 0, sizeof(num));
+ off = 0;
+ } else {
+ *errmsg = "Unable to parse nidlist: invalid character in range";
+ return -EINVAL;
+ }
+ }
+
+ if (strlen(num)) {
+ if (slash)
+ inc = strtoul(num, NULL, base);
+ else
+ last = strtoul(num, NULL, base);
+ memset(num, 0, sizeof(num));
+ }
+
+ if (!hyphen)
+ first = last;
+
+ /* This is the last set of [ first - last ]. We reach this point because
+ * the above loop reached the end of the range and no ',' was found so
+ * the final set of number range wasn't processed. Do that handling here.
+ */
+ if (first || last) {
+ char *next = tmp2 + 1;
+ int len = strlen(nid);
+
+ if (first > last) {
+ *errmsg = "Unable to parse nidlist: range is wrong order";
+ return -ERANGE;
+ }
+
+ if (strchr(nid, '['))
+ len = strchr(nid, '[') - nid;
+
+ tmp = strchr(tmp2, '[');
+ if (tmp)
+ tmp2 = strchr(tmp, ']');
+
+ while (last >= first) {
+ char str[LNET_MAX_STR_LEN];
+
+ snprintf(str, sizeof(str), "%.*s%u%.*s",
+ len, nid, first, (int)(tmp - next), next);
+ if (tmp && tmp2) {
+ rc = unroll_nid_range_scan(list, str, tmp, tmp2,
+ nidstr, errmsg);
+ if (rc < 0)
+ return rc;
+ } else {
+ char *end = strchr(nidstr, ',');
+ int count = end ? end - nidstr : strlen(nidstr);
+ struct nid_node *item;
+
+ item = calloc(1, sizeof(struct nid_node));
+ if (!item) {
+ *errmsg = "Unable to parse nidlist: allocation failed";
+ return -ENOMEM;
+ }
+ snprintf(item->nidstr, sizeof(item->nidstr),
+ "%s@%.*s", str, count, nidstr);
+ nl_init_list_head(&item->list);
+ nl_list_add_tail(&item->list, &list->children);
+ }
+ first += inc;
+ }
+ }
+
+ return 0;
+}
+
+int lustre_lnet_parse_nid_range(struct nid_node *head, char *nidstr,
+ const char **errmsg)
+{
+ int rc = 0;
+ char *nid;
+
+ if (!nidstr) {
+ *errmsg = "supplied nidstr is NULL";
+ return -EINVAL;
+ }
+
+ if (strchr(nidstr, '*')) {
+ *errmsg = "asterisk not allowed in nidstring";
+ return -EINVAL;
+ }
+
+ if (strstr(nidstr, "<?>")) {
+ *errmsg = "Unable to parse nidlist: LNET_ANY_NID is unsupported";
+ return -EINVAL;
+ }
+
+ if (strchr(nidstr, '@') == NULL) {
+ *errmsg = "Unable to parse nidlist: no valid NIDs in string";
+ return -EINVAL;
+ }
+
+ while ((nid = strsep(&nidstr, "@")) != NULL) {
+ char *tmp = NULL, *tmp2 = NULL, *end = NULL;
+
+ if (!nid) {
+ *errmsg = "Unable to parse nidlist: no proper NID string";
+ return -ENOENT;
+ }
+
+ tmp = strchr(nid, '[');
+ tmp2 = strchr(nid, ']');
+
+ if (!tmp && !tmp2) {
+ char *end = strchr(nidstr, ',');
+ struct nid_node *item;
+ int count;
+
+ item = calloc(1, sizeof(struct nid_node));
+ if (!item) {
+ *errmsg = "Unable to parse nidlist: allocation failed";
+ rc = -ENOMEM;
+ goto err;
+ }
+
+ count = end ? end - nidstr : strlen(nidstr);
+ snprintf(item->nidstr, sizeof(item->nidstr),
+ "%s@%.*s", nid, count, nidstr);
+ nl_init_list_head(&item->list);
+ nl_list_add_tail(&item->list, &head->children);
+ } else {
+ rc = unroll_nid_range_scan(head, nid, tmp, tmp2,
+ nidstr, errmsg);
+ if (rc < 0)
+ goto err;
+ }
+
+ if (nidstr) {
+ end = strchr(nidstr, ',');
+ if (end)
+ nidstr = end + 1;
+ else
+ nidstr = NULL;
+ }
+ }
+err:
+ return rc;
+}
+
static int
lustre_lnet_ioctl_config_ni(struct list_head *intf_list,
struct lnet_ioctl_config_lnd_tunables *tunables,
int lustre_yaml_exec(char *f, struct cYAML **show_rc,
struct cYAML **err_rc);
+struct nid_node {
+ char nidstr[LNET_MAX_STR_LEN * 2];
+ struct nl_list_head children;
+ struct nl_list_head list;
+};
+
+int lustre_lnet_parse_nid_range(struct nid_node *head, char *nidstr,
+ const char **errmsg);
+void lustre_lnet_free_list(struct nid_node *head);
+
/**
* yaml_emitter_set_output_netlink
*
if (!strlen(sep))
goto nla_put_failure;
- if (strspn(sep, "-0123456789") == strlen(sep)) {
+ if (strcasecmp(sep, "yes") == 0 ||
+ strcasecmp(sep, "true") == 0 ||
+ strcasecmp(sep, "on") == 0 ||
+ strcasecmp(sep, "y") == 0) {
+ NLA_PUT_S64(msg, LN_SCALAR_ATTR_INT_VALUE, 1);
+ } else if (strcasecmp(sep, "no") == 0 ||
+ strcasecmp(sep, "false") == 0 ||
+ strcasecmp(sep, "off") == 0 ||
+ strcasecmp(sep, "n") == 0) {
+ NLA_PUT_S64(msg, LN_SCALAR_ATTR_INT_VALUE, 0);
+ } else if (strspn(sep, "-0123456789") == strlen(sep)) {
num = strtoll(sep, NULL, 0);
NLA_PUT_S64(msg, LN_SCALAR_ATTR_INT_VALUE, num);
} else {
}
static int set_value_helper(int argc, char **argv,
- int (*cb)(int, bool, char*, int, struct cYAML**))
+ int (*cb)(int, bool, char*, int, int, struct cYAML**))
{
char *nid = NULL;
long int healthv = -1;
long int state = -1;
int rc, opt;
struct cYAML *err_rc = NULL;
-
const char *const short_options = "t:n:s:a";
static const struct option long_options[] = {
{ .name = "nid", .has_arg = required_argument, .val = 'n' },
{ .name = "health", .has_arg = required_argument, .val = 't' },
{ .name = "state", .has_arg = required_argument, .val = 's' },
{ .name = "all", .has_arg = no_argument, .val = 'a' },
- { .name = NULL } };
-
- rc = check_cmd(net_cmds, "net", "set", 0, argc, argv);
- if (rc)
- return rc;
+ { .name = NULL }
+ };
while ((opt = getopt_long(argc, argv, short_options,
- long_options, NULL)) != -1) {
+ long_options, NULL)) != -1) {
switch (opt) {
case 'n':
nid = optarg;
}
}
- if (state > -1)
- rc = lustre_lnet_set_peer_state(state, nid, -1, &err_rc);
- else
- rc = cb(healthv, all, nid, -1, &err_rc);
-
+ rc = cb(healthv, all, nid, state, -1, &err_rc);
if (rc != LUSTRE_CFG_RC_NO_ERR)
cYAML_print_tree2file(stderr, err_rc);
if (rc == 0)
goto emitter_error;
+ if (disable_mr) {
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)"Multi-Rail",
+ strlen("Multi-Rail"), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_BOOL_TAG,
+ (yaml_char_t *)"False",
+ strlen("False"), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+ }
+
+ if (state != -1) {
+ char peer_state[INT_STRING_LEN];
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)"peer state",
+ strlen("peer state"), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ snprintf(peer_state, sizeof(peer_state), "%d", state);
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_INT_TAG,
+ (yaml_char_t *)peer_state,
+ strlen(peer_state), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+ }
+
+ if (!nidstr && health_value == -1)
+ goto skip_peer_nis;
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)"peer ni",
+ strlen("peer ni"), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_sequence_start_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_SEQ_TAG,
+ 1, YAML_BLOCK_SEQUENCE_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ if (nidstr) {
+ struct nid_node head, *entry;
+ int count = 0;
+
+ /* If we have LNET_ANY_NID and its NLM_F_REPLACE we
+ * treat it as the all flag case for lnetctl peer set
+ */
+ if (strcmp(nidstr, "<?>") == 0) {
+ yaml_mapping_start_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_MAP_TAG,
+ 1, YAML_BLOCK_MAPPING_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)"nid",
+ strlen("nid"), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)nidstr,
+ strlen(nidstr), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_mapping_end_event_initialize(&event);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ goto handle_health;
+ }
+
+ NL_INIT_LIST_HEAD(&head.children);
+ nl_init_list_head(&head.list);
+ rc = lustre_lnet_parse_nid_range(&head, nidstr, &msg);
+ if (rc < 0) {
+ fprintf(stdout, "can't parse nidrange: \"%s\"\n", nidstr);
+ lustre_lnet_free_list(&head);
+ yaml_emitter_delete(&output);
+ errno = rc;
+ rc = 0;
+ goto free_reply;
+ }
+
+ if (nl_list_empty(&head.children)) {
+ lustre_lnet_free_list(&head);
+ yaml_emitter_delete(&output);
+ msg = "Unable to parse nidlist: did not expand to any nids";
+ errno = -ENOENT;
+ rc = 0;
+ goto free_reply;
+ }
+ rc = 1; /* one means its working */
+
+ nl_list_for_each_entry(entry, &head.children, list) {
+ char *nid = entry->nidstr;
+
+ if (count++ > LNET_MAX_NIDS_PER_PEER) {
+ lustre_lnet_free_list(&head);
+ yaml_emitter_delete(&output);
+ msg = "Unable to parse nidlist: specifies more NIDs than allowed";
+ errno = -E2BIG;
+ rc = 0;
+ goto free_reply;
+ }
+
+ yaml_mapping_start_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_MAP_TAG,
+ 1, YAML_BLOCK_MAPPING_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)"nid",
+ strlen("nid"), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)nid,
+ strlen(nid), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_mapping_end_event_initialize(&event);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+ }
+ lustre_lnet_free_list(&head);
+ }
+handle_health:
+ if (health_value >= 0) {
+ char health[INT_STRING_LEN];
+
+ /* Create the mapping for 'health stats'. The value field for
+ * the mapping is not provided so its treated as a empty string.
+ */
+ yaml_mapping_start_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_MAP_TAG,
+ 1, YAML_BLOCK_MAPPING_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)"health stats",
+ strlen("health stats"), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ /* Setup all mappings for data related to the 'health stats' */
+ yaml_mapping_start_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_MAP_TAG,
+ 1, YAML_BLOCK_MAPPING_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)"health value",
+ strlen("health value"), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ snprintf(health, sizeof(health), "%d", health_value);
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_INT_TAG,
+ (yaml_char_t *)health,
+ strlen(health), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_mapping_end_event_initialize(&event);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_mapping_end_event_initialize(&event);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+ }
+
+ yaml_sequence_end_event_initialize(&event);
+ rc = yaml_emitter_emit(&output, &event);
+ if (rc == 0)
+ goto emitter_error;
+skip_peer_nis:
yaml_mapping_end_event_initialize(&event);
rc = yaml_emitter_emit(&output, &event);
if (rc == 0)
return rc == 1 ? 0 : rc;
}
+int yaml_lnet_config_peer_ni_healthv(int healthv, bool all, char *lpni_nid,
+ int state, int seq_no, struct cYAML **err_rc)
+{
+ int rc;
+
+ rc = yaml_lnet_peer(lpni_nid ? lpni_nid : "<?>", all ? "<?>" : NULL,
+ false, healthv, state, false, LNET_GENL_VERSION,
+ NLM_F_REPLACE);
+ if (rc <= 0) {
+ if (rc == -EOPNOTSUPP)
+ goto old_api;
+ return rc;
+ }
+old_api:
+ if (state == -1)
+ rc = lustre_lnet_config_peer_ni_healthv(healthv, all, lpni_nid,
+ seq_no, err_rc);
+ else
+ rc = lustre_lnet_set_peer_state(state, lpni_nid, -1, err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ cYAML_print_tree2file(stderr, *err_rc);
+
+ cYAML_free_tree(*err_rc);
+
+ return rc;
+}
+
static int jt_set_peer_ni_value(int argc, char **argv)
{
- return set_value_helper(argc, argv, lustre_lnet_config_peer_ni_healthv);
+ int rc = check_cmd(peer_cmds, "peer", "set", 0, argc, argv);
+
+ if (rc < 0)
+ return rc;
+
+ return set_value_helper(argc, argv, yaml_lnet_config_peer_ni_healthv);
}
static int jt_show_recovery(int argc, char **argv)
static int jt_peer_nid_common(int argc, char **argv, int cmd)
{
+ int flags = cmd == LNETCTL_ADD_CMD ? NLM_F_CREATE : 0;
int rc = LUSTRE_CFG_RC_NO_ERR, opt;
bool is_mr = true;
char *prim_nid = NULL, *nidstr = NULL;
char err_str[LNET_MAX_STR_LEN] = "Error";
struct cYAML *err_rc = NULL;
int force_lock = 0;
-
const char *const short_opts = "k:m:n:f:l";
const struct option long_opts[] = {
{ .name = "prim_nid", .has_arg = required_argument, .val = 'k' },
{ .name = "lock_prim", .has_arg = no_argument, .val = 'l' },
{ .name = NULL } };
- rc = check_cmd(peer_cmds, "peer", "add", 2, argc, argv);
+ rc = check_cmd(peer_cmds, "peer",
+ cmd == LNETCTL_ADD_CMD ? "add" : "del", 2, argc, argv);
if (rc)
return rc;
"Unrecognized option '-%c'", opt);
}
force_lock = 1;
+ flags |= NLM_F_EXCL;
break;
case 'l':
if (cmd == LNETCTL_DEL_CMD) {
"Unrecognized option '-%c'", opt);
}
force_lock = 1;
+ flags |= NLM_F_EXCL;
break;
case '?':
print_help(peer_cmds, "peer",
}
}
+ rc = yaml_lnet_peer(prim_nid, nidstr, !is_mr, -1, -1, false,
+ LNET_GENL_VERSION, flags);
+ if (rc <= 0) {
+ if (rc == -EOPNOTSUPP)
+ goto old_api;
+ return rc;
+ }
+old_api:
rc = lustre_lnet_modify_peer(prim_nid, nidstr, is_mr, cmd,
force_lock, -1, &err_rc);
if (rc != LUSTRE_CFG_RC_NO_ERR)
echo "Add peer with nidranage that overlaps primary nid (o2ib)"
compare_peer_add "5.5.5.5@o2ib" "5.5.5.[1-4]@o2ib"
+
+ echo "Add peer with nidranage that contain , plus primary nid (o2ib)"
+ compare_peer_add "5.5.5.5@o2ib" "5.5.5.[1,2,3-4]@o2ib"
}
run_test 5 "Add peer with nidrange (o2ib)"