+ /*
+ * This function can be called with different cpt locks being
+ * held. lpni_alive_count modification needs to be properly protected.
+ * Significant reads to lpni_alive_count are also protected with
+ * the same lock
+ */
+ spin_lock(&lp->lpni_lock);
+
lp->lpni_timestamp = when; /* update timestamp */
lp->lpni_ping_deadline = 0; /* disable ping timeout */
if (lp->lpni_alive_count != 0 && /* got old news */
(!lp->lpni_alive) == (!alive)) { /* new date for old news */
lp->lpni_timestamp = when; /* update timestamp */
lp->lpni_ping_deadline = 0; /* disable ping timeout */
if (lp->lpni_alive_count != 0 && /* got old news */
(!lp->lpni_alive) == (!alive)) { /* new date for old news */
CDEBUG(D_NET, "set %s %d\n", libcfs_nid2str(lp->lpni_nid), alive);
}
CDEBUG(D_NET, "set %s %d\n", libcfs_nid2str(lp->lpni_nid), alive);
}
/* Notify only in 1 thread at any time to ensure ordered notification.
* NB individual events can be missed; the only guarantee is that you
* always get the most recent news */
/* Notify only in 1 thread at any time to ensure ordered notification.
* NB individual events can be missed; the only guarantee is that you
* always get the most recent news */
CDEBUG(D_NET, "%s: Unexpected magic %08x\n",
libcfs_nid2str(gw->lpni_nid), info->pi_magic);
gw->lpni_ping_feats = LNET_PING_FEAT_INVAL;
CDEBUG(D_NET, "%s: Unexpected magic %08x\n",
libcfs_nid2str(gw->lpni_nid), info->pi_magic);
gw->lpni_ping_feats = LNET_PING_FEAT_INVAL;
if ((gw->lpni_ping_feats & LNET_PING_FEAT_MASK) == 0) {
CDEBUG(D_NET, "%s: Unexpected features 0x%x\n",
libcfs_nid2str(gw->lpni_nid), gw->lpni_ping_feats);
if ((gw->lpni_ping_feats & LNET_PING_FEAT_MASK) == 0) {
CDEBUG(D_NET, "%s: Unexpected features 0x%x\n",
libcfs_nid2str(gw->lpni_nid), gw->lpni_ping_feats);
CDEBUG(D_NET, "%s: unexpected LNET_NID_ANY\n",
libcfs_nid2str(gw->lpni_nid));
gw->lpni_ping_feats = LNET_PING_FEAT_INVAL;
CDEBUG(D_NET, "%s: unexpected LNET_NID_ANY\n",
libcfs_nid2str(gw->lpni_nid));
gw->lpni_ping_feats = LNET_PING_FEAT_INVAL;
CDEBUG(D_NET, "%s: Unexpected status 0x%x\n",
libcfs_nid2str(gw->lpni_nid), stat->ns_status);
gw->lpni_ping_feats = LNET_PING_FEAT_INVAL;
CDEBUG(D_NET, "%s: Unexpected status 0x%x\n",
libcfs_nid2str(gw->lpni_nid), stat->ns_status);
gw->lpni_ping_feats = LNET_PING_FEAT_INVAL;
int
lnet_notify(lnet_ni_t *ni, lnet_nid_t nid, int alive, cfs_time_t when)
{
int
lnet_notify(lnet_ni_t *ni, lnet_nid_t nid, int alive, cfs_time_t when)
{
- struct lnet_peer_ni *lp = NULL;
- cfs_time_t now = cfs_time_current();
- int cpt = lnet_cpt_of_nid(nid, ni);
+ struct lnet_peer_ni *lp = NULL;
+ cfs_time_t now = cfs_time_current();
+ int cpt = lnet_cpt_of_nid(nid, ni);
+ /*
+ * It is possible for this function to be called for the same peer
+ * but with different NIs. We want to synchronize the notification
+ * between the different calls. So we will use the lpni_cpt to
+ * grab the net lock.
+ */
+ if (lp->lpni_cpt != cpt) {
+ lnet_net_unlock(cpt);
+ cpt = lp->lpni_cpt;
+ lnet_net_lock(cpt);
+ }
+
/* We can't fully trust LND on reporting exact peer last_alive
* if he notifies us about dead peer. For example ksocklnd can
* call us with when == _time_when_the_node_was_booted_ if
/* We can't fully trust LND on reporting exact peer last_alive
* if he notifies us about dead peer. For example ksocklnd can
* call us with when == _time_when_the_node_was_booted_ if