Whamcloud - gitweb
LU-709 build: Remove last bit of HAVE_GFP_T
[fs/lustre-release.git] / lnet / lnet / peer.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
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.
11  *
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).
17  *
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
21  *
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
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lnet/lnet/peer.c
37  */
38
39 #define DEBUG_SUBSYSTEM S_LNET
40
41 #include <lnet/lib-lnet.h>
42
43 int
44 lnet_create_peer_table(void)
45 {
46         cfs_list_t  *hash;
47         int          i;
48
49         LASSERT (the_lnet.ln_peer_hash == NULL);
50         LIBCFS_ALLOC(hash, LNET_PEER_HASHSIZE * sizeof(cfs_list_t));
51         
52         if (hash == NULL) {
53                 CERROR("Can't allocate peer hash table\n");
54                 return -ENOMEM;
55         }
56
57         for (i = 0; i < LNET_PEER_HASHSIZE; i++)
58                 CFS_INIT_LIST_HEAD(&hash[i]);
59
60         the_lnet.ln_peer_hash = hash;
61         return 0;
62 }
63
64 void
65 lnet_destroy_peer_table(void)
66 {
67         int         i;
68
69         if (the_lnet.ln_peer_hash == NULL)
70                 return;
71
72         for (i = 0; i < LNET_PEER_HASHSIZE; i++)
73                 LASSERT (cfs_list_empty(&the_lnet.ln_peer_hash[i]));
74
75         LIBCFS_FREE(the_lnet.ln_peer_hash,
76                     LNET_PEER_HASHSIZE * sizeof (cfs_list_t));
77         the_lnet.ln_peer_hash = NULL;
78 }
79
80 void
81 lnet_clear_peer_table(void)
82 {
83         int         i;
84
85         LASSERT (the_lnet.ln_shutdown);         /* i.e. no new peers */
86
87         for (i = 0; i < LNET_PEER_HASHSIZE; i++) {
88                 cfs_list_t *peers = &the_lnet.ln_peer_hash[i];
89
90                 LNET_LOCK();
91                 while (!cfs_list_empty(peers)) {
92                         lnet_peer_t *lp = cfs_list_entry(peers->next,
93                                                          lnet_peer_t,
94                                                          lp_hashlist);
95
96                         cfs_list_del(&lp->lp_hashlist);
97                         lnet_peer_decref_locked(lp);   /* lose hash table's ref */
98                 }
99                 LNET_UNLOCK();
100         }
101
102         LNET_LOCK();
103         for (i = 3; the_lnet.ln_npeers != 0;i++) {
104                 LNET_UNLOCK();
105
106                 if ((i & (i-1)) == 0)
107                         CDEBUG(D_WARNING,"Waiting for %d peers\n", 
108                                the_lnet.ln_npeers);
109                 cfs_pause(cfs_time_seconds(1));
110
111                 LNET_LOCK();
112         }
113         LNET_UNLOCK();
114 }
115
116 void
117 lnet_destroy_peer_locked (lnet_peer_t *lp) 
118 {
119         lnet_ni_decref_locked(lp->lp_ni);
120         LNET_UNLOCK();
121
122         LASSERT (lp->lp_refcount == 0);
123         LASSERT (lp->lp_rtr_refcount == 0);
124         LASSERT (cfs_list_empty(&lp->lp_txq));
125         LASSERT (lp->lp_txqnob == 0);
126         LASSERT (lp->lp_rcd == NULL);
127
128         LIBCFS_FREE(lp, sizeof(*lp));
129
130         LNET_LOCK();
131
132         LASSERT(the_lnet.ln_npeers > 0);
133         the_lnet.ln_npeers--;
134 }
135
136 lnet_peer_t *
137 lnet_find_peer_locked (lnet_nid_t nid)
138 {
139         unsigned int      idx = LNET_NIDADDR(nid) % LNET_PEER_HASHSIZE;
140         cfs_list_t       *peers = &the_lnet.ln_peer_hash[idx];
141         cfs_list_t       *tmp;
142         lnet_peer_t      *lp;
143
144         if (the_lnet.ln_shutdown)
145                 return NULL;
146
147         cfs_list_for_each (tmp, peers) {
148                 lp = cfs_list_entry(tmp, lnet_peer_t, lp_hashlist);
149
150                 if (lp->lp_nid == nid) {
151                         lnet_peer_addref_locked(lp);
152                         return lp;
153                 }
154         }
155
156         return NULL;
157 }
158
159 int
160 lnet_nid2peer_locked(lnet_peer_t **lpp, lnet_nid_t nid)
161 {
162         lnet_peer_t    *lp;
163         lnet_peer_t    *lp2;
164
165         lp = lnet_find_peer_locked(nid);
166         if (lp != NULL) {
167                 *lpp = lp;
168                 return 0;
169         }
170         
171         LNET_UNLOCK();
172         
173         LIBCFS_ALLOC(lp, sizeof(*lp));
174         if (lp == NULL) {
175                 *lpp = NULL;
176                 LNET_LOCK();
177                 return -ENOMEM;
178         }
179
180         memset(lp, 0, sizeof(*lp));             /* zero counters etc */
181         
182         CFS_INIT_LIST_HEAD(&lp->lp_txq);
183         CFS_INIT_LIST_HEAD(&lp->lp_rtrq);
184         
185         lp->lp_notify = 0;
186         lp->lp_notifylnd = 0;
187         lp->lp_notifying = 0;
188         lp->lp_alive_count = 0;
189         lp->lp_timestamp = 0;
190         lp->lp_alive = !lnet_peers_start_down(); /* 1 bit!! */
191         lp->lp_last_alive = cfs_time_current(); /* assumes alive */
192         lp->lp_last_query = 0; /* haven't asked NI yet */
193         lp->lp_ping_timestamp = 0;
194         lp->lp_nid = nid;
195         lp->lp_refcount = 2;                    /* 1 for caller; 1 for hash */
196         lp->lp_rtr_refcount = 0;
197
198         LNET_LOCK();
199
200         lp2 = lnet_find_peer_locked(nid);
201         if (lp2 != NULL) {
202                 LNET_UNLOCK();
203                 LIBCFS_FREE(lp, sizeof(*lp));
204                 LNET_LOCK();
205
206                 if (the_lnet.ln_shutdown) {
207                         lnet_peer_decref_locked(lp2);
208                         *lpp = NULL;
209                         return -ESHUTDOWN;
210                 }
211
212                 *lpp = lp2;
213                 return 0;
214         }
215                 
216         lp->lp_ni = lnet_net2ni_locked(LNET_NIDNET(nid));
217         if (lp->lp_ni == NULL) {
218                 LNET_UNLOCK();
219                 LIBCFS_FREE(lp, sizeof(*lp));
220                 LNET_LOCK();
221
222                 *lpp = NULL;
223                 return the_lnet.ln_shutdown ? -ESHUTDOWN : -EHOSTUNREACH;
224         }
225
226         lp->lp_txcredits    =
227         lp->lp_mintxcredits = lp->lp_ni->ni_peertxcredits;
228         lp->lp_rtrcredits    =
229         lp->lp_minrtrcredits = lnet_peer_buffer_credits(lp->lp_ni);
230
231         /* can't add peers after shutdown starts */
232         LASSERT (!the_lnet.ln_shutdown);
233
234         cfs_list_add_tail(&lp->lp_hashlist, lnet_nid2peerhash(nid));
235         the_lnet.ln_npeers++;
236         the_lnet.ln_peertable_version++;
237         *lpp = lp;
238         return 0;
239 }
240
241 void
242 lnet_debug_peer(lnet_nid_t nid)
243 {
244         char        *aliveness = "NA";
245         int          rc;
246         lnet_peer_t *lp;
247
248         LNET_LOCK();
249
250         rc = lnet_nid2peer_locked(&lp, nid);
251         if (rc != 0) {
252                 LNET_UNLOCK();
253                 CDEBUG(D_WARNING, "No peer %s\n", libcfs_nid2str(nid));
254                 return;
255         }
256
257         if (lnet_isrouter(lp) || lnet_peer_aliveness_enabled(lp))
258                 aliveness = lp->lp_alive ? "up" : "down";
259
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);
265
266         lnet_peer_decref_locked(lp);
267
268         LNET_UNLOCK();
269 }