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);
125 LASSERT (lp->lp_rcd == NULL);
127 LIBCFS_FREE(lp, sizeof(*lp));
131 LASSERT(the_lnet.ln_npeers > 0);
132 the_lnet.ln_npeers--;
136 lnet_find_peer_locked (lnet_nid_t nid)
138 unsigned int idx = LNET_NIDADDR(nid) % LNET_PEER_HASHSIZE;
139 struct list_head *peers = &the_lnet.ln_peer_hash[idx];
140 struct list_head *tmp;
143 if (the_lnet.ln_shutdown)
146 list_for_each (tmp, peers) {
147 lp = list_entry(tmp, lnet_peer_t, lp_hashlist);
149 if (lp->lp_nid == nid) {
150 lnet_peer_addref_locked(lp);
159 lnet_nid2peer_locked(lnet_peer_t **lpp, lnet_nid_t nid)
164 lp = lnet_find_peer_locked(nid);
172 LIBCFS_ALLOC(lp, sizeof(*lp));
179 memset(lp, 0, sizeof(*lp)); /* zero counters etc */
181 CFS_INIT_LIST_HEAD(&lp->lp_txq);
182 CFS_INIT_LIST_HEAD(&lp->lp_rtrq);
185 lp->lp_notifylnd = 0;
186 lp->lp_notifying = 0;
187 lp->lp_alive_count = 0;
188 lp->lp_timestamp = 0;
189 lp->lp_alive = !lnet_peers_start_down(); /* 1 bit!! */
190 lp->lp_last_alive = cfs_time_current(); /* assumes alive */
191 lp->lp_last_query = 0; /* haven't asked NI yet */
192 lp->lp_ping_timestamp = 0;
194 lp->lp_refcount = 2; /* 1 for caller; 1 for hash */
195 lp->lp_rtr_refcount = 0;
199 lp2 = lnet_find_peer_locked(nid);
202 LIBCFS_FREE(lp, sizeof(*lp));
205 if (the_lnet.ln_shutdown) {
206 lnet_peer_decref_locked(lp2);
215 lp->lp_ni = lnet_net2ni_locked(LNET_NIDNET(nid));
216 if (lp->lp_ni == NULL) {
218 LIBCFS_FREE(lp, sizeof(*lp));
222 return the_lnet.ln_shutdown ? -ESHUTDOWN : -EHOSTUNREACH;
226 lp->lp_mintxcredits = lp->lp_ni->ni_peertxcredits;
228 lp->lp_minrtrcredits = lnet_peer_buffer_credits(lp->lp_ni);
230 /* can't add peers after shutdown starts */
231 LASSERT (!the_lnet.ln_shutdown);
233 list_add_tail(&lp->lp_hashlist, lnet_nid2peerhash(nid));
234 the_lnet.ln_npeers++;
235 the_lnet.ln_peertable_version++;
241 lnet_debug_peer(lnet_nid_t nid)
243 char *aliveness = "NA";
249 rc = lnet_nid2peer_locked(&lp, nid);
252 CDEBUG(D_WARNING, "No peer %s\n", libcfs_nid2str(nid));
256 if (lnet_isrouter(lp) || lnet_peer_aliveness_enabled(lp))
257 aliveness = lp->lp_alive ? "up" : "down";
259 CDEBUG(D_WARNING, "%-24s %4d %5s %5d %5d %5d %5d %5d %ld\n",
260 libcfs_nid2str(lp->lp_nid), lp->lp_refcount,
261 aliveness, lp->lp_ni->ni_peertxcredits,
262 lp->lp_rtrcredits, lp->lp_minrtrcredits,
263 lp->lp_txcredits, lp->lp_mintxcredits, lp->lp_txqnob);
265 lnet_peer_decref_locked(lp);