1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see
20 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
39 #define DEBUG_SUBSYSTEM S_LNET
41 #include <lnet/lib-lnet.h>
44 lnet_create_peer_table(void)
46 struct list_head *hash;
49 LASSERT (the_lnet.ln_peer_hash == NULL);
50 LIBCFS_ALLOC(hash, LNET_PEER_HASHSIZE * sizeof(struct list_head));
53 CERROR("Can't allocate peer hash table\n");
57 for (i = 0; i < LNET_PEER_HASHSIZE; i++)
58 CFS_INIT_LIST_HEAD(&hash[i]);
60 the_lnet.ln_peer_hash = hash;
65 lnet_destroy_peer_table(void)
69 if (the_lnet.ln_peer_hash == NULL)
72 for (i = 0; i < LNET_PEER_HASHSIZE; i++)
73 LASSERT (list_empty(&the_lnet.ln_peer_hash[i]));
75 LIBCFS_FREE(the_lnet.ln_peer_hash,
76 LNET_PEER_HASHSIZE * sizeof (struct list_head));
77 the_lnet.ln_peer_hash = NULL;
81 lnet_clear_peer_table(void)
85 LASSERT (the_lnet.ln_shutdown); /* i.e. no new peers */
87 for (i = 0; i < LNET_PEER_HASHSIZE; i++) {
88 struct list_head *peers = &the_lnet.ln_peer_hash[i];
91 while (!list_empty(peers)) {
92 lnet_peer_t *lp = list_entry(peers->next,
93 lnet_peer_t, lp_hashlist);
95 list_del(&lp->lp_hashlist);
96 lnet_peer_decref_locked(lp); /* lose hash table's ref */
102 for (i = 3; the_lnet.ln_npeers != 0;i++) {
105 if ((i & (i-1)) == 0)
106 CDEBUG(D_WARNING,"Waiting for %d peers\n",
108 cfs_pause(cfs_time_seconds(1));
116 lnet_destroy_peer_locked (lnet_peer_t *lp)
118 lnet_ni_decref_locked(lp->lp_ni);
121 LASSERT (lp->lp_refcount == 0);
122 LASSERT (lp->lp_rtr_refcount == 0);
123 LASSERT (list_empty(&lp->lp_txq));
124 LASSERT (lp->lp_txqnob == 0);
126 LIBCFS_FREE(lp, sizeof(*lp));
130 LASSERT(the_lnet.ln_npeers > 0);
131 the_lnet.ln_npeers--;
135 lnet_find_peer_locked (lnet_nid_t nid)
137 unsigned int idx = LNET_NIDADDR(nid) % LNET_PEER_HASHSIZE;
138 struct list_head *peers = &the_lnet.ln_peer_hash[idx];
139 struct list_head *tmp;
142 if (the_lnet.ln_shutdown)
145 list_for_each (tmp, peers) {
146 lp = list_entry(tmp, lnet_peer_t, lp_hashlist);
148 if (lp->lp_nid == nid) {
149 lnet_peer_addref_locked(lp);
158 lnet_nid2peer_locked(lnet_peer_t **lpp, lnet_nid_t nid)
163 lp = lnet_find_peer_locked(nid);
171 LIBCFS_ALLOC(lp, sizeof(*lp));
178 memset(lp, 0, sizeof(*lp)); /* zero counters etc */
180 CFS_INIT_LIST_HEAD(&lp->lp_txq);
181 CFS_INIT_LIST_HEAD(&lp->lp_rtrq);
184 lp->lp_notifylnd = 0;
185 lp->lp_notifying = 0;
186 lp->lp_alive_count = 0;
187 lp->lp_timestamp = 0;
188 lp->lp_alive = !lnet_peers_start_down(); /* 1 bit!! */
189 lp->lp_last_alive = cfs_time_current_sec(); /* assumes alive */
190 lp->lp_last_query = 0; /* didn't ask LND yet */
191 lp->lp_ping_timestamp = 0;
193 lp->lp_refcount = 2; /* 1 for caller; 1 for hash */
194 lp->lp_rtr_refcount = 0;
198 lp2 = lnet_find_peer_locked(nid);
201 LIBCFS_FREE(lp, sizeof(*lp));
204 if (the_lnet.ln_shutdown) {
205 lnet_peer_decref_locked(lp2);
214 lp->lp_ni = lnet_net2ni_locked(LNET_NIDNET(nid));
215 if (lp->lp_ni == NULL) {
217 LIBCFS_FREE(lp, sizeof(*lp));
221 return the_lnet.ln_shutdown ? -ESHUTDOWN : -EHOSTUNREACH;
225 lp->lp_mintxcredits = lp->lp_ni->ni_peertxcredits;
227 /* As a first approximation; allow this peer the same number of router
228 * buffers as it is allowed outstanding sends */
229 lp->lp_rtrcredits = lp->lp_minrtrcredits = lp->lp_txcredits;
231 LASSERT (!the_lnet.ln_shutdown);
232 /* can't add peers after shutdown starts */
234 list_add_tail(&lp->lp_hashlist, lnet_nid2peerhash(nid));
235 the_lnet.ln_npeers++;
236 the_lnet.ln_peertable_version++;
242 lnet_debug_peer(lnet_nid_t nid)
244 char *aliveness = "NA";
250 rc = lnet_nid2peer_locked(&lp, nid);
253 CDEBUG(D_WARNING, "No peer %s\n", libcfs_nid2str(nid));
257 if (lnet_isrouter(lp) || lp->lp_ni->ni_peertimeout > 0)
258 aliveness = lp->lp_alive ? "up" : "down";
260 CDEBUG(D_WARNING, "%-24s %4d %5s %5d %5d %5d %5d %5d %ld\n",
261 libcfs_nid2str(lp->lp_nid), lp->lp_refcount,
262 aliveness, lp->lp_ni->ni_peertxcredits,
263 lp->lp_rtrcredits, lp->lp_minrtrcredits,
264 lp->lp_txcredits, lp->lp_mintxcredits, lp->lp_txqnob);
266 lnet_peer_decref_locked(lp);