int lnet_peer_add_pref_rtr(struct lnet_peer_ni *lpni, struct lnet_nid *nid);
int lnet_peer_ni_set_non_mr_pref_nid(struct lnet_peer_ni *lpni,
struct lnet_nid *nid);
-int lnet_del_peer_ni(lnet_nid_t key_nid, lnet_nid_t nid);
-int lnet_user_add_peer_ni(lnet_nid_t prim_nid, struct lnet_nid *nid, bool mr);
+int lnet_del_peer_ni(lnet_nid_t key_nid, lnet_nid_t nid, int force);
+int lnet_user_add_peer_ni(lnet_nid_t prim_nid, struct lnet_nid *nid, bool mr,
+ bool lock_prim);
int lnet_get_peer_info(struct lnet_ioctl_peer_cfg *cfg, void __user *bulk);
int lnet_get_peer_ni_info(__u32 peer_index, __u64 *nid,
char alivness[LNET_MAX_STR_LEN],
struct libcfs_ioctl_hdr prcfg_hdr;
lnet_nid_t prcfg_prim_nid;
lnet_nid_t prcfg_cfg_nid;
- __u32 prcfg_count;
+ __u32 prcfg_count; /* ADD_PEER_NI: used for 'lock_prim' option
+ * DEL_PEER_NI: used for 'force' option
+ */
__u32 prcfg_mr;
__u32 prcfg_state;
__u32 prcfg_size;
lnet_nid4_to_nid(cfg->prcfg_cfg_nid, &nid);
rc = lnet_user_add_peer_ni(cfg->prcfg_prim_nid,
&nid,
- cfg->prcfg_mr);
+ cfg->prcfg_mr,
+ cfg->prcfg_count == 1);
mutex_unlock(&the_lnet.ln_api_mutex);
return rc;
}
mutex_lock(&the_lnet.ln_api_mutex);
rc = lnet_del_peer_ni(cfg->prcfg_prim_nid,
- cfg->prcfg_cfg_nid);
+ cfg->prcfg_cfg_nid,
+ cfg->prcfg_count);
mutex_unlock(&the_lnet.ln_api_mutex);
return rc;
}
return lnet_peer_add_nid(lp, nid, flags);
}
-int lnet_user_add_peer_ni(lnet_nid_t prim_nid, struct lnet_nid *nid, bool mr)
+int lnet_user_add_peer_ni(lnet_nid_t prim_nid, struct lnet_nid *nid, bool mr,
+ bool lock_prim)
{
- return lnet_add_peer_ni(prim_nid, lnet_nid_to_nid4(nid), mr,
- LNET_PEER_CONFIGURED);
+ int fl = LNET_PEER_CONFIGURED | (LNET_PEER_LOCK_PRIMARY * lock_prim);
+
+ return lnet_add_peer_ni(prim_nid, lnet_nid_to_nid4(nid), mr, fl);
}
static int
* being modified/deleted by a different thread.
*/
int
-lnet_del_peer_ni(lnet_nid_t prim_nid, lnet_nid_t nid)
+lnet_del_peer_ni(lnet_nid_t prim_nid, lnet_nid_t nid, int force)
{
struct lnet_peer *lp;
struct lnet_peer_ni *lpni;
if (nid == LNET_NID_ANY ||
nid == lnet_nid_to_nid4(&lp->lp_primary_nid)) {
- if (lp->lp_state & LNET_PEER_LOCK_PRIMARY) {
+ if (!force && lp->lp_state & LNET_PEER_LOCK_PRIMARY) {
CERROR("peer %s created by Lustre. Must preserve primary NID, but will remove other NIDs\n",
libcfs_nidstr(&lp->lp_primary_nid));
return lnet_reset_peer(lp);
}
static int lustre_lnet_handle_peer_nidlist(lnet_nid_t *nidlist, int num_nids,
- bool is_mr, __u32 cmd,
+ bool is_mr, int option, __u32 cmd,
char *cmd_type, char *err_str)
{
struct lnet_ioctl_peer_cfg data;
data.prcfg_mr = is_mr;
data.prcfg_prim_nid = nidlist[0];
data.prcfg_cfg_nid = LNET_NID_ANY;
+ data.prcfg_count = option;
rc = dispatch_peer_ni_cmd(cmd, &data, err_str, cmd_type);
data.prcfg_mr = is_mr;
data.prcfg_prim_nid = nidlist[0];
data.prcfg_cfg_nid = nidlist[nid_idx];
+ data.prcfg_count = option;
rc = dispatch_peer_ni_cmd(cmd, &data, err_str, cmd_type);
LIBCFS_IOC_INIT_V2(data, prcfg_hdr);
data.prcfg_prim_nid = nidlist[0];
data.prcfg_cfg_nid = LNET_NID_ANY;
+ data.prcfg_count = option;
rc = dispatch_peer_ni_cmd(cmd, &data, err_str, cmd_type);
}
static int
lustre_lnet_mod_peer_nidlist(lnet_nid_t pnid, lnet_nid_t *lnet_nidlist,
- int cmd, int num_nids, bool is_mr, int seq_no,
- struct cYAML **err_rc)
+ int cmd, int num_nids, bool is_mr, int option,
+ int seq_no, struct cYAML **err_rc)
{
int rc = LUSTRE_CFG_RC_NO_ERR;
char err_str[LNET_MAX_STR_LEN];
(num_nids - 1));
rc = lustre_lnet_handle_peer_nidlist(lnet_nidlist2,
- num_nids, is_mr, ioc_cmd,
- cmd_str, err_str);
+ num_nids, is_mr, option,
+ ioc_cmd, cmd_str, err_str);
out:
if (lnet_nidlist2)
free(lnet_nidlist2);
}
}
-int lustre_lnet_modify_peer(char *prim_nid, char *nids, bool is_mr,
- int cmd, int seq_no, struct cYAML **err_rc)
+int lustre_lnet_modify_peer(char *prim_nid, char *nids, bool is_mr, int cmd,
+ int option, int seq_no, struct cYAML **err_rc)
{
int num_nids, rc;
char err_str[LNET_MAX_STR_LEN] = "Error";
rc = lustre_lnet_mod_peer_nidlist(pnid, lnet_nidlist,
cmd, num_nids, is_mr,
- -1, err_rc);
+ option, -1, err_rc);
out:
if (rc != LUSTRE_CFG_RC_NO_ERR)
struct cYAML *seq_no, *prim_nid, *mr, *peer_nis;
lnet_nid_t lnet_nidlist[LNET_MAX_NIDS_PER_PEER];
lnet_nid_t pnid = LNET_NID_ANY;
+ int force = 0;
seq_no = cYAML_get_object_item(tree, "seq_no");
seqn = seq_no ? seq_no->cy_valueint : -1;
}
rc = lustre_lnet_mod_peer_nidlist(pnid, lnet_nidlist, cmd,
- num_nids, mr_value, seqn,
- err_rc);
+ num_nids, mr_value, force,
+ seqn, err_rc);
failed:
if (nidstr)
* nids - a comma separated string of nids
* is_mr - Specifies whether this peer is MR capable.
* cmd - CONFIG or DELETE
+ * force - whether force-deleting a peer with locked primary nid
* seq_no - sequence number of the command
* err_rc - YAML structure of the resultant return code
*/
-int lustre_lnet_modify_peer(char *prim_nid, char *nids, bool is_mr,
- int cmd, int seq_no, struct cYAML **err_rc);
+int lustre_lnet_modify_peer(char *prim_nid, char *nids, bool is_mr, int cmd,
+ int force, int seq_no, struct cYAML **err_rc);
/*
* lustre_lnet_show_peer
"\t--prim_nid: Primary NID of the peer.\n"
"\t--nid: one or more peer NIDs\n"
"\t--non_mr: create this peer as not Multi-Rail capable\n"
- "\t--ip2nets: specify a range of nids per peer"},
+ "\t--ip2nets: specify a range of nids per peer\n"
+ "\t--lock_prim: lock primary nid\n"},
{"del", jt_del_peer_nid, 0, "delete a peer NID\n"
"\t--prim_nid: Primary NID of the peer.\n"
"\t--nid: list of NIDs to remove. If none provided,\n"
"\t peer is deleted\n"
- "\t--ip2nets: specify a range of nids per peer"},
+ "\t--ip2nets: specify a range of nids per peer\n"
+ "\t--force: force-delete locked primary NID\n"},
{"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."
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:mn:";
+ 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 = "non_mr", .has_arg = no_argument, .val = 'm' },
{ .name = "nid", .has_arg = required_argument, .val = 'n' },
+ { .name = "force", .has_arg = no_argument, .val = 'f' },
+ { .name = "lock_prim", .has_arg = no_argument, .val = 'l' },
{ .name = NULL } };
rc = check_cmd(peer_cmds, "peer", "add", 2, argc, argv);
}
is_mr = false;
break;
+ case 'f':
+ if (cmd == LNETCTL_ADD_CMD) {
+ rc = LUSTRE_CFG_RC_BAD_PARAM;
+ snprintf(err_str, LNET_MAX_STR_LEN,
+ "Unrecognized option '-%c'", opt);
+ }
+ force_lock = 1;
+ break;
+ case 'l':
+ if (cmd == LNETCTL_DEL_CMD) {
+ rc = LUSTRE_CFG_RC_BAD_PARAM;
+ snprintf(err_str, LNET_MAX_STR_LEN,
+ "Unrecognized option '-%c'", opt);
+ }
+ force_lock = 1;
+ break;
case '?':
print_help(peer_cmds, "peer",
cmd == LNETCTL_ADD_CMD ? "add" : "del");
}
rc = lustre_lnet_modify_peer(prim_nid, nidstr, is_mr, cmd,
- -1, &err_rc);
+ force_lock, -1, &err_rc);
if (rc != LUSTRE_CFG_RC_NO_ERR)
goto out;
\-\-non_mr: create this peer as not Multi-Rail capable\.
.
.br
+\-\-lock_prim: lock primary NID of the peer for the purpose of identification with Lustre\.
+.
+.br
.TP
\fBlnetctl peer\fR del
\-\-prim_nid: Primary NID of the peer\.
.
.br
+\-\-force: optional, use to delete a peer with primary NID locked\.
+.
+.br
.TP
\fBlnetctl peer\fR show
}
run_test 25 "Delete all secondary nids from peer (tcp, gni and o2ib)"
+test_26() {
+ reinit_dlc || return $?
+
+ do_lnetctl peer add --prim_nid 1.1.1.1@tcp --lock_prim ||
+ error "Peer add with --lock_prim option failed $?"
+ do_lnetctl peer del --prim_nid 1.1.1.1@tcp ||
+ error "Peer del failed $?"
+ $LNETCTL peer show --nid 1.1.1.1@tcp | grep -q 1.1.1.1@tcp ||
+ error "1.1.1.1@tcp is not listed"
+ do_lnetctl peer del --prim_nid 1.1.1.1@tcp --force ||
+ error "Peer del --force failed $?"
+ do_lnetctl peer show --nid 1.1.1.1@tcp &&
+ error "failed to delete 1.1.1.1@tcp"
+
+ return 0
+}
+run_test 26 "Delete peer with primary nid locked"
+
test_99a() {
reinit_dlc || return $?