Whamcloud - gitweb
LU-1406 ofd: init lu_target in OFD
[fs/lustre-release.git] / lnet / lnet / peer.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  */
30 /*
31  * This file is part of Lustre, http://www.lustre.org/
32  * Lustre is a trademark of Sun Microsystems, Inc.
33  *
34  * lnet/lnet/peer.c
35  */
36
37 #define DEBUG_SUBSYSTEM S_LNET
38
39 #include <lnet/lib-lnet.h>
40
41 int
42 lnet_create_peer_table(void)
43 {
44         cfs_list_t  *hash;
45         int          i;
46
47         LASSERT (the_lnet.ln_peer_hash == NULL);
48         LIBCFS_ALLOC(hash, LNET_PEER_HASHSIZE * sizeof(cfs_list_t));
49         
50         if (hash == NULL) {
51                 CERROR("Can't allocate peer hash table\n");
52                 return -ENOMEM;
53         }
54
55         for (i = 0; i < LNET_PEER_HASHSIZE; i++)
56                 CFS_INIT_LIST_HEAD(&hash[i]);
57
58         the_lnet.ln_peer_hash = hash;
59         return 0;
60 }
61
62 void
63 lnet_destroy_peer_table(void)
64 {
65         int         i;
66
67         if (the_lnet.ln_peer_hash == NULL)
68                 return;
69
70         for (i = 0; i < LNET_PEER_HASHSIZE; i++)
71                 LASSERT (cfs_list_empty(&the_lnet.ln_peer_hash[i]));
72
73         LIBCFS_FREE(the_lnet.ln_peer_hash,
74                     LNET_PEER_HASHSIZE * sizeof (cfs_list_t));
75         the_lnet.ln_peer_hash = NULL;
76 }
77
78 void
79 lnet_clear_peer_table(void)
80 {
81         int         i;
82
83         LASSERT (the_lnet.ln_shutdown);         /* i.e. no new peers */
84
85         for (i = 0; i < LNET_PEER_HASHSIZE; i++) {
86                 cfs_list_t *peers = &the_lnet.ln_peer_hash[i];
87
88                 LNET_LOCK();
89                 while (!cfs_list_empty(peers)) {
90                         lnet_peer_t *lp = cfs_list_entry(peers->next,
91                                                          lnet_peer_t,
92                                                          lp_hashlist);
93
94                         cfs_list_del(&lp->lp_hashlist);
95                         lnet_peer_decref_locked(lp);   /* lose hash table's ref */
96                 }
97                 LNET_UNLOCK();
98         }
99
100         LNET_LOCK();
101         for (i = 3; the_lnet.ln_npeers != 0;i++) {
102                 LNET_UNLOCK();
103
104                 if ((i & (i-1)) == 0)
105                         CDEBUG(D_WARNING,"Waiting for %d peers\n", 
106                                the_lnet.ln_npeers);
107                 cfs_pause(cfs_time_seconds(1));
108
109                 LNET_LOCK();
110         }
111         LNET_UNLOCK();
112 }
113
114 void
115 lnet_destroy_peer_locked (lnet_peer_t *lp) 
116 {
117         lnet_ni_decref_locked(lp->lp_ni);
118         LNET_UNLOCK();
119
120         LASSERT (lp->lp_refcount == 0);
121         LASSERT (lp->lp_rtr_refcount == 0);
122         LASSERT (cfs_list_empty(&lp->lp_txq));
123         LASSERT (lp->lp_txqnob == 0);
124         LASSERT (lp->lp_rcd == NULL);
125
126         LIBCFS_FREE(lp, sizeof(*lp));
127
128         LNET_LOCK();
129
130         LASSERT(the_lnet.ln_npeers > 0);
131         the_lnet.ln_npeers--;
132 }
133
134 lnet_peer_t *
135 lnet_find_peer_locked (lnet_nid_t nid)
136 {
137         unsigned int      idx = LNET_NIDADDR(nid) % LNET_PEER_HASHSIZE;
138         cfs_list_t       *peers = &the_lnet.ln_peer_hash[idx];
139         cfs_list_t       *tmp;
140         lnet_peer_t      *lp;
141
142         if (the_lnet.ln_shutdown)
143                 return NULL;
144
145         cfs_list_for_each (tmp, peers) {
146                 lp = cfs_list_entry(tmp, lnet_peer_t, lp_hashlist);
147
148                 if (lp->lp_nid == nid) {
149                         lnet_peer_addref_locked(lp);
150                         return lp;
151                 }
152         }
153
154         return NULL;
155 }
156
157 int
158 lnet_nid2peer_locked(lnet_peer_t **lpp, lnet_nid_t nid)
159 {
160         lnet_peer_t    *lp;
161         lnet_peer_t    *lp2;
162
163         lp = lnet_find_peer_locked(nid);
164         if (lp != NULL) {
165                 *lpp = lp;
166                 return 0;
167         }
168         
169         LNET_UNLOCK();
170         
171         LIBCFS_ALLOC(lp, sizeof(*lp));
172         if (lp == NULL) {
173                 *lpp = NULL;
174                 LNET_LOCK();
175                 return -ENOMEM;
176         }
177
178         memset(lp, 0, sizeof(*lp));             /* zero counters etc */
179         
180         CFS_INIT_LIST_HEAD(&lp->lp_txq);
181         CFS_INIT_LIST_HEAD(&lp->lp_rtrq);
182         
183         lp->lp_notify = 0;
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(); /* assumes alive */
190         lp->lp_last_query = 0; /* haven't asked NI yet */
191         lp->lp_ping_timestamp = 0;
192         lp->lp_nid = nid;
193         lp->lp_refcount = 2;                    /* 1 for caller; 1 for hash */
194         lp->lp_rtr_refcount = 0;
195
196         LNET_LOCK();
197
198         lp2 = lnet_find_peer_locked(nid);
199         if (lp2 != NULL) {
200                 LNET_UNLOCK();
201                 LIBCFS_FREE(lp, sizeof(*lp));
202                 LNET_LOCK();
203
204                 if (the_lnet.ln_shutdown) {
205                         lnet_peer_decref_locked(lp2);
206                         *lpp = NULL;
207                         return -ESHUTDOWN;
208                 }
209
210                 *lpp = lp2;
211                 return 0;
212         }
213                 
214         lp->lp_ni = lnet_net2ni_locked(LNET_NIDNET(nid));
215         if (lp->lp_ni == NULL) {
216                 LNET_UNLOCK();
217                 LIBCFS_FREE(lp, sizeof(*lp));
218                 LNET_LOCK();
219
220                 *lpp = NULL;
221                 return the_lnet.ln_shutdown ? -ESHUTDOWN : -EHOSTUNREACH;
222         }
223
224         lp->lp_txcredits    =
225         lp->lp_mintxcredits = lp->lp_ni->ni_peertxcredits;
226         lp->lp_rtrcredits    =
227         lp->lp_minrtrcredits = lnet_peer_buffer_credits(lp->lp_ni);
228
229         /* can't add peers after shutdown starts */
230         LASSERT (!the_lnet.ln_shutdown);
231
232         cfs_list_add_tail(&lp->lp_hashlist, lnet_nid2peerhash(nid));
233         the_lnet.ln_npeers++;
234         the_lnet.ln_peertable_version++;
235         *lpp = lp;
236         return 0;
237 }
238
239 void
240 lnet_debug_peer(lnet_nid_t nid)
241 {
242         char        *aliveness = "NA";
243         int          rc;
244         lnet_peer_t *lp;
245
246         LNET_LOCK();
247
248         rc = lnet_nid2peer_locked(&lp, nid);
249         if (rc != 0) {
250                 LNET_UNLOCK();
251                 CDEBUG(D_WARNING, "No peer %s\n", libcfs_nid2str(nid));
252                 return;
253         }
254
255         if (lnet_isrouter(lp) || lnet_peer_aliveness_enabled(lp))
256                 aliveness = lp->lp_alive ? "up" : "down";
257
258         CDEBUG(D_WARNING, "%-24s %4d %5s %5d %5d %5d %5d %5d %ld\n",
259                libcfs_nid2str(lp->lp_nid), lp->lp_refcount,
260                aliveness, lp->lp_ni->ni_peertxcredits,
261                lp->lp_rtrcredits, lp->lp_minrtrcredits,
262                lp->lp_txcredits, lp->lp_mintxcredits, lp->lp_txqnob);
263
264         lnet_peer_decref_locked(lp);
265
266         LNET_UNLOCK();
267 }