X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;ds=sidebyside;f=lnet%2Flnet%2Fpeer.c;h=20f78fb30ec2953192733a6df1f6d2a9f80c7862;hb=9ed12d2e8f3f2189d7794e55e7c0e8c0178ffde7;hp=1425bd8276579df27c59511e54c6b54eb847bb76;hpb=010f6b1819b9009745abda8d6119589dc336bd95;p=fs%2Flustre-release.git diff --git a/lnet/lnet/peer.c b/lnet/lnet/peer.c index 1425bd8..20f78fb 100644 --- a/lnet/lnet/peer.c +++ b/lnet/lnet/peer.c @@ -104,7 +104,7 @@ lnet_peer_tables_destroy(void) for (j = 0; j < LNET_PEER_HASH_SIZE; j++) LASSERT(list_empty(&hash[j])); - LIBCFS_FREE(hash, LNET_PEER_HASH_SIZE * sizeof(*hash)); + CFS_FREE_PTR_ARRAY(hash, LNET_PEER_HASH_SIZE); } cfs_percpt_free(the_lnet.ln_peer_tables); @@ -258,6 +258,11 @@ lnet_peer_alloc(lnet_nid_t nid) init_waitqueue_head(&lp->lp_dc_waitq); spin_lock_init(&lp->lp_lock); lp->lp_primary_nid = nid; + lp->lp_disc_src_nid = LNET_NID_ANY; + if (lnet_peers_start_down()) + lp->lp_alive = false; + else + lp->lp_alive = true; /* * all peers created on a router should have health on @@ -273,7 +278,7 @@ lnet_peer_alloc(lnet_nid_t nid) * to ever use a different interface when sending messages to * myself. */ - if (LNET_NETTYP(LNET_NIDNET(nid)) == LOLND) + if (nid == LNET_NID_LO_0) lp->lp_state = LNET_PEER_NO_DISCOVERY; lp->lp_cpt = lnet_nid_cpt_hash(nid, LNET_CPT_NUMBER); @@ -400,8 +405,6 @@ lnet_peer_ni_del_locked(struct lnet_peer_ni *lpni, bool force) /* decrement the ref count on the peer table */ ptable = the_lnet.ln_peer_tables[lpni->lpni_cpt]; - LASSERT(ptable->pt_number > 0); - ptable->pt_number--; /* * The peer_ni can no longer be found with a lookup. But there @@ -523,7 +526,7 @@ lnet_peer_del_nid(struct lnet_peer *lp, lnet_nid_t nid, unsigned flags) /* assign the next peer_ni to be the primary */ lpni2 = lnet_get_next_peer_ni_locked(lp, NULL, lpni); LASSERT(lpni2); - lp->lp_primary_nid = lpni->lpni_nid; + lp->lp_primary_nid = lpni2->lpni_nid; } rc = lnet_peer_ni_del_locked(lpni, force); @@ -574,22 +577,10 @@ lnet_peer_table_cleanup_locked(struct lnet_net *net, static void lnet_peer_ni_finalize_wait(struct lnet_peer_table *ptable) { - int i = 3; - - spin_lock(&ptable->pt_zombie_lock); - while (ptable->pt_zombies) { - spin_unlock(&ptable->pt_zombie_lock); - - if (is_power_of_2(i)) { - CDEBUG(D_WARNING, + wait_var_event_warning(&ptable->pt_zombies, + ptable->pt_zombies == 0, "Waiting for %d zombies on peer table\n", ptable->pt_zombies); - } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(cfs_time_seconds(1) >> 1); - spin_lock(&ptable->pt_zombie_lock); - } - spin_unlock(&ptable->pt_zombie_lock); } static void @@ -651,7 +642,8 @@ lnet_get_peer_ni_locked(struct lnet_peer_table *ptable, lnet_nid_t nid) struct list_head *peers; struct lnet_peer_ni *lp; - LASSERT(the_lnet.ln_state == LNET_STATE_RUNNING); + if (the_lnet.ln_state != LNET_STATE_RUNNING) + return NULL; peers = &ptable->pt_hash[lnet_nid2peerhash(nid)]; list_for_each_entry(lp, peers, lpni_hashlist) { @@ -1047,7 +1039,7 @@ lnet_peer_add_pref_nid(struct lnet_peer_ni *lpni, lnet_nid_t nid) if (oldnids) { size = sizeof(*nids) * (lpni->lpni_pref_nnids - 1); - LIBCFS_FREE(oldnids, sizeof(*oldnids) * size); + CFS_FREE_PTR_ARRAY(oldnids, size); } out: if (rc == -EEXIST && (lpni->lpni_state & LNET_PEER_NI_NON_MR_PREF)) { @@ -1127,7 +1119,7 @@ lnet_peer_del_pref_nid(struct lnet_peer_ni *lpni, lnet_nid_t nid) if (oldnids) { size = sizeof(*nids) * (lpni->lpni_pref_nnids + 1); - LIBCFS_FREE(oldnids, sizeof(*oldnids) * size); + CFS_FREE_PTR_ARRAY(oldnids, size); } out: CDEBUG(D_NET, "peer %s nid %s: %d\n", @@ -1189,6 +1181,9 @@ LNetPrimaryNID(lnet_nid_t nid) int rc = 0; int cpt; + if (nid == LNET_NID_LO_0) + return LNET_NID_LO_0; + cpt = lnet_net_lock_current(); lpni = lnet_nid2peerni_locked(nid, LNET_NID_ANY, cpt); if (IS_ERR(lpni)) { @@ -1198,6 +1193,11 @@ LNetPrimaryNID(lnet_nid_t nid) lp = lpni->lpni_peer_net->lpn_peer; while (!lnet_peer_is_uptodate(lp)) { + spin_lock(&lp->lp_lock); + /* force a full discovery cycle */ + lp->lp_state |= LNET_PEER_FORCE_PING | LNET_PEER_FORCE_PUSH; + spin_unlock(&lp->lp_lock); + rc = lnet_discover_peer_locked(lpni, cpt, true); if (rc) goto out_decref; @@ -1257,7 +1257,6 @@ lnet_peer_attach_peer_ni(struct lnet_peer *lp, ptable = the_lnet.ln_peer_tables[lpni->lpni_cpt]; list_add_tail(&lpni->lpni_hashlist, &ptable->pt_hash[hash]); ptable->pt_version++; - ptable->pt_number++; /* This is the 1st refcount on lpni. */ atomic_inc(&lpni->lpni_refcount); } @@ -1274,6 +1273,7 @@ lnet_peer_attach_peer_ni(struct lnet_peer *lp, /* Add peer_ni to peer_net */ lpni->lpni_peer_net = lpn; list_add_tail(&lpni->lpni_peer_nis, &lpn->lpn_peer_nis); + lnet_update_peer_net_healthv(lpni); lnet_peer_net_addref_locked(lpn); /* Add peer_net to peer */ @@ -1528,11 +1528,7 @@ lnet_peer_ni_traffic_add(lnet_nid_t nid, lnet_nid_t pref) struct lnet_peer *lp; struct lnet_peer_net *lpn; struct lnet_peer_ni *lpni; - /* - * Assume peer is Multi-Rail capable and let discovery find out - * otherwise. - */ - unsigned flags = LNET_PEER_MULTI_RAIL; + unsigned flags = 0; int rc = 0; if (nid == LNET_NID_ANY) { @@ -1722,10 +1718,9 @@ lnet_destroy_peer_ni_locked(struct lnet_peer_ni *lpni) ptable->pt_zombies--; spin_unlock(&ptable->pt_zombie_lock); - if (lpni->lpni_pref_nnids > 1) { - LIBCFS_FREE(lpni->lpni_pref.nids, - sizeof(*lpni->lpni_pref.nids) * lpni->lpni_pref_nnids); - } + if (lpni->lpni_pref_nnids > 1) + CFS_FREE_PTR_ARRAY(lpni->lpni_pref.nids, lpni->lpni_pref_nnids); + LIBCFS_FREE(lpni, sizeof(*lpni)); lnet_peer_net_decref_locked(lpn); @@ -1926,9 +1921,7 @@ static void lnet_peer_discovery_complete(struct lnet_peer *lp) { struct lnet_msg *msg, *tmp; int rc = 0; - struct list_head pending_msgs; - - INIT_LIST_HEAD(&pending_msgs); + LIST_HEAD(pending_msgs); CDEBUG(D_NET, "Discovery complete. Dequeue peer %s\n", libcfs_nid2str(lp->lp_primary_nid)); @@ -1974,15 +1967,18 @@ static void lnet_peer_discovery_complete(struct lnet_peer *lp) */ void lnet_peer_push_event(struct lnet_event *ev) { - struct lnet_ping_buffer *pbuf = ev->md.user_ptr; + struct lnet_ping_buffer *pbuf; struct lnet_peer *lp; + pbuf = LNET_PING_INFO_TO_BUFFER(ev->md_start + ev->offset); + /* lnet_find_peer() adds a refcount */ lp = lnet_find_peer(ev->source.nid); if (!lp) { CDEBUG(D_NET, "Push Put from unknown %s (source %s). Ignoring...\n", libcfs_nid2str(ev->initiator.nid), libcfs_nid2str(ev->source.nid)); + pbuf->pb_needs_post = true; return; } @@ -2034,26 +2030,24 @@ void lnet_peer_push_event(struct lnet_event *ev) } /* - * Check the MULTIRAIL flag. Complain if the peer was DLC - * configured without it. - */ - if (!(lp->lp_state & LNET_PEER_MULTI_RAIL)) { - if (lp->lp_state & LNET_PEER_CONFIGURED) { - CERROR("Push says %s is Multi-Rail, DLC says not\n", - libcfs_nid2str(lp->lp_primary_nid)); - } else { - lp->lp_state |= LNET_PEER_MULTI_RAIL; - lnet_peer_clr_non_mr_pref_nids(lp); - } - } - - /* * The peer may have discovery disabled at its end. Set * NO_DISCOVERY as appropriate. */ if (!(pbuf->pb_info.pi_features & LNET_PING_FEAT_DISCOVERY)) { CDEBUG(D_NET, "Peer %s has discovery disabled\n", libcfs_nid2str(lp->lp_primary_nid)); + /* + * Mark the peer for deletion if we already know about it + * and it's going from discovery set to no discovery set + */ + if (!(lp->lp_state & (LNET_PEER_NO_DISCOVERY | + LNET_PEER_DISCOVERING)) && + lp->lp_state & LNET_PEER_DISCOVERED) { + CDEBUG(D_NET, "Marking %s:0x%x for deletion\n", + libcfs_nid2str(lp->lp_primary_nid), + lp->lp_state); + lp->lp_state |= LNET_PEER_MARK_DELETION; + } lp->lp_state |= LNET_PEER_NO_DISCOVERY; } else if (lp->lp_state & LNET_PEER_NO_DISCOVERY) { CDEBUG(D_NET, "Peer %s has discovery enabled\n", @@ -2062,11 +2056,36 @@ void lnet_peer_push_event(struct lnet_event *ev) } /* + * Update the MULTI_RAIL flag based on the push. If the peer + * was configured with DLC then the setting should match what + * DLC put in. + * NB: We verified above that the MR feature bit is set in pi_features + */ + if (lp->lp_state & LNET_PEER_MULTI_RAIL) { + CDEBUG(D_NET, "peer %s(%p) is MR\n", + libcfs_nid2str(lp->lp_primary_nid), lp); + } else if (lp->lp_state & LNET_PEER_CONFIGURED) { + CWARN("Push says %s is Multi-Rail, DLC says not\n", + libcfs_nid2str(lp->lp_primary_nid)); + } else if (lnet_peer_discovery_disabled) { + CDEBUG(D_NET, "peer %s(%p) not MR: DD disabled locally\n", + libcfs_nid2str(lp->lp_primary_nid), lp); + } else if (lp->lp_state & LNET_PEER_NO_DISCOVERY) { + CDEBUG(D_NET, "peer %s(%p) not MR: DD disabled remotely\n", + libcfs_nid2str(lp->lp_primary_nid), lp); + } else { + CDEBUG(D_NET, "peer %s(%p) is MR capable\n", + libcfs_nid2str(lp->lp_primary_nid), lp); + lp->lp_state |= LNET_PEER_MULTI_RAIL; + lnet_peer_clr_non_mr_pref_nids(lp); + } + + /* * Check for truncation of the Put message. Clear the * NIDS_UPTODATE flag and set FORCE_PING to trigger a ping, * and tell discovery to allocate a bigger buffer. */ - if (pbuf->pb_nnis < pbuf->pb_info.pi_nnis) { + if (ev->mlength < ev->rlength) { if (the_lnet.ln_push_target_nnis < pbuf->pb_info.pi_nnis) the_lnet.ln_push_target_nnis = pbuf->pb_info.pi_nnis; lp->lp_state &= ~LNET_PEER_NIDS_UPTODATE; @@ -2124,6 +2143,9 @@ void lnet_peer_push_event(struct lnet_event *ev) LNET_PING_BUFFER_SEQNO(pbuf)); out: + /* We've processed this buffer. It can be reposted */ + pbuf->pb_needs_post = true; + /* * Queue the peer for discovery if not done, force it on the request * queue and wake the discovery thread if the peer was already queued, @@ -2256,7 +2278,7 @@ lnet_discovery_event_ack(struct lnet_peer *lp, struct lnet_event *ev) { struct lnet_ping_buffer *pbuf; - pbuf = LNET_PING_INFO_TO_BUFFER(ev->md.start); + pbuf = LNET_PING_INFO_TO_BUFFER(ev->md_start); spin_lock(&lp->lp_lock); lp->lp_state &= ~LNET_PEER_PUSH_SENT; lp->lp_push_error = ev->status; @@ -2279,6 +2301,8 @@ lnet_discovery_event_reply(struct lnet_peer *lp, struct lnet_event *ev) spin_lock(&lp->lp_lock); + lp->lp_disc_src_nid = ev->target.nid; + /* * If some kind of error happened the contents of message * cannot be used. Set PING_FAILED to trigger a retry. @@ -2293,7 +2317,7 @@ lnet_discovery_event_reply(struct lnet_peer *lp, struct lnet_event *ev) goto out; } - pbuf = LNET_PING_INFO_TO_BUFFER(ev->md.start); + pbuf = LNET_PING_INFO_TO_BUFFER(ev->md_start); if (pbuf->pb_info.pi_magic == __swab32(LNET_PROTO_PING_MAGIC)) lnet_swap_pinginfo(pbuf); @@ -2312,20 +2336,6 @@ lnet_discovery_event_reply(struct lnet_peer *lp, struct lnet_event *ev) /* - * Only enable the multi-rail feature on the peer if both sides of - * the connection have discovery on - */ - if (pbuf->pb_info.pi_features & LNET_PING_FEAT_MULTI_RAIL) { - CDEBUG(D_NET, "Peer %s has Multi-Rail feature enabled\n", - libcfs_nid2str(lp->lp_primary_nid)); - lp->lp_state |= LNET_PEER_MULTI_RAIL; - } else { - CDEBUG(D_NET, "Peer %s has Multi-Rail feature disabled\n", - libcfs_nid2str(lp->lp_primary_nid)); - lp->lp_state &= ~LNET_PEER_MULTI_RAIL; - } - - /* * The peer may have discovery disabled at its end. Set * NO_DISCOVERY as appropriate. */ @@ -2347,22 +2357,24 @@ lnet_discovery_event_reply(struct lnet_peer *lp, struct lnet_event *ev) */ if (pbuf->pb_info.pi_features & LNET_PING_FEAT_MULTI_RAIL) { if (lp->lp_state & LNET_PEER_MULTI_RAIL) { - /* Everything's fine */ + CDEBUG(D_NET, "peer %s(%p) is MR\n", + libcfs_nid2str(lp->lp_primary_nid), lp); } else if (lp->lp_state & LNET_PEER_CONFIGURED) { CWARN("Reply says %s is Multi-Rail, DLC says not\n", libcfs_nid2str(lp->lp_primary_nid)); + } else if (lnet_peer_discovery_disabled) { + CDEBUG(D_NET, + "peer %s(%p) not MR: DD disabled locally\n", + libcfs_nid2str(lp->lp_primary_nid), lp); + } else if (lp->lp_state & LNET_PEER_NO_DISCOVERY) { + CDEBUG(D_NET, + "peer %s(%p) not MR: DD disabled remotely\n", + libcfs_nid2str(lp->lp_primary_nid), lp); } else { - /* - * if discovery is disabled then we don't want to - * update the state of the peer. All we'll do is - * update the peer_nis which were reported back in - * the initial ping - */ - - if (!lnet_is_discovery_disabled_locked(lp)) { - lp->lp_state |= LNET_PEER_MULTI_RAIL; - lnet_peer_clr_non_mr_pref_nids(lp); - } + CDEBUG(D_NET, "peer %s(%p) is MR capable\n", + libcfs_nid2str(lp->lp_primary_nid), lp); + lp->lp_state |= LNET_PEER_MULTI_RAIL; + lnet_peer_clr_non_mr_pref_nids(lp); } } else if (lp->lp_state & LNET_PEER_MULTI_RAIL) { if (lp->lp_state & LNET_PEER_CONFIGURED) { @@ -2506,7 +2518,7 @@ lnet_discovery_event_unlink(struct lnet_peer *lp, struct lnet_event *ev) */ static void lnet_discovery_event_handler(struct lnet_event *event) { - struct lnet_peer *lp = event->md.user_ptr; + struct lnet_peer *lp = event->md_user_ptr; struct lnet_ping_buffer *pbuf; int rc; @@ -2536,7 +2548,7 @@ static void lnet_discovery_event_handler(struct lnet_event *event) } lnet_net_lock(LNET_LOCK_EX); if (event->unlinked) { - pbuf = LNET_PING_INFO_TO_BUFFER(event->md.start); + pbuf = LNET_PING_INFO_TO_BUFFER(event->md_start); lnet_ping_buffer_decref(pbuf); lnet_peer_decref_locked(lp); } @@ -2599,10 +2611,10 @@ static int lnet_peer_merge_data(struct lnet_peer *lp, lp->lp_state &= ~LNET_PEER_ROUTER_ENABLED; spin_unlock(&lp->lp_lock); - nnis = MAX(lp->lp_nnis, pbuf->pb_info.pi_nnis); - LIBCFS_ALLOC(curnis, nnis * sizeof(*curnis)); - LIBCFS_ALLOC(addnis, nnis * sizeof(*addnis)); - LIBCFS_ALLOC(delnis, nnis * sizeof(*delnis)); + nnis = max_t(int, lp->lp_nnis, pbuf->pb_info.pi_nnis); + CFS_ALLOC_PTR_ARRAY(curnis, nnis); + CFS_ALLOC_PTR_ARRAY(addnis, nnis); + CFS_ALLOC_PTR_ARRAY(delnis, nnis); if (!curnis || !addnis || !delnis) { rc = -ENOMEM; goto out; @@ -2635,7 +2647,7 @@ static int lnet_peer_merge_data(struct lnet_peer *lp, * present in curnis[] then this peer is for this node. */ for (i = 0; i < ncurnis; i++) { - if (LNET_NETTYP(LNET_NIDNET(curnis[i])) == LOLND) + if (curnis[i] == LNET_NID_LO_0) continue; for (j = 1; j < pbuf->pb_info.pi_nnis; j++) { if (curnis[i] == pbuf->pb_info.pi_ni[j].ns_nid) { @@ -2706,9 +2718,9 @@ static int lnet_peer_merge_data(struct lnet_peer *lp, */ rc = 0; out: - LIBCFS_FREE(curnis, nnis * sizeof(*curnis)); - LIBCFS_FREE(addnis, nnis * sizeof(*addnis)); - LIBCFS_FREE(delnis, nnis * sizeof(*delnis)); + CFS_FREE_PTR_ARRAY(curnis, nnis); + CFS_FREE_PTR_ARRAY(addnis, nnis); + CFS_FREE_PTR_ARRAY(delnis, nnis); lnet_ping_buffer_decref(pbuf); CDEBUG(D_NET, "peer %s (%p): %d\n", libcfs_nid2str(lp->lp_primary_nid), lp, rc); @@ -2858,7 +2870,7 @@ __must_hold(&lp->lp_lock) if (pbuf->pb_info.pi_nnis <= 1) goto out; nid = pbuf->pb_info.pi_ni[1].ns_nid; - if (LNET_NETTYP(LNET_NIDNET(lp->lp_primary_nid)) == LOLND) { + if (lp->lp_primary_nid == LNET_NID_LO_0) { rc = lnet_peer_set_primary_nid(lp, nid, flags); if (!rc) rc = lnet_peer_merge_data(lp, pbuf); @@ -2993,10 +3005,10 @@ __must_hold(&lp->lp_lock) pnid = lnet_peer_select_nid(lp); lnet_net_unlock(cpt); - nnis = MAX(lp->lp_data_nnis, LNET_INTERFACES_MIN); + nnis = max(lp->lp_data_nnis, LNET_INTERFACES_MIN); rc = lnet_send_ping(pnid, &lp->lp_ping_mdh, nnis, lp, - the_lnet.ln_dc_eqh, false); + the_lnet.ln_dc_handler, false); /* * if LNetMDBind in lnet_send_ping fails we need to decrement the @@ -3057,6 +3069,21 @@ __must_hold(&lp->lp_lock) return rc ? rc : LNET_REDISCOVER_PEER; } +/* + * Mark the peer as discovered. + */ +static int lnet_peer_discovered(struct lnet_peer *lp) +__must_hold(&lp->lp_lock) +{ + lp->lp_state |= LNET_PEER_DISCOVERED; + lp->lp_state &= ~(LNET_PEER_DISCOVERING | + LNET_PEER_REDISCOVER); + + CDEBUG(D_NET, "peer %s\n", libcfs_nid2str(lp->lp_primary_nid)); + + return 0; +} + /* Active side of push. */ static int lnet_peer_send_push(struct lnet_peer *lp) __must_hold(&lp->lp_lock) @@ -3070,6 +3097,12 @@ __must_hold(&lp->lp_lock) /* Don't push to a non-multi-rail peer. */ if (!(lp->lp_state & LNET_PEER_MULTI_RAIL)) { lp->lp_state &= ~LNET_PEER_FORCE_PUSH; + /* if peer's NIDs are uptodate then peer is discovered */ + if (lp->lp_state & LNET_PEER_NIDS_UPTODATE) { + rc = lnet_peer_discovered(lp); + return rc; + } + return 0; } @@ -3087,11 +3120,11 @@ __must_hold(&lp->lp_lock) md.length = LNET_PING_INFO_SIZE(pbuf->pb_nnis); md.threshold = 2; /* Put/Ack */ md.max_size = 0; - md.options = 0; - md.eq_handle = the_lnet.ln_dc_eqh; + md.options = LNET_MD_TRACK_RESPONSE; + md.handler = the_lnet.ln_dc_handler; md.user_ptr = lp; - rc = LNetMDBind(md, LNET_UNLINK, &lp->lp_push_mdh); + rc = LNetMDBind(&md, LNET_UNLINK, &lp->lp_push_mdh); if (rc) { lnet_ping_buffer_decref(pbuf); CERROR("Can't bind push source MD: %d\n", rc); @@ -3109,10 +3142,18 @@ __must_hold(&lp->lp_lock) goto fail_unlink; } - rc = LNetPut(LNET_NID_ANY, lp->lp_push_mdh, + rc = LNetPut(lp->lp_disc_src_nid, lp->lp_push_mdh, LNET_ACK_REQ, id, LNET_RESERVED_PORTAL, LNET_PROTO_PING_MATCHBITS, 0, 0); + /* + * reset the discovery nid. There is no need to restrict sending + * from that source, if we call lnet_push_update_to_peers(). It'll + * get set to a specific NID, if we initiate discovery from the + * scratch + */ + lp->lp_disc_src_nid = LNET_NID_ANY; + if (rc) goto fail_unlink; @@ -3155,22 +3196,6 @@ static void lnet_peer_discovery_error(struct lnet_peer *lp, int error) } /* - * Mark the peer as discovered. - */ -static int lnet_peer_discovered(struct lnet_peer *lp) -__must_hold(&lp->lp_lock) -{ - lp->lp_state |= LNET_PEER_DISCOVERED; - lp->lp_state &= ~(LNET_PEER_DISCOVERING | - LNET_PEER_REDISCOVER); - - CDEBUG(D_NET, "peer %s\n", libcfs_nid2str(lp->lp_primary_nid)); - - return 0; -} - - -/* * Discovering this peer is taking too long. Cancel any Ping or Push * that discovery is waiting on by unlinking the relevant MDs. The * lnet_discovery_event_handler() will proceed from here and complete @@ -3219,7 +3244,8 @@ static int lnet_peer_discovery_wait_for_work(void) TASK_INTERRUPTIBLE); if (the_lnet.ln_dc_state == LNET_DC_STATE_STOPPING) break; - if (lnet_push_target_resize_needed()) + if (lnet_push_target_resize_needed() || + the_lnet.ln_push_target->pb_needs_post) break; if (!list_empty(&the_lnet.ln_dc_request)) break; @@ -3268,11 +3294,9 @@ static int lnet_peer_discovery_wait_for_work(void) static void lnet_resend_msgs(void) { struct lnet_msg *msg, *tmp; - struct list_head resend; + LIST_HEAD(resend); int rc; - INIT_LIST_HEAD(&resend); - spin_lock(&the_lnet.ln_msg_resend_lock); list_splice(&the_lnet.ln_msg_resend, &resend); spin_unlock(&the_lnet.ln_msg_resend_lock); @@ -3299,20 +3323,24 @@ static int lnet_peer_discovery(void *arg) wait_for_completion(&the_lnet.ln_started); CDEBUG(D_NET, "started\n"); - cfs_block_allsigs(); for (;;) { if (lnet_peer_discovery_wait_for_work()) break; - lnet_resend_msgs(); - if (lnet_push_target_resize_needed()) lnet_push_target_resize(); + else if (the_lnet.ln_push_target->pb_needs_post) + lnet_push_target_post(the_lnet.ln_push_target, + &the_lnet.ln_push_target_md); + + lnet_resend_msgs(); lnet_net_lock(LNET_LOCK_EX); - if (the_lnet.ln_dc_state == LNET_DC_STATE_STOPPING) + if (the_lnet.ln_dc_state == LNET_DC_STATE_STOPPING) { + lnet_net_unlock(LNET_LOCK_EX); break; + } /* * Process all incoming discovery work requests. When @@ -3336,6 +3364,12 @@ static int lnet_peer_discovery(void *arg) lp->lp_last_queued = ktime_get_real_seconds(); lnet_net_unlock(LNET_LOCK_EX); + if (lnet_push_target_resize_needed()) + lnet_push_target_resize(); + else if (the_lnet.ln_push_target->pb_needs_post) + lnet_push_target_post(the_lnet.ln_push_target, + &the_lnet.ln_push_target_md); + /* * Select an action depending on the state of * the peer and whether discovery is disabled. @@ -3380,6 +3414,50 @@ static int lnet_peer_discovery(void *arg) lnet_peer_discovery_complete(lp); if (the_lnet.ln_dc_state == LNET_DC_STATE_STOPPING) break; + + if (lp->lp_state & LNET_PEER_MARK_DELETION) { + struct list_head rlist; + struct lnet_route *route, *tmp; + int sensitivity = lp->lp_health_sensitivity; + + INIT_LIST_HEAD(&rlist); + + /* + * remove the peer from the discovery work + * queue if it's on there in preparation + * of deleting it. + */ + if (!list_empty(&lp->lp_dc_list)) + list_del(&lp->lp_dc_list); + + lnet_net_unlock(LNET_LOCK_EX); + + mutex_lock(&the_lnet.ln_api_mutex); + + lnet_net_lock(LNET_LOCK_EX); + list_for_each_entry_safe(route, tmp, + &lp->lp_routes, + lr_gwlist) + lnet_move_route(route, NULL, &rlist); + lnet_net_unlock(LNET_LOCK_EX); + + /* delete the peer */ + lnet_peer_del(lp); + + list_for_each_entry_safe(route, tmp, + &rlist, lr_list) { + /* re-add these routes */ + lnet_add_route(route->lr_net, + route->lr_hops, + route->lr_nid, + route->lr_priority, + sensitivity); + LIBCFS_FREE(route, sizeof(*route)); + } + mutex_unlock(&the_lnet.ln_api_mutex); + + lnet_net_lock(LNET_LOCK_EX); + } } lnet_net_unlock(LNET_LOCK_EX); @@ -3407,7 +3485,7 @@ static int lnet_peer_discovery(void *arg) /* Queue cleanup 2: wait for the expired queue to clear. */ while (!list_empty(&the_lnet.ln_dc_expired)) - schedule_timeout(cfs_time_seconds(1)); + schedule_timeout_uninterruptible(cfs_time_seconds(1)); /* Queue cleanup 3: clear the request queue. */ lnet_net_lock(LNET_LOCK_EX); @@ -3419,8 +3497,8 @@ static int lnet_peer_discovery(void *arg) } lnet_net_unlock(LNET_LOCK_EX); - LNetEQFree(the_lnet.ln_dc_eqh); - LNetInvalidateEQHandle(&the_lnet.ln_dc_eqh); + lnet_assert_handler_unused(the_lnet.ln_dc_handler); + the_lnet.ln_dc_handler = NULL; the_lnet.ln_dc_state = LNET_DC_STATE_SHUTDOWN; wake_up(&the_lnet.ln_dc_waitq); @@ -3434,25 +3512,19 @@ static int lnet_peer_discovery(void *arg) int lnet_peer_discovery_start(void) { struct task_struct *task; - int rc; + int rc = 0; if (the_lnet.ln_dc_state != LNET_DC_STATE_SHUTDOWN) return -EALREADY; - rc = LNetEQAlloc(0, lnet_discovery_event_handler, &the_lnet.ln_dc_eqh); - if (rc != 0) { - CERROR("Can't allocate discovery EQ: %d\n", rc); - return rc; - } - + the_lnet.ln_dc_handler = lnet_discovery_event_handler; the_lnet.ln_dc_state = LNET_DC_STATE_RUNNING; task = kthread_run(lnet_peer_discovery, NULL, "lnet_discovery"); if (IS_ERR(task)) { rc = PTR_ERR(task); CERROR("Can't start peer discovery thread: %d\n", rc); - LNetEQFree(the_lnet.ln_dc_eqh); - LNetInvalidateEQHandle(&the_lnet.ln_dc_eqh); + the_lnet.ln_dc_handler = NULL; the_lnet.ln_dc_state = LNET_DC_STATE_SHUTDOWN; } @@ -3719,7 +3791,7 @@ lnet_peer_ni_add_to_recoveryq_locked(struct lnet_peer_ni *lpni) if (list_empty(&lpni->lpni_recovery) && atomic_read(&lpni->lpni_healthv) < LNET_MAX_HEALTH_VALUE) { - CERROR("lpni %s added to recovery queue. Health = %d\n", + CDEBUG(D_NET, "lpni %s added to recovery queue. Health = %d\n", libcfs_nid2str(lpni->lpni_nid), atomic_read(&lpni->lpni_healthv)); list_add_tail(&lpni->lpni_recovery, &the_lnet.ln_mt_peerNIRecovq);