X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lnet%2Flnet%2Fpeer.c;h=33bd35144c6e6ad7d0b0eaa70216e06f8e938b6d;hb=ac201366ad5700edc860c139955af8a09bf53a1a;hp=8acde11ca9e79472dbaa3c478cabd5e349fcdb57;hpb=1f4e9f0f4f483dc93cbecdc841740bc11ec59a73;p=fs%2Flustre-release.git diff --git a/lnet/lnet/peer.c b/lnet/lnet/peer.c index 8acde11..33bd351 100644 --- a/lnet/lnet/peer.c +++ b/lnet/lnet/peer.c @@ -27,7 +27,6 @@ */ /* * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. * * lnet/lnet/peer.c */ @@ -264,6 +263,7 @@ lnet_peer_alloc(lnet_nid_t nid) spin_lock_init(&lp->lp_lock); lp->lp_primary_nid = nid; lp->lp_disc_src_nid = LNET_NID_ANY; + lp->lp_disc_dst_nid = LNET_NID_ANY; if (lnet_peers_start_down()) lp->lp_alive = false; else @@ -1328,6 +1328,51 @@ lnet_is_discovery_disabled(struct lnet_peer *lp) return rc; } +int +LNetAddPeer(lnet_nid_t *nids, __u32 num_nids) +{ + lnet_nid_t pnid = 0; + bool mr; + int i, rc; + + if (!nids || num_nids < 1) + return -EINVAL; + + rc = LNetNIInit(LNET_PID_ANY); + if (rc < 0) + return rc; + + mutex_lock(&the_lnet.ln_api_mutex); + + mr = lnet_peer_discovery_disabled == 0; + + rc = 0; + for (i = 0; i < num_nids; i++) { + if (nids[i] == LNET_NID_LO_0) + continue; + + if (!pnid) { + pnid = nids[i]; + rc = lnet_add_peer_ni(pnid, LNET_NID_ANY, mr, true); + } else if (lnet_peer_discovery_disabled) { + rc = lnet_add_peer_ni(nids[i], LNET_NID_ANY, mr, true); + } else { + rc = lnet_add_peer_ni(pnid, nids[i], mr, true); + } + + if (rc && rc != -EEXIST) + goto unlock; + } + +unlock: + mutex_unlock(&the_lnet.ln_api_mutex); + + LNetNIFini(); + + return rc == -EEXIST ? 0 : rc; +} +EXPORT_SYMBOL(LNetAddPeer); + lnet_nid_t LNetPrimaryNID(lnet_nid_t nid) { @@ -1348,7 +1393,13 @@ LNetPrimaryNID(lnet_nid_t nid) } lp = lpni->lpni_peer_net->lpn_peer; - while (!lnet_peer_is_uptodate(lp)) { + /* If discovery is disabled locally then we needn't bother running + * discovery here because discovery will not modify whatever + * primary NID is currently set for this peer. If the specified peer is + * down then this discovery can introduce long delays into the mount + * process, so skip it if it isn't necessary. + */ + while (!lnet_peer_discovery_disabled && !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; @@ -1369,7 +1420,11 @@ LNetPrimaryNID(lnet_nid_t nid) } lp = lpni->lpni_peer_net->lpn_peer; - /* Only try once if discovery is disabled */ + /* If we find that the peer has discovery disabled then we will + * not modify whatever primary NID is currently set for this + * peer. Thus, we can break out of this loop even if the peer + * is not fully up to date. + */ if (lnet_is_discovery_disabled(lp)) break; } @@ -1439,7 +1494,10 @@ 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); + if (lp->lp_primary_nid == lpni->lpni_nid) + list_add(&lpni->lpni_peer_nis, &lpn->lpn_peer_nis); + else + list_add_tail(&lpni->lpni_peer_nis, &lpn->lpn_peer_nis); lnet_update_peer_net_healthv(lpni); lnet_peer_net_addref_locked(lpn); @@ -1447,7 +1505,10 @@ lnet_peer_attach_peer_ni(struct lnet_peer *lp, if (!lpn->lpn_peer) { new_lpn = true; lpn->lpn_peer = lp; - list_add_tail(&lpn->lpn_peer_nets, &lp->lp_peer_nets); + if (lp->lp_primary_nid == lpni->lpni_nid) + list_add(&lpn->lpn_peer_nets, &lp->lp_peer_nets); + else + list_add_tail(&lpn->lpn_peer_nets, &lp->lp_peer_nets); lnet_peer_addref_locked(lp); } @@ -1532,6 +1593,11 @@ lnet_peer_add(lnet_nid_t nid, unsigned flags) else if ((lp->lp_state ^ flags) & LNET_PEER_MULTI_RAIL) rc = -EPERM; goto out; + } else if (!(flags & LNET_PEER_CONFIGURED)) { + if (lp->lp_primary_nid == nid) { + rc = -EEXIST; + goto out; + } } /* Delete and recreate as a configured peer. */ lnet_peer_del(lp); @@ -1688,10 +1754,14 @@ lnet_peer_set_primary_nid(struct lnet_peer *lp, lnet_nid_t nid, unsigned flags) if (lp->lp_primary_nid == nid) goto out; + + lp->lp_primary_nid = nid; + rc = lnet_peer_add_nid(lp, nid, flags); - if (rc) + if (rc) { + lp->lp_primary_nid = old; goto out; - lp->lp_primary_nid = nid; + } out: CDEBUG(D_NET, "peer %s NID %s: %d\n", libcfs_nid2str(old), libcfs_nid2str(nid), rc); @@ -1766,17 +1836,19 @@ out: * being created/modified/deleted by a different thread. */ int -lnet_add_peer_ni(lnet_nid_t prim_nid, lnet_nid_t nid, bool mr) +lnet_add_peer_ni(lnet_nid_t prim_nid, lnet_nid_t nid, bool mr, bool temp) { struct lnet_peer *lp = NULL; struct lnet_peer_ni *lpni; - unsigned flags; + unsigned int flags = 0; /* The prim_nid must always be specified */ if (prim_nid == LNET_NID_ANY) return -EINVAL; - flags = LNET_PEER_CONFIGURED; + if (!temp) + flags = LNET_PEER_CONFIGURED; + if (mr) flags |= LNET_PEER_MULTI_RAIL; @@ -1795,7 +1867,7 @@ lnet_add_peer_ni(lnet_nid_t prim_nid, lnet_nid_t nid, bool mr) lp = lpni->lpni_peer_net->lpn_peer; /* Peer must have been configured. */ - if (!(lp->lp_state & LNET_PEER_CONFIGURED)) { + if (!temp && !(lp->lp_state & LNET_PEER_CONFIGURED)) { CDEBUG(D_NET, "peer %s was not configured\n", libcfs_nid2str(prim_nid)); return -ENOENT; @@ -2512,6 +2584,7 @@ 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; + lp->lp_disc_dst_nid = ev->source.nid; /* * If some kind of error happened the contents of message @@ -2544,20 +2617,41 @@ lnet_discovery_event_reply(struct lnet_peer *lp, struct lnet_event *ev) goto out; } - /* * The peer may have discovery disabled at its end. Set * NO_DISCOVERY as appropriate. */ - if ((pbuf->pb_info.pi_features & LNET_PING_FEAT_DISCOVERY) && - !lnet_peer_discovery_disabled) { - CDEBUG(D_NET, "Peer %s has discovery enabled\n", - libcfs_nid2str(lp->lp_primary_nid)); - lp->lp_state &= ~LNET_PEER_NO_DISCOVERY; - } else { + if (!(pbuf->pb_info.pi_features & LNET_PING_FEAT_DISCOVERY) || + lnet_peer_discovery_disabled) { CDEBUG(D_NET, "Peer %s has discovery disabled\n", libcfs_nid2str(lp->lp_primary_nid)); + + /* Detect whether this peer has toggled discovery from on to + * off and whether we can delete and re-create the peer. Peers + * that were manually configured cannot be deleted by discovery. + * We need to delete this peer and re-create it if the peer was + * not configured manually, is currently considered DD capable, + * and either: + * 1. We've already discovered the peer (the peer has toggled + * the discovery feature from on to off), or + * 2. The peer is considered MR, but it was not user configured + * (this was a "temporary" peer created via the kernel APIs + * that we're discovering for the first time) + */ + if (!(lp->lp_state & (LNET_PEER_CONFIGURED | + LNET_PEER_NO_DISCOVERY)) && + (lp->lp_state & (LNET_PEER_DISCOVERED | + LNET_PEER_MULTI_RAIL))) { + 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 { + CDEBUG(D_NET, "Peer %s has discovery enabled\n", + libcfs_nid2str(lp->lp_primary_nid)); + lp->lp_state &= ~LNET_PEER_NO_DISCOVERY; } /* @@ -2765,7 +2859,8 @@ static void lnet_discovery_event_handler(struct lnet_event *event) /* put peer back at end of request queue, if discovery not already * done */ - if (rc == LNET_REDISCOVER_PEER && !lnet_peer_is_uptodate(lp)) { + if (rc == LNET_REDISCOVER_PEER && !lnet_peer_is_uptodate(lp) && + lnet_peer_queue_for_discovery(lp)) { list_move_tail(&lp->lp_dc_list, &the_lnet.ln_dc_request); wake_up(&the_lnet.ln_dc_waitq); } @@ -2793,6 +2888,7 @@ static void lnet_discovery_event_handler(struct lnet_event *event) static int lnet_peer_merge_data(struct lnet_peer *lp, struct lnet_ping_buffer *pbuf) { + struct lnet_peer_net *lpn; struct lnet_peer_ni *lpni; lnet_nid_t *curnis = NULL; struct lnet_ni_status *addnis = NULL; @@ -2921,6 +3017,28 @@ static int lnet_peer_merge_data(struct lnet_peer *lp, goto out; } } + + /* The peer net for the primary NID should be the first entry in the + * peer's lp_peer_nets list, and the peer NI for the primary NID should + * be the first entry in its peer net's lpn_peer_nis list. + */ + lpni = lnet_find_peer_ni_locked(pbuf->pb_info.pi_ni[1].ns_nid); + if (!lpni) { + CERROR("Internal error: Failed to lookup peer NI for primary NID: %s\n", + libcfs_nid2str(pbuf->pb_info.pi_ni[1].ns_nid)); + goto out; + } + + lnet_peer_ni_decref_locked(lpni); + + lpn = lpni->lpni_peer_net; + if (lpn->lpn_peer_nets.prev != &lp->lp_peer_nets) + list_move(&lpn->lpn_peer_nets, &lp->lp_peer_nets); + + if (lpni->lpni_peer_nis.prev != &lpni->lpni_peer_net->lpn_peer_nis) + list_move(&lpni->lpni_peer_nis, + &lpni->lpni_peer_net->lpn_peer_nis); + /* * Errors other than -ENOMEM are due to peers having been * configured with DLC. Ignore these because DLC overrides @@ -3055,7 +3173,7 @@ __must_hold(&lp->lp_lock) * of deleting it. */ if (!list_empty(&lp->lp_dc_list)) - list_del(&lp->lp_dc_list); + list_del_init(&lp->lp_dc_list); list_for_each_entry_safe(route, tmp, &lp->lp_routes, lr_gwlist) @@ -3195,8 +3313,10 @@ __must_hold(&lp->lp_lock) * received by lp, we need to set the discovery source * NID for new_lp to the NID stored in lp. */ - if (lp->lp_disc_src_nid != LNET_NID_ANY) + if (lp->lp_disc_src_nid != LNET_NID_ANY) { new_lp->lp_disc_src_nid = lp->lp_disc_src_nid; + new_lp->lp_disc_dst_nid = lp->lp_disc_dst_nid; + } spin_unlock(&new_lp->lp_lock); spin_unlock(&lp->lp_lock); @@ -3246,41 +3366,10 @@ __must_hold(&lp->lp_lock) return rc ? rc : LNET_REDISCOVER_PEER; } -/* - * Select NID to send a Ping or Push to. - */ -static lnet_nid_t lnet_peer_select_nid(struct lnet_peer *lp) -{ - struct lnet_peer_ni *lpni; - - /* Look for a direct-connected NID for this peer. */ - lpni = NULL; - while ((lpni = lnet_get_next_peer_ni_locked(lp, NULL, lpni)) != NULL) { - if (!lnet_get_net_locked(lpni->lpni_peer_net->lpn_net_id)) - continue; - break; - } - if (lpni) - return lpni->lpni_nid; - - /* Look for a routed-connected NID for this peer. */ - lpni = NULL; - while ((lpni = lnet_get_next_peer_ni_locked(lp, NULL, lpni)) != NULL) { - if (!lnet_find_rnet_locked(lpni->lpni_peer_net->lpn_net_id)) - continue; - break; - } - if (lpni) - return lpni->lpni_nid; - - return LNET_NID_ANY; -} - /* Active side of ping. */ static int lnet_peer_send_ping(struct lnet_peer *lp) __must_hold(&lp->lp_lock) { - lnet_nid_t pnid; int nnis; int rc; int cpt; @@ -3292,12 +3381,11 @@ __must_hold(&lp->lp_lock) cpt = lnet_net_lock_current(); /* Refcount for MD. */ lnet_peer_addref_locked(lp); - pnid = lnet_peer_select_nid(lp); lnet_net_unlock(cpt); nnis = max(lp->lp_data_nnis, LNET_INTERFACES_MIN); - rc = lnet_send_ping(pnid, &lp->lp_ping_mdh, nnis, lp, + rc = lnet_send_ping(lp->lp_primary_nid, &lp->lp_ping_mdh, nnis, lp, the_lnet.ln_dc_handler, false); /* @@ -3422,18 +3510,17 @@ __must_hold(&lp->lp_lock) CERROR("Can't bind push source MD: %d\n", rc); goto fail_error; } + cpt = lnet_net_lock_current(); /* Refcount for MD. */ lnet_peer_addref_locked(lp); id.pid = LNET_PID_LUSTRE; - id.nid = lnet_peer_select_nid(lp); + if (lp->lp_disc_dst_nid != LNET_NID_ANY) + id.nid = lp->lp_disc_dst_nid; + else + id.nid = lp->lp_primary_nid; lnet_net_unlock(cpt); - if (id.nid == LNET_NID_ANY) { - rc = -EHOSTUNREACH; - goto fail_unlink; - } - rc = LNetPut(lp->lp_disc_src_nid, lp->lp_push_mdh, LNET_ACK_REQ, id, LNET_RESERVED_PORTAL, LNET_PROTO_PING_MATCHBITS, 0, 0); @@ -3445,6 +3532,7 @@ __must_hold(&lp->lp_lock) * scratch */ lp->lp_disc_src_nid = LNET_NID_ANY; + lp->lp_disc_dst_nid = LNET_NID_ANY; if (rc) goto fail_unlink; @@ -3983,6 +4071,8 @@ int lnet_get_peer_info(struct lnet_ioctl_peer_cfg *cfg, void __user *bulk) atomic_read(&lpni->lpni_hstats.hlt_remote_error); lpni_hstats->hlpni_health_value = atomic_read(&lpni->lpni_healthv); + lpni_hstats->hlpni_ping_count = lpni->lpni_ping_count; + lpni_hstats->hlpni_next_ping = lpni->lpni_next_ping; if (copy_to_user(bulk, lpni_hstats, sizeof(*lpni_hstats))) goto out_free_hstats; bulk += sizeof(*lpni_hstats); @@ -4027,7 +4117,8 @@ lnet_peer_ni_add_to_recoveryq_locked(struct lnet_peer_ni *lpni, return; } - if (now > lpni->lpni_last_alive + lnet_recovery_limit) { + if (lnet_recovery_limit && + now > lpni->lpni_last_alive + lnet_recovery_limit) { CDEBUG(D_NET, "lpni %s aged out last alive %lld\n", libcfs_nid2str(lpni->lpni_nid), lpni->lpni_last_alive); @@ -4077,7 +4168,7 @@ lnet_peer_ni_set_healthv(lnet_nid_t nid, int value, bool all) lnet_net_unlock(LNET_LOCK_EX); return; } - atomic_set(&lpni->lpni_healthv, value); + lnet_set_lpni_healthv_locked(lpni, value); lnet_peer_ni_add_to_recoveryq_locked(lpni, &the_lnet.ln_mt_peerNIRecovq, now); lnet_peer_ni_decref_locked(lpni); @@ -4098,7 +4189,8 @@ lnet_peer_ni_set_healthv(lnet_nid_t nid, int value, bool all) list_for_each_entry(lpn, &lp->lp_peer_nets, lpn_peer_nets) { list_for_each_entry(lpni, &lpn->lpn_peer_nis, lpni_peer_nis) { - atomic_set(&lpni->lpni_healthv, value); + lnet_set_lpni_healthv_locked(lpni, + value); lnet_peer_ni_add_to_recoveryq_locked(lpni, &the_lnet.ln_mt_peerNIRecovq, now); }