MODULE_PARM_DESC(lnet_recovery_limit,
"How long to attempt recovery of unhealthy peer interfaces in seconds. Set to 0 to allow indefinite recovery");
+unsigned int lnet_max_recovery_ping_interval = 900;
+unsigned int lnet_max_recovery_ping_count = 9;
+static int max_recovery_ping_interval_set(const char *val,
+ cfs_kernel_param_arg_t *kp);
+
+#define param_check_max_recovery_ping_interval(name, p) \
+ __param_check(name, p, int)
+
+#ifdef HAVE_KERNEL_PARAM_OPS
+static struct kernel_param_ops param_ops_max_recovery_ping_interval = {
+ .set = max_recovery_ping_interval_set,
+ .get = param_get_int,
+};
+module_param(lnet_max_recovery_ping_interval, max_recovery_ping_interval, 0644);
+#else
+module_param_call(lnet_max_recovery_ping_interval, max_recovery_ping_interval,
+ param_get_int, &lnet_max_recovery_ping_interval, 0644);
+#endif
+MODULE_PARM_DESC(lnet_max_recovery_ping_interval,
+ "The max interval between LNet recovery pings, in seconds");
+
static int lnet_interfaces_max = LNET_INTERFACES_MAX_DEFAULT;
static int intf_max_set(const char *val, cfs_kernel_param_arg_t *kp);
*/
static atomic_t lnet_dlc_seq_no = ATOMIC_INIT(0);
-static int lnet_ping(struct lnet_process_id id, struct lnet_nid *src_nid,
+static int lnet_ping(struct lnet_process_id id4, struct lnet_nid *src_nid,
signed long timeout, struct lnet_process_id __user *ids,
int n_ids);
}
static int
+max_recovery_ping_interval_set(const char *val, cfs_kernel_param_arg_t *kp)
+{
+ int rc;
+ unsigned long value;
+
+ rc = kstrtoul(val, 0, &value);
+ if (rc) {
+ CERROR("Invalid module parameter value for 'lnet_max_recovery_ping_interval'\n");
+ return rc;
+ }
+
+ if (!value) {
+ CERROR("Invalid max ping timeout. Must be strictly positive\n");
+ return -EINVAL;
+ }
+
+ /* The purpose of locking the api_mutex here is to ensure that
+ * the correct value ends up stored properly.
+ */
+ mutex_lock(&the_lnet.ln_api_mutex);
+ lnet_max_recovery_ping_interval = value;
+ lnet_max_recovery_ping_count = 0;
+ value >>= 1;
+ while (value) {
+ lnet_max_recovery_ping_count++;
+ value >>= 1;
+ }
+ mutex_unlock(&the_lnet.ln_api_mutex);
+
+ return 0;
+}
+
+static int
discovery_set(const char *val, cfs_kernel_param_arg_t *kp)
{
int rc;
}
static int
-lnet_unprepare (void)
+lnet_unprepare(void)
{
/* NB no LNET_LOCK since this is the last reference. All LND instances
* have shut down already, so it is safe to unlink and free all
list_for_each_entry(net, &the_lnet.ln_nets, net_list) {
if (net->net_id == net_id) {
- ni = list_entry(net->net_ni_list.next, struct lnet_ni,
- ni_netlist);
+ ni = list_first_entry(&net->net_ni_list, struct lnet_ni,
+ ni_netlist);
return ni;
}
}
static unsigned int
lnet_nid4_cpt_hash(lnet_nid_t nid, unsigned int number)
{
- __u64 key = nid;
- unsigned int val;
+ __u64 key = nid;
+ __u64 pair_bits = 0x0001000100010001LLU;
+ __u64 mask = pair_bits * 0xFF;
+ __u64 pair_sum;
- LASSERT(number >= 1 && number <= LNET_CPT_NUMBER);
+ /* Use (sum-by-multiplication of nid bytes) mod (number of CPTs)
+ * to match nid to a CPT.
+ */
+ pair_sum = (key & mask) + ((key >> 8) & mask);
+ pair_sum = (pair_sum * pair_bits) >> 48;
- if (number == 1)
- return 0;
+ CDEBUG(D_NET, "Match nid %s to cpt %u\n",
+ libcfs_nid2str(nid), (unsigned int)(pair_sum) % number);
- val = hash_long(key, LNET_CPT_BITS);
- /* NB: LNET_CP_NUMBER doesn't have to be PO2 */
- if (val < number)
- return val;
-
- return (unsigned int)(key + val + (val >> 1)) % number;
+ return (unsigned int)(pair_sum) % number;
}
unsigned int
* list and shut them down in guaranteed thread context
*/
i = 2;
- while (!list_empty(zombie_list)) {
- int *ref;
- int j;
+ while ((ni = list_first_entry_or_null(zombie_list,
+ struct lnet_ni,
+ ni_netlist)) != NULL) {
+ int *ref;
+ int j;
- ni = list_entry(zombie_list->next,
- struct lnet_ni, ni_netlist);
list_del_init(&ni->ni_netlist);
/* the ni should be in deleting state. If it's not it's
* a bug */
islo = ni->ni_net->net_lnd->lnd_type == LOLND;
LASSERT(!in_interrupt());
- /* Holding the mutex makes it safe for lnd_shutdown
+ /* Holding the LND mutex makes it safe for lnd_shutdown
* to call module_put(). Module unload cannot finish
* until lnet_unregister_lnd() completes, and that
- * requires the mutex.
+ * requires the LND mutex.
*/
+ mutex_unlock(&the_lnet.ln_api_mutex);
mutex_lock(&the_lnet.ln_lnd_mutex);
(net->net_lnd->lnd_shutdown)(ni);
mutex_unlock(&the_lnet.ln_lnd_mutex);
+ mutex_lock(&the_lnet.ln_api_mutex);
if (!islo)
CDEBUG(D_LNI, "Removed LNI %s\n",
list_del_init(&net->net_list);
- while (!list_empty(&net->net_ni_list)) {
- ni = list_entry(net->net_ni_list.next,
- struct lnet_ni, ni_netlist);
+ while ((ni = list_first_entry_or_null(&net->net_ni_list,
+ struct lnet_ni,
+ ni_netlist)) != NULL) {
lnet_net_unlock(LNET_LOCK_EX);
lnet_shutdown_lndni(ni);
lnet_net_lock(LNET_LOCK_EX);
/* NB called holding the global mutex */
/* All quiet on the API front */
- LASSERT(the_lnet.ln_state == LNET_STATE_RUNNING);
+ LASSERT(the_lnet.ln_state == LNET_STATE_RUNNING ||
+ the_lnet.ln_state == LNET_STATE_STOPPING);
LASSERT(the_lnet.ln_refcount == 0);
lnet_net_lock(LNET_LOCK_EX);
lnet_net_unlock(LNET_LOCK_EX);
/* iterate through the net zombie list and delete each net */
- while (!list_empty(&the_lnet.ln_net_zombie)) {
- net = list_entry(the_lnet.ln_net_zombie.next,
- struct lnet_net, net_list);
+ while ((net = list_first_entry_or_null(&the_lnet.ln_net_zombie,
+ struct lnet_net,
+ net_list)) != NULL)
lnet_shutdown_lndnet(net);
- }
spin_lock(&the_lnet.ln_msg_resend_lock);
list_splice(&the_lnet.ln_msg_resend, &resend);
lnet_ni_tq_credits(ni) * ni->ni_ncpts);
atomic_set(&ni->ni_healthv, LNET_MAX_HEALTH_VALUE);
+ /* Nodes with small feet have little entropy. The NID for this
+ * node gives the most entropy in the low bits.
+ */
+ add_device_randomness(&ni->ni_nid, sizeof(ni->ni_nid));
+
CDEBUG(D_LNI, "Added LNI %s [%d/%d/%d/%d]\n",
libcfs_nidstr(&ni->ni_nid),
ni->ni_net->net_tunables.lct_peer_tx_credits,
* After than we want to delete the network being added,
* to avoid a memory leak.
*/
- while (!list_empty(&net->net_ni_added)) {
- ni = list_entry(net->net_ni_added.next, struct lnet_ni,
- ni_netlist);
+ while ((ni = list_first_entry_or_null(&net->net_ni_added,
+ struct lnet_ni,
+ ni_netlist)) != NULL) {
list_del_init(&ni->ni_netlist);
/* make sure that the the NI we're about to start
* shutdown the new NIs that are being started up
* free the NET being started
*/
- while (!list_empty(&local_ni_list)) {
- ni = list_entry(local_ni_list.next, struct lnet_ni,
- ni_netlist);
-
+ while ((ni = list_first_entry_or_null(&local_ni_list,
+ struct lnet_ni,
+ ni_netlist)) != NULL)
lnet_shutdown_lndni(ni);
- }
failed0:
lnet_net_free(net);
the_lnet.ln_state = LNET_STATE_RUNNING;
lnet_net_unlock(LNET_LOCK_EX);
- while (!list_empty(netlist)) {
- net = list_entry(netlist->next, struct lnet_net, net_list);
+ while ((net = list_first_entry_or_null(netlist,
+ struct lnet_net,
+ net_list)) != NULL) {
list_del_init(&net->net_list);
rc = lnet_startup_lndnet(net, NULL);
CDEBUG(D_OTHER, "refs %d\n", the_lnet.ln_refcount);
+ if (the_lnet.ln_state == LNET_STATE_STOPPING) {
+ mutex_unlock(&the_lnet.ln_api_mutex);
+ return -ESHUTDOWN;
+ }
+
if (the_lnet.ln_refcount > 0) {
rc = the_lnet.ln_refcount++;
mutex_unlock(&the_lnet.ln_api_mutex);
lnet_unprepare();
LASSERT(rc < 0);
mutex_unlock(&the_lnet.ln_api_mutex);
- while (!list_empty(&net_head)) {
- struct lnet_net *net;
-
- net = list_entry(net_head.next, struct lnet_net, net_list);
+ while ((net = list_first_entry_or_null(&net_head,
+ struct lnet_net,
+ net_list)) != NULL) {
list_del_init(&net->net_list);
lnet_net_free(net);
}
} else {
LASSERT(!the_lnet.ln_niinit_self);
+ lnet_net_lock(LNET_LOCK_EX);
+ the_lnet.ln_state = LNET_STATE_STOPPING;
+ lnet_net_unlock(LNET_LOCK_EX);
+
lnet_fault_fini();
lnet_router_debugfs_fini();
* a message being sent. This function accessed the net without
* checking if the list is empty
*/
- if (prev == NULL) {
- if (net == NULL)
- net = list_entry(the_lnet.ln_nets.next, struct lnet_net,
- net_list);
+ if (!prev) {
+ if (!net)
+ net = list_first_entry(&the_lnet.ln_nets,
+ struct lnet_net,
+ net_list);
if (list_empty(&net->net_ni_list))
return NULL;
- ni = list_entry(net->net_ni_list.next, struct lnet_ni,
- ni_netlist);
+ ni = list_first_entry(&net->net_ni_list, struct lnet_ni,
+ ni_netlist);
return ni;
}
return NULL;
/* get the next net */
- net = list_entry(prev->ni_net->net_list.next, struct lnet_net,
- net_list);
+ net = list_first_entry(&prev->ni_net->net_list, struct lnet_net,
+ net_list);
if (list_empty(&net->net_ni_list))
return NULL;
/* get the ni on it */
- ni = list_entry(net->net_ni_list.next, struct lnet_ni,
- ni_netlist);
+ ni = list_first_entry(&net->net_ni_list, struct lnet_ni,
+ ni_netlist);
return ni;
}
return NULL;
/* there are more nis left */
- ni = list_entry(prev->ni_netlist.next, struct lnet_ni, ni_netlist);
+ ni = list_first_entry(&prev->ni_netlist, struct lnet_ni, ni_netlist);
return ni;
}
lnet_set_tune_defaults(tun);
mutex_lock(&the_lnet.ln_api_mutex);
- while (!list_empty(&net_head)) {
- net = list_entry(net_head.next, struct lnet_net, net_list);
+ if (the_lnet.ln_state != LNET_STATE_RUNNING) {
+ rc = -ESHUTDOWN;
+ goto out;
+ }
+
+ while ((net = list_first_entry_or_null(&net_head,
+ struct lnet_net,
+ net_list)) != NULL) {
list_del_init(&net->net_list);
rc = lnet_add_net_common(net, tun);
if (rc < 0)
out:
mutex_unlock(&the_lnet.ln_api_mutex);
- while (!list_empty(&net_head)) {
- net = list_entry(net_head.next, struct lnet_net, net_list);
+ while ((net = list_first_entry_or_null(&net_head,
+ struct lnet_net,
+ net_list)) != NULL) {
list_del_init(&net->net_list);
lnet_net_free(net);
}
lnet_set_tune_defaults(tun);
mutex_lock(&the_lnet.ln_api_mutex);
-
- rc = lnet_add_net_common(net, tun);
+ if (the_lnet.ln_state != LNET_STATE_RUNNING)
+ rc = -ESHUTDOWN;
+ else
+ rc = lnet_add_net_common(net, tun);
mutex_unlock(&the_lnet.ln_api_mutex);
return -EINVAL;
mutex_lock(&the_lnet.ln_api_mutex);
+ if (the_lnet.ln_state != LNET_STATE_RUNNING) {
+ rc = -ESHUTDOWN;
+ goto unlock_api_mutex;
+ }
lnet_net_lock(0);
return rc == 0 ? -EINVAL : rc;
mutex_lock(&the_lnet.ln_api_mutex);
+ if (the_lnet.ln_state != LNET_STATE_RUNNING) {
+ rc = -ESHUTDOWN;
+ goto out_unlock_clean;
+ }
if (rc > 1) {
rc = -EINVAL; /* only add one network per call */
goto out_unlock_clean;
}
- net = list_entry(net_head.next, struct lnet_net, net_list);
+ net = list_first_entry(&net_head, struct lnet_net, net_list);
list_del_init(&net->net_list);
LASSERT(lnet_net_unique(net->net_id, &the_lnet.ln_nets, NULL));
out_unlock_clean:
mutex_unlock(&the_lnet.ln_api_mutex);
- while (!list_empty(&net_head)) {
- /* net_head list is empty in success case */
- net = list_entry(net_head.next, struct lnet_net, net_list);
+ /* net_head list is empty in success case */
+ while ((net = list_first_entry_or_null(&net_head,
+ struct lnet_net,
+ net_list)) != NULL) {
list_del_init(&net->net_list);
lnet_net_free(net);
}
return -EINVAL;
mutex_lock(&the_lnet.ln_api_mutex);
+ if (the_lnet.ln_state != LNET_STATE_RUNNING) {
+ rc = -ESHUTDOWN;
+ goto out;
+ }
lnet_net_lock(0);
case IOC_LIBCFS_ADD_PEER_NI: {
struct lnet_ioctl_peer_cfg *cfg = arg;
+ struct lnet_nid prim_nid;
if (cfg->prcfg_hdr.ioc_len < sizeof(*cfg))
return -EINVAL;
mutex_lock(&the_lnet.ln_api_mutex);
- rc = lnet_add_peer_ni(cfg->prcfg_prim_nid,
- cfg->prcfg_cfg_nid,
- cfg->prcfg_mr, false);
+ lnet_nid4_to_nid(cfg->prcfg_prim_nid, &prim_nid);
+ lnet_nid4_to_nid(cfg->prcfg_cfg_nid, &nid);
+ rc = lnet_add_peer_ni(&prim_nid, &nid, cfg->prcfg_mr, false);
mutex_unlock(&the_lnet.ln_api_mutex);
return rc;
}
case IOC_LIBCFS_DEL_PEER_NI: {
struct lnet_ioctl_peer_cfg *cfg = arg;
+ struct lnet_nid prim_nid;
if (cfg->prcfg_hdr.ioc_len < sizeof(*cfg))
return -EINVAL;
mutex_lock(&the_lnet.ln_api_mutex);
- rc = lnet_del_peer_ni(cfg->prcfg_prim_nid,
- cfg->prcfg_cfg_nid);
+ lnet_nid4_to_nid(cfg->prcfg_prim_nid, &prim_nid);
+ lnet_nid4_to_nid(cfg->prcfg_cfg_nid, &nid);
+ rc = lnet_del_peer_ni(&prim_nid,
+ &nid);
mutex_unlock(&the_lnet.ln_api_mutex);
return rc;
}
}
case IOC_LIBCFS_LNET_DIST:
- rc = LNetDist(data->ioc_nid, &data->ioc_nid, &data->ioc_u32[1]);
+ lnet_nid4_to_nid(data->ioc_nid, &nid);
+ rc = LNetDist(&nid, &nid, &data->ioc_u32[1]);
if (rc < 0 && rc != -EHOSTUNREACH)
return rc;
+ data->ioc_nid = lnet_nid_to_nid4(&nid);
data->ioc_u32[0] = rc;
return 0;
return rc;
mutex_lock(&the_lnet.ln_api_mutex);
- lp = lnet_find_peer4(ping->ping_id.nid);
+ lnet_nid4_to_nid(ping->ping_id.nid, &nid);
+ lp = lnet_find_peer(&nid);
if (lp) {
ping->ping_id.nid =
lnet_nid_to_nid4(&lp->lp_primary_nid);
return rc;
mutex_lock(&the_lnet.ln_api_mutex);
- lp = lnet_find_peer4(discover->ping_id.nid);
+ lnet_nid4_to_nid(discover->ping_id.nid, &nid);
+ lp = lnet_find_peer(&nid);
if (lp) {
discover->ping_id.nid =
lnet_nid_to_nid4(&lp->lp_primary_nid);
* \retval true If peer NID is on the local node.
* \retval false If peer NID is not on the local node.
*/
-bool LNetIsPeerLocal(lnet_nid_t nid)
+bool LNetIsPeerLocal(struct lnet_nid *nid)
{
struct lnet_net *net;
struct lnet_ni *ni;
cpt = lnet_net_lock_current();
list_for_each_entry(net, &the_lnet.ln_nets, net_list) {
list_for_each_entry(ni, &net->net_ni_list, ni_netlist) {
- if (lnet_nid_to_nid4(&ni->ni_nid) == nid) {
+ if (nid_same(&ni->ni_nid, nid)) {
lnet_net_unlock(cpt);
return true;
}
complete(&pd->completion);
}
-static int lnet_ping(struct lnet_process_id id, struct lnet_nid *src_nid,
+static int lnet_ping(struct lnet_process_id id4, struct lnet_nid *src_nid,
signed long timeout, struct lnet_process_id __user *ids,
int n_ids)
{
struct ping_data pd = { 0 };
struct lnet_ping_buffer *pbuf;
struct lnet_process_id tmpid;
+ struct lnet_processid id;
int i;
int nob;
int rc;
int rc2;
/* n_ids limit is arbitrary */
- if (n_ids <= 0 || id.nid == LNET_NID_ANY)
+ if (n_ids <= 0 || id4.nid == LNET_NID_ANY)
return -EINVAL;
/*
if (n_ids > lnet_interfaces_max)
n_ids = lnet_interfaces_max;
- if (id.pid == LNET_PID_ANY)
- id.pid = LNET_PID_LUSTRE;
+ if (id4.pid == LNET_PID_ANY)
+ id4.pid = LNET_PID_LUSTRE;
pbuf = lnet_ping_buffer_alloc(n_ids, GFP_NOFS);
if (!pbuf)
goto fail_ping_buffer_decref;
}
- rc = LNetGet(lnet_nid_to_nid4(src_nid), pd.mdh, id,
- LNET_RESERVED_PORTAL,
+ lnet_pid4_to_pid(id4, &id);
+ rc = LNetGet(src_nid, pd.mdh, &id, LNET_RESERVED_PORTAL,
LNET_PROTO_PING_MATCHBITS, 0, false);
if (rc != 0) {
if (nob < 8) {
CERROR("%s: ping info too short %d\n",
- libcfs_id2str(id), nob);
+ libcfs_idstr(&id), nob);
goto fail_ping_buffer_decref;
}
lnet_swap_pinginfo(pbuf);
} else if (pbuf->pb_info.pi_magic != LNET_PROTO_PING_MAGIC) {
CERROR("%s: Unexpected magic %08x\n",
- libcfs_id2str(id), pbuf->pb_info.pi_magic);
+ libcfs_idstr(&id), pbuf->pb_info.pi_magic);
goto fail_ping_buffer_decref;
}
if ((pbuf->pb_info.pi_features & LNET_PING_FEAT_NI_STATUS) == 0) {
CERROR("%s: ping w/o NI status: 0x%x\n",
- libcfs_id2str(id), pbuf->pb_info.pi_features);
+ libcfs_idstr(&id), pbuf->pb_info.pi_features);
goto fail_ping_buffer_decref;
}
if (nob < LNET_PING_INFO_SIZE(0)) {
CERROR("%s: Short reply %d(%d min)\n",
- libcfs_id2str(id),
+ libcfs_idstr(&id),
nob, (int)LNET_PING_INFO_SIZE(0));
goto fail_ping_buffer_decref;
}
if (nob < LNET_PING_INFO_SIZE(n_ids)) {
CERROR("%s: Short reply %d(%d expected)\n",
- libcfs_id2str(id),
+ libcfs_idstr(&id),
nob, (int)LNET_PING_INFO_SIZE(n_ids));
goto fail_ping_buffer_decref;
}
}
static int
-lnet_discover(struct lnet_process_id id, __u32 force,
+lnet_discover(struct lnet_process_id id4, __u32 force,
struct lnet_process_id __user *ids, int n_ids)
{
struct lnet_peer_ni *lpni;
struct lnet_peer_ni *p;
struct lnet_peer *lp;
struct lnet_process_id *buf;
+ struct lnet_processid id;
int cpt;
int i;
int rc;
if (n_ids <= 0 ||
- id.nid == LNET_NID_ANY)
+ id4.nid == LNET_NID_ANY)
return -EINVAL;
+ lnet_pid4_to_pid(id4, &id);
if (id.pid == LNET_PID_ANY)
id.pid = LNET_PID_LUSTRE;
return -ENOMEM;
cpt = lnet_net_lock_current();
- lpni = lnet_nid2peerni_locked(id.nid, LNET_NID_ANY, cpt);
+ lpni = lnet_peerni_by_nid_locked(&id.nid, NULL, cpt);
if (IS_ERR(lpni)) {
rc = PTR_ERR(lpni);
goto out;
* and lookup the lpni again
*/
lnet_peer_ni_decref_locked(lpni);
- lpni = lnet_find_peer_ni_locked(id.nid);
+ lpni = lnet_peer_ni_find_locked(&id.nid);
if (!lpni) {
rc = -ENOENT;
goto out;