staging:lustre: separate kernel and user land defines in the LNet headers
[deliverable/linux.git] / drivers / staging / lustre / lnet / lnet / api-ni.c
CommitLineData
d7e09d03
PT
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) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
29 *
30 * Copyright (c) 2011, 2012, Intel Corporation.
31 */
32/*
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
35 */
36
37#define DEBUG_SUBSYSTEM S_LNET
d7e09d03 38#include <linux/log2.h>
9056be30 39#include <linux/ktime.h>
d7e09d03 40
db18b8e9
JS
41#include "../../include/linux/lnet/lib-lnet.h"
42
d7e09d03
PT
43#define D_LNI D_CONSOLE
44
7e7ab095 45lnet_t the_lnet; /* THE state of the network */
d7e09d03
PT
46EXPORT_SYMBOL(the_lnet);
47
48
49static char *ip2nets = "";
8cc7b4b9
PT
50module_param(ip2nets, charp, 0444);
51MODULE_PARM_DESC(ip2nets, "LNET network <- IP table");
d7e09d03
PT
52
53static char *networks = "";
8cc7b4b9
PT
54module_param(networks, charp, 0444);
55MODULE_PARM_DESC(networks, "local networks");
d7e09d03
PT
56
57static char *routes = "";
8cc7b4b9
PT
58module_param(routes, charp, 0444);
59MODULE_PARM_DESC(routes, "routes to non-local networks");
d7e09d03
PT
60
61static int rnet_htable_size = LNET_REMOTE_NETS_HASH_DEFAULT;
8cc7b4b9
PT
62module_param(rnet_htable_size, int, 0444);
63MODULE_PARM_DESC(rnet_htable_size, "size of remote network hash table");
d7e09d03 64
51bd8814 65static char *
d7e09d03
PT
66lnet_get_routes(void)
67{
68 return routes;
69}
70
51bd8814 71static char *
d7e09d03
PT
72lnet_get_networks(void)
73{
7e7ab095
MS
74 char *nets;
75 int rc;
d7e09d03
PT
76
77 if (*networks != 0 && *ip2nets != 0) {
8ad5360a 78 LCONSOLE_ERROR_MSG(0x101, "Please specify EITHER 'networks' or 'ip2nets' but not both at once\n");
d7e09d03
PT
79 return NULL;
80 }
81
82 if (*ip2nets != 0) {
83 rc = lnet_parse_ip2nets(&nets, ip2nets);
84 return (rc == 0) ? nets : NULL;
85 }
86
87 if (*networks != 0)
88 return networks;
89
90 return "tcp";
91}
92
51bd8814 93static void
d7e09d03
PT
94lnet_init_locks(void)
95{
96 spin_lock_init(&the_lnet.ln_eq_wait_lock);
97 init_waitqueue_head(&the_lnet.ln_eq_waitq);
98 mutex_init(&the_lnet.ln_lnd_mutex);
99 mutex_init(&the_lnet.ln_api_mutex);
100}
101
d7e09d03
PT
102static int
103lnet_create_remote_nets_table(void)
104{
7e7ab095
MS
105 int i;
106 struct list_head *hash;
d7e09d03
PT
107
108 LASSERT(the_lnet.ln_remote_nets_hash == NULL);
109 LASSERT(the_lnet.ln_remote_nets_hbits > 0);
110 LIBCFS_ALLOC(hash, LNET_REMOTE_NETS_HASH_SIZE * sizeof(*hash));
111 if (hash == NULL) {
112 CERROR("Failed to create remote nets hash table\n");
113 return -ENOMEM;
114 }
115
116 for (i = 0; i < LNET_REMOTE_NETS_HASH_SIZE; i++)
117 INIT_LIST_HEAD(&hash[i]);
118 the_lnet.ln_remote_nets_hash = hash;
119 return 0;
120}
121
122static void
123lnet_destroy_remote_nets_table(void)
124{
1ae2bdb2 125 int i;
d7e09d03
PT
126
127 if (the_lnet.ln_remote_nets_hash == NULL)
128 return;
129
130 for (i = 0; i < LNET_REMOTE_NETS_HASH_SIZE; i++)
131 LASSERT(list_empty(&the_lnet.ln_remote_nets_hash[i]));
132
133 LIBCFS_FREE(the_lnet.ln_remote_nets_hash,
1ae2bdb2
DE
134 LNET_REMOTE_NETS_HASH_SIZE *
135 sizeof(the_lnet.ln_remote_nets_hash[0]));
d7e09d03
PT
136 the_lnet.ln_remote_nets_hash = NULL;
137}
138
139static void
140lnet_destroy_locks(void)
141{
142 if (the_lnet.ln_res_lock != NULL) {
143 cfs_percpt_lock_free(the_lnet.ln_res_lock);
144 the_lnet.ln_res_lock = NULL;
145 }
146
147 if (the_lnet.ln_net_lock != NULL) {
148 cfs_percpt_lock_free(the_lnet.ln_net_lock);
149 the_lnet.ln_net_lock = NULL;
150 }
d7e09d03
PT
151}
152
153static int
154lnet_create_locks(void)
155{
156 lnet_init_locks();
157
158 the_lnet.ln_res_lock = cfs_percpt_lock_alloc(lnet_cpt_table());
159 if (the_lnet.ln_res_lock == NULL)
160 goto failed;
161
162 the_lnet.ln_net_lock = cfs_percpt_lock_alloc(lnet_cpt_table());
163 if (the_lnet.ln_net_lock == NULL)
164 goto failed;
165
166 return 0;
167
168 failed:
169 lnet_destroy_locks();
170 return -ENOMEM;
171}
172
3b7566d9 173static void lnet_assert_wire_constants(void)
d7e09d03
PT
174{
175 /* Wire protocol assertions generated by 'wirecheck'
176 * running on Linux robert.bartonsoftware.com 2.6.8-1.521
177 * #1 Mon Aug 16 09:01:18 EDT 2004 i686 athlon i386 GNU/Linux
178 * with gcc version 3.3.3 20040412 (Red Hat Linux 3.3.3-7) */
179
180 /* Constants... */
3b7566d9
TP
181 CLASSERT(LNET_PROTO_TCP_MAGIC == 0xeebc0ded);
182 CLASSERT(LNET_PROTO_TCP_VERSION_MAJOR == 1);
183 CLASSERT(LNET_PROTO_TCP_VERSION_MINOR == 0);
184 CLASSERT(LNET_MSG_ACK == 0);
185 CLASSERT(LNET_MSG_PUT == 1);
186 CLASSERT(LNET_MSG_GET == 2);
187 CLASSERT(LNET_MSG_REPLY == 3);
188 CLASSERT(LNET_MSG_HELLO == 4);
d7e09d03
PT
189
190 /* Checks for struct ptl_handle_wire_t */
3b7566d9
TP
191 CLASSERT((int)sizeof(lnet_handle_wire_t) == 16);
192 CLASSERT((int)offsetof(lnet_handle_wire_t, wh_interface_cookie) == 0);
193 CLASSERT((int)sizeof(((lnet_handle_wire_t *)0)->wh_interface_cookie) == 8);
194 CLASSERT((int)offsetof(lnet_handle_wire_t, wh_object_cookie) == 8);
195 CLASSERT((int)sizeof(((lnet_handle_wire_t *)0)->wh_object_cookie) == 8);
d7e09d03
PT
196
197 /* Checks for struct lnet_magicversion_t */
3b7566d9
TP
198 CLASSERT((int)sizeof(lnet_magicversion_t) == 8);
199 CLASSERT((int)offsetof(lnet_magicversion_t, magic) == 0);
200 CLASSERT((int)sizeof(((lnet_magicversion_t *)0)->magic) == 4);
201 CLASSERT((int)offsetof(lnet_magicversion_t, version_major) == 4);
202 CLASSERT((int)sizeof(((lnet_magicversion_t *)0)->version_major) == 2);
203 CLASSERT((int)offsetof(lnet_magicversion_t, version_minor) == 6);
204 CLASSERT((int)sizeof(((lnet_magicversion_t *)0)->version_minor) == 2);
d7e09d03
PT
205
206 /* Checks for struct lnet_hdr_t */
3b7566d9
TP
207 CLASSERT((int)sizeof(lnet_hdr_t) == 72);
208 CLASSERT((int)offsetof(lnet_hdr_t, dest_nid) == 0);
209 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->dest_nid) == 8);
210 CLASSERT((int)offsetof(lnet_hdr_t, src_nid) == 8);
211 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->src_nid) == 8);
212 CLASSERT((int)offsetof(lnet_hdr_t, dest_pid) == 16);
213 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->dest_pid) == 4);
214 CLASSERT((int)offsetof(lnet_hdr_t, src_pid) == 20);
215 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->src_pid) == 4);
216 CLASSERT((int)offsetof(lnet_hdr_t, type) == 24);
217 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->type) == 4);
218 CLASSERT((int)offsetof(lnet_hdr_t, payload_length) == 28);
219 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->payload_length) == 4);
220 CLASSERT((int)offsetof(lnet_hdr_t, msg) == 32);
221 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->msg) == 40);
d7e09d03
PT
222
223 /* Ack */
3b7566d9
TP
224 CLASSERT((int)offsetof(lnet_hdr_t, msg.ack.dst_wmd) == 32);
225 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->msg.ack.dst_wmd) == 16);
226 CLASSERT((int)offsetof(lnet_hdr_t, msg.ack.match_bits) == 48);
227 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->msg.ack.match_bits) == 8);
228 CLASSERT((int)offsetof(lnet_hdr_t, msg.ack.mlength) == 56);
229 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->msg.ack.mlength) == 4);
d7e09d03
PT
230
231 /* Put */
3b7566d9
TP
232 CLASSERT((int)offsetof(lnet_hdr_t, msg.put.ack_wmd) == 32);
233 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->msg.put.ack_wmd) == 16);
234 CLASSERT((int)offsetof(lnet_hdr_t, msg.put.match_bits) == 48);
235 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->msg.put.match_bits) == 8);
236 CLASSERT((int)offsetof(lnet_hdr_t, msg.put.hdr_data) == 56);
237 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->msg.put.hdr_data) == 8);
238 CLASSERT((int)offsetof(lnet_hdr_t, msg.put.ptl_index) == 64);
239 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->msg.put.ptl_index) == 4);
240 CLASSERT((int)offsetof(lnet_hdr_t, msg.put.offset) == 68);
241 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->msg.put.offset) == 4);
d7e09d03
PT
242
243 /* Get */
3b7566d9
TP
244 CLASSERT((int)offsetof(lnet_hdr_t, msg.get.return_wmd) == 32);
245 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->msg.get.return_wmd) == 16);
246 CLASSERT((int)offsetof(lnet_hdr_t, msg.get.match_bits) == 48);
247 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->msg.get.match_bits) == 8);
248 CLASSERT((int)offsetof(lnet_hdr_t, msg.get.ptl_index) == 56);
249 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->msg.get.ptl_index) == 4);
250 CLASSERT((int)offsetof(lnet_hdr_t, msg.get.src_offset) == 60);
251 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->msg.get.src_offset) == 4);
252 CLASSERT((int)offsetof(lnet_hdr_t, msg.get.sink_length) == 64);
253 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->msg.get.sink_length) == 4);
d7e09d03
PT
254
255 /* Reply */
3b7566d9
TP
256 CLASSERT((int)offsetof(lnet_hdr_t, msg.reply.dst_wmd) == 32);
257 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->msg.reply.dst_wmd) == 16);
d7e09d03
PT
258
259 /* Hello */
3b7566d9
TP
260 CLASSERT((int)offsetof(lnet_hdr_t, msg.hello.incarnation) == 32);
261 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->msg.hello.incarnation) == 8);
262 CLASSERT((int)offsetof(lnet_hdr_t, msg.hello.type) == 40);
263 CLASSERT((int)sizeof(((lnet_hdr_t *)0)->msg.hello.type) == 4);
d7e09d03
PT
264}
265
51bd8814 266static lnd_t *
3b7566d9 267lnet_find_lnd_by_type(int type)
d7e09d03 268{
7e7ab095
MS
269 lnd_t *lnd;
270 struct list_head *tmp;
d7e09d03
PT
271
272 /* holding lnd mutex */
565f3d2f 273 list_for_each(tmp, &the_lnet.ln_lnds) {
d7e09d03
PT
274 lnd = list_entry(tmp, lnd_t, lnd_list);
275
276 if ((int)lnd->lnd_type == type)
277 return lnd;
278 }
279
280 return NULL;
281}
282
283void
3b7566d9 284lnet_register_lnd(lnd_t *lnd)
d7e09d03 285{
bdd84a6f 286 mutex_lock(&the_lnet.ln_lnd_mutex);
d7e09d03 287
3b7566d9
TP
288 LASSERT(the_lnet.ln_init);
289 LASSERT(libcfs_isknown_lnd(lnd->lnd_type));
290 LASSERT(lnet_find_lnd_by_type(lnd->lnd_type) == NULL);
d7e09d03 291
3b7566d9 292 list_add_tail(&lnd->lnd_list, &the_lnet.ln_lnds);
d7e09d03
PT
293 lnd->lnd_refcount = 0;
294
295 CDEBUG(D_NET, "%s LND registered\n", libcfs_lnd2str(lnd->lnd_type));
296
bdd84a6f 297 mutex_unlock(&the_lnet.ln_lnd_mutex);
d7e09d03
PT
298}
299EXPORT_SYMBOL(lnet_register_lnd);
300
301void
3b7566d9 302lnet_unregister_lnd(lnd_t *lnd)
d7e09d03 303{
bdd84a6f 304 mutex_lock(&the_lnet.ln_lnd_mutex);
d7e09d03 305
3b7566d9
TP
306 LASSERT(the_lnet.ln_init);
307 LASSERT(lnet_find_lnd_by_type(lnd->lnd_type) == lnd);
308 LASSERT(lnd->lnd_refcount == 0);
d7e09d03 309
3b7566d9 310 list_del(&lnd->lnd_list);
d7e09d03
PT
311 CDEBUG(D_NET, "%s LND unregistered\n", libcfs_lnd2str(lnd->lnd_type));
312
bdd84a6f 313 mutex_unlock(&the_lnet.ln_lnd_mutex);
d7e09d03
PT
314}
315EXPORT_SYMBOL(lnet_unregister_lnd);
316
317void
318lnet_counters_get(lnet_counters_t *counters)
319{
320 lnet_counters_t *ctr;
7e7ab095 321 int i;
d7e09d03
PT
322
323 memset(counters, 0, sizeof(*counters));
324
325 lnet_net_lock(LNET_LOCK_EX);
326
327 cfs_percpt_for_each(ctr, i, the_lnet.ln_counters) {
328 counters->msgs_max += ctr->msgs_max;
329 counters->msgs_alloc += ctr->msgs_alloc;
330 counters->errors += ctr->errors;
331 counters->send_count += ctr->send_count;
332 counters->recv_count += ctr->recv_count;
333 counters->route_count += ctr->route_count;
b3d0dfe5 334 counters->drop_count += ctr->drop_count;
d7e09d03
PT
335 counters->send_length += ctr->send_length;
336 counters->recv_length += ctr->recv_length;
337 counters->route_length += ctr->route_length;
338 counters->drop_length += ctr->drop_length;
339
340 }
341 lnet_net_unlock(LNET_LOCK_EX);
342}
343EXPORT_SYMBOL(lnet_counters_get);
344
345void
346lnet_counters_reset(void)
347{
348 lnet_counters_t *counters;
7e7ab095 349 int i;
d7e09d03
PT
350
351 lnet_net_lock(LNET_LOCK_EX);
352
353 cfs_percpt_for_each(counters, i, the_lnet.ln_counters)
354 memset(counters, 0, sizeof(lnet_counters_t));
355
356 lnet_net_unlock(LNET_LOCK_EX);
357}
358EXPORT_SYMBOL(lnet_counters_reset);
359
51bd8814 360static __u64
3b7566d9 361lnet_create_interface_cookie(void)
d7e09d03
PT
362{
363 /* NB the interface cookie in wire handles guards against delayed
9056be30
TR
364 * replies and ACKs appearing valid after reboot.
365 */
366 return ktime_get_ns();
d7e09d03
PT
367}
368
369static char *
370lnet_res_type2str(int type)
371{
372 switch (type) {
373 default:
374 LBUG();
375 case LNET_COOKIE_TYPE_MD:
376 return "MD";
377 case LNET_COOKIE_TYPE_ME:
378 return "ME";
379 case LNET_COOKIE_TYPE_EQ:
380 return "EQ";
381 }
382}
383
51bd8814 384static void
d7e09d03
PT
385lnet_res_container_cleanup(struct lnet_res_container *rec)
386{
7e7ab095 387 int count = 0;
d7e09d03
PT
388
389 if (rec->rec_type == 0) /* not set yet, it's uninitialized */
390 return;
391
392 while (!list_empty(&rec->rec_active)) {
393 struct list_head *e = rec->rec_active.next;
394
395 list_del_init(e);
396 if (rec->rec_type == LNET_COOKIE_TYPE_EQ) {
397 lnet_eq_free(list_entry(e, lnet_eq_t, eq_list));
398
399 } else if (rec->rec_type == LNET_COOKIE_TYPE_MD) {
400 lnet_md_free(list_entry(e, lnet_libmd_t, md_list));
401
402 } else { /* NB: Active MEs should be attached on portals */
403 LBUG();
404 }
405 count++;
406 }
407
408 if (count > 0) {
409 /* Found alive MD/ME/EQ, user really should unlink/free
410 * all of them before finalize LNet, but if someone didn't,
411 * we have to recycle garbage for him */
412 CERROR("%d active elements on exit of %s container\n",
413 count, lnet_res_type2str(rec->rec_type));
414 }
415
d7e09d03
PT
416 if (rec->rec_lh_hash != NULL) {
417 LIBCFS_FREE(rec->rec_lh_hash,
418 LNET_LH_HASH_SIZE * sizeof(rec->rec_lh_hash[0]));
419 rec->rec_lh_hash = NULL;
420 }
421
422 rec->rec_type = 0; /* mark it as finalized */
423}
424
51bd8814 425static int
39445367 426lnet_res_container_setup(struct lnet_res_container *rec, int cpt, int type)
d7e09d03 427{
7e7ab095
MS
428 int rc = 0;
429 int i;
d7e09d03
PT
430
431 LASSERT(rec->rec_type == 0);
432
433 rec->rec_type = type;
434 INIT_LIST_HEAD(&rec->rec_active);
d7e09d03
PT
435 rec->rec_lh_cookie = (cpt << LNET_COOKIE_TYPE_BITS) | type;
436
437 /* Arbitrary choice of hash table size */
438 LIBCFS_CPT_ALLOC(rec->rec_lh_hash, lnet_cpt_table(), cpt,
439 LNET_LH_HASH_SIZE * sizeof(rec->rec_lh_hash[0]));
440 if (rec->rec_lh_hash == NULL) {
441 rc = -ENOMEM;
442 goto out;
443 }
444
445 for (i = 0; i < LNET_LH_HASH_SIZE; i++)
446 INIT_LIST_HEAD(&rec->rec_lh_hash[i]);
447
448 return 0;
449
450out:
451 CERROR("Failed to setup %s resource container\n",
452 lnet_res_type2str(type));
453 lnet_res_container_cleanup(rec);
454 return rc;
455}
456
457static void
458lnet_res_containers_destroy(struct lnet_res_container **recs)
459{
7e7ab095
MS
460 struct lnet_res_container *rec;
461 int i;
d7e09d03
PT
462
463 cfs_percpt_for_each(rec, i, recs)
464 lnet_res_container_cleanup(rec);
465
466 cfs_percpt_free(recs);
467}
468
469static struct lnet_res_container **
39445367 470lnet_res_containers_create(int type)
d7e09d03 471{
7e7ab095
MS
472 struct lnet_res_container **recs;
473 struct lnet_res_container *rec;
474 int rc;
475 int i;
d7e09d03
PT
476
477 recs = cfs_percpt_alloc(lnet_cpt_table(), sizeof(*rec));
478 if (recs == NULL) {
479 CERROR("Failed to allocate %s resource containers\n",
480 lnet_res_type2str(type));
481 return NULL;
482 }
483
484 cfs_percpt_for_each(rec, i, recs) {
39445367 485 rc = lnet_res_container_setup(rec, i, type);
d7e09d03
PT
486 if (rc != 0) {
487 lnet_res_containers_destroy(recs);
488 return NULL;
489 }
490 }
491
492 return recs;
493}
494
495lnet_libhandle_t *
496lnet_res_lh_lookup(struct lnet_res_container *rec, __u64 cookie)
497{
498 /* ALWAYS called with lnet_res_lock held */
7e7ab095
MS
499 struct list_head *head;
500 lnet_libhandle_t *lh;
501 unsigned int hash;
d7e09d03
PT
502
503 if ((cookie & LNET_COOKIE_MASK) != rec->rec_type)
504 return NULL;
505
506 hash = cookie >> (LNET_COOKIE_TYPE_BITS + LNET_CPT_BITS);
507 head = &rec->rec_lh_hash[hash & LNET_LH_HASH_MASK];
508
509 list_for_each_entry(lh, head, lh_hash_chain) {
510 if (lh->lh_cookie == cookie)
511 return lh;
512 }
513
514 return NULL;
515}
516
517void
518lnet_res_lh_initialize(struct lnet_res_container *rec, lnet_libhandle_t *lh)
519{
520 /* ALWAYS called with lnet_res_lock held */
7e7ab095
MS
521 unsigned int ibits = LNET_COOKIE_TYPE_BITS + LNET_CPT_BITS;
522 unsigned int hash;
d7e09d03
PT
523
524 lh->lh_cookie = rec->rec_lh_cookie;
525 rec->rec_lh_cookie += 1 << ibits;
526
527 hash = (lh->lh_cookie >> ibits) & LNET_LH_HASH_MASK;
528
529 list_add(&lh->lh_hash_chain, &rec->rec_lh_hash[hash]);
530}
531
532
533int lnet_unprepare(void);
534
51bd8814 535static int
d7e09d03
PT
536lnet_prepare(lnet_pid_t requested_pid)
537{
538 /* Prepare to bring up the network */
539 struct lnet_res_container **recs;
7e7ab095 540 int rc = 0;
d7e09d03 541
3b7566d9 542 LASSERT(the_lnet.ln_refcount == 0);
d7e09d03
PT
543
544 the_lnet.ln_routing = 0;
545
3b7566d9 546 LASSERT((requested_pid & LNET_PID_USERFLAG) == 0);
d7e09d03
PT
547 the_lnet.ln_pid = requested_pid;
548
549 INIT_LIST_HEAD(&the_lnet.ln_test_peers);
550 INIT_LIST_HEAD(&the_lnet.ln_nis);
551 INIT_LIST_HEAD(&the_lnet.ln_nis_cpt);
552 INIT_LIST_HEAD(&the_lnet.ln_nis_zombie);
553 INIT_LIST_HEAD(&the_lnet.ln_routers);
554
555 rc = lnet_create_remote_nets_table();
556 if (rc != 0)
557 goto failed;
558
559 the_lnet.ln_interface_cookie = lnet_create_interface_cookie();
560
561 the_lnet.ln_counters = cfs_percpt_alloc(lnet_cpt_table(),
562 sizeof(lnet_counters_t));
563 if (the_lnet.ln_counters == NULL) {
564 CERROR("Failed to allocate counters for LNet\n");
565 rc = -ENOMEM;
566 goto failed;
567 }
568
569 rc = lnet_peer_tables_create();
570 if (rc != 0)
571 goto failed;
572
573 rc = lnet_msg_containers_create();
574 if (rc != 0)
575 goto failed;
576
577 rc = lnet_res_container_setup(&the_lnet.ln_eq_container, 0,
39445367 578 LNET_COOKIE_TYPE_EQ);
d7e09d03
PT
579 if (rc != 0)
580 goto failed;
581
39445367 582 recs = lnet_res_containers_create(LNET_COOKIE_TYPE_ME);
a18ac314
JL
583 if (recs == NULL) {
584 rc = -ENOMEM;
d7e09d03 585 goto failed;
a18ac314 586 }
d7e09d03
PT
587
588 the_lnet.ln_me_containers = recs;
589
39445367 590 recs = lnet_res_containers_create(LNET_COOKIE_TYPE_MD);
a18ac314
JL
591 if (recs == NULL) {
592 rc = -ENOMEM;
d7e09d03 593 goto failed;
a18ac314 594 }
d7e09d03
PT
595
596 the_lnet.ln_md_containers = recs;
597
598 rc = lnet_portals_create();
599 if (rc != 0) {
600 CERROR("Failed to create portals for LNet: %d\n", rc);
601 goto failed;
602 }
603
604 return 0;
605
606 failed:
607 lnet_unprepare();
608 return rc;
609}
610
611int
3b7566d9 612lnet_unprepare(void)
d7e09d03
PT
613{
614 /* NB no LNET_LOCK since this is the last reference. All LND instances
615 * have shut down already, so it is safe to unlink and free all
616 * descriptors, even those that appear committed to a network op (eg MD
617 * with non-zero pending count) */
618
619 lnet_fail_nid(LNET_NID_ANY, 0);
620
621 LASSERT(the_lnet.ln_refcount == 0);
622 LASSERT(list_empty(&the_lnet.ln_test_peers));
623 LASSERT(list_empty(&the_lnet.ln_nis));
624 LASSERT(list_empty(&the_lnet.ln_nis_cpt));
625 LASSERT(list_empty(&the_lnet.ln_nis_zombie));
626
627 lnet_portals_destroy();
628
629 if (the_lnet.ln_md_containers != NULL) {
630 lnet_res_containers_destroy(the_lnet.ln_md_containers);
631 the_lnet.ln_md_containers = NULL;
632 }
633
634 if (the_lnet.ln_me_containers != NULL) {
635 lnet_res_containers_destroy(the_lnet.ln_me_containers);
636 the_lnet.ln_me_containers = NULL;
637 }
638
639 lnet_res_container_cleanup(&the_lnet.ln_eq_container);
640
641 lnet_msg_containers_destroy();
642 lnet_peer_tables_destroy();
643 lnet_rtrpools_free();
644
645 if (the_lnet.ln_counters != NULL) {
646 cfs_percpt_free(the_lnet.ln_counters);
647 the_lnet.ln_counters = NULL;
648 }
649 lnet_destroy_remote_nets_table();
650
651 return 0;
652}
653
654lnet_ni_t *
655lnet_net2ni_locked(__u32 net, int cpt)
656{
7e7ab095
MS
657 struct list_head *tmp;
658 lnet_ni_t *ni;
d7e09d03
PT
659
660 LASSERT(cpt != LNET_LOCK_EX);
661
662 list_for_each(tmp, &the_lnet.ln_nis) {
663 ni = list_entry(tmp, lnet_ni_t, ni_list);
664
665 if (LNET_NIDNET(ni->ni_nid) == net) {
666 lnet_ni_addref_locked(ni, cpt);
667 return ni;
668 }
669 }
670
671 return NULL;
672}
673
674lnet_ni_t *
675lnet_net2ni(__u32 net)
676{
677 lnet_ni_t *ni;
678
679 lnet_net_lock(0);
680 ni = lnet_net2ni_locked(net, 0);
681 lnet_net_unlock(0);
682
683 return ni;
684}
685EXPORT_SYMBOL(lnet_net2ni);
686
687static unsigned int
688lnet_nid_cpt_hash(lnet_nid_t nid, unsigned int number)
689{
7e7ab095
MS
690 __u64 key = nid;
691 unsigned int val;
d7e09d03
PT
692
693 LASSERT(number >= 1 && number <= LNET_CPT_NUMBER);
694
695 if (number == 1)
696 return 0;
697
72c0824a 698 val = hash_long(key, LNET_CPT_BITS);
d7e09d03
PT
699 /* NB: LNET_CP_NUMBER doesn't have to be PO2 */
700 if (val < number)
701 return val;
702
703 return (unsigned int)(key + val + (val >> 1)) % number;
704}
705
706int
707lnet_cpt_of_nid_locked(lnet_nid_t nid)
708{
709 struct lnet_ni *ni;
710
711 /* must called with hold of lnet_net_lock */
712 if (LNET_CPT_NUMBER == 1)
713 return 0; /* the only one */
714
715 /* take lnet_net_lock(any) would be OK */
716 if (!list_empty(&the_lnet.ln_nis_cpt)) {
717 list_for_each_entry(ni, &the_lnet.ln_nis_cpt, ni_cptlist) {
718 if (LNET_NIDNET(ni->ni_nid) != LNET_NIDNET(nid))
719 continue;
720
721 LASSERT(ni->ni_cpts != NULL);
722 return ni->ni_cpts[lnet_nid_cpt_hash
723 (nid, ni->ni_ncpts)];
724 }
725 }
726
727 return lnet_nid_cpt_hash(nid, LNET_CPT_NUMBER);
728}
729
730int
731lnet_cpt_of_nid(lnet_nid_t nid)
732{
7e7ab095
MS
733 int cpt;
734 int cpt2;
d7e09d03
PT
735
736 if (LNET_CPT_NUMBER == 1)
737 return 0; /* the only one */
738
739 if (list_empty(&the_lnet.ln_nis_cpt))
740 return lnet_nid_cpt_hash(nid, LNET_CPT_NUMBER);
741
742 cpt = lnet_net_lock_current();
743 cpt2 = lnet_cpt_of_nid_locked(nid);
744 lnet_net_unlock(cpt);
745
746 return cpt2;
747}
748EXPORT_SYMBOL(lnet_cpt_of_nid);
749
750int
751lnet_islocalnet(__u32 net)
752{
7e7ab095
MS
753 struct lnet_ni *ni;
754 int cpt;
d7e09d03
PT
755
756 cpt = lnet_net_lock_current();
757
758 ni = lnet_net2ni_locked(net, cpt);
759 if (ni != NULL)
760 lnet_ni_decref_locked(ni, cpt);
761
762 lnet_net_unlock(cpt);
763
764 return ni != NULL;
765}
766
767lnet_ni_t *
768lnet_nid2ni_locked(lnet_nid_t nid, int cpt)
769{
7e7ab095
MS
770 struct lnet_ni *ni;
771 struct list_head *tmp;
d7e09d03
PT
772
773 LASSERT(cpt != LNET_LOCK_EX);
774
775 list_for_each(tmp, &the_lnet.ln_nis) {
776 ni = list_entry(tmp, lnet_ni_t, ni_list);
777
778 if (ni->ni_nid == nid) {
779 lnet_ni_addref_locked(ni, cpt);
780 return ni;
781 }
782 }
783
784 return NULL;
785}
786
787int
788lnet_islocalnid(lnet_nid_t nid)
789{
7e7ab095
MS
790 struct lnet_ni *ni;
791 int cpt;
d7e09d03
PT
792
793 cpt = lnet_net_lock_current();
794 ni = lnet_nid2ni_locked(nid, cpt);
795 if (ni != NULL)
796 lnet_ni_decref_locked(ni, cpt);
797 lnet_net_unlock(cpt);
798
799 return ni != NULL;
800}
801
802int
3b7566d9 803lnet_count_acceptor_nis(void)
d7e09d03
PT
804{
805 /* Return the # of NIs that need the acceptor. */
7e7ab095
MS
806 int count = 0;
807 struct list_head *tmp;
808 struct lnet_ni *ni;
809 int cpt;
d7e09d03
PT
810
811 cpt = lnet_net_lock_current();
812 list_for_each(tmp, &the_lnet.ln_nis) {
813 ni = list_entry(tmp, lnet_ni_t, ni_list);
814
815 if (ni->ni_lnd->lnd_accept != NULL)
816 count++;
817 }
818
819 lnet_net_unlock(cpt);
820
821 return count;
822}
823
824static int
825lnet_ni_tq_credits(lnet_ni_t *ni)
826{
7e7ab095 827 int credits;
d7e09d03
PT
828
829 LASSERT(ni->ni_ncpts >= 1);
830
831 if (ni->ni_ncpts == 1)
832 return ni->ni_maxtxcredits;
833
834 credits = ni->ni_maxtxcredits / ni->ni_ncpts;
835 credits = max(credits, 8 * ni->ni_peertxcredits);
836 credits = min(credits, ni->ni_maxtxcredits);
837
838 return credits;
839}
840
51bd8814 841static void
3b7566d9 842lnet_shutdown_lndnis(void)
d7e09d03 843{
7e7ab095
MS
844 int i;
845 int islo;
846 lnet_ni_t *ni;
d7e09d03
PT
847
848 /* NB called holding the global mutex */
849
850 /* All quiet on the API front */
851 LASSERT(!the_lnet.ln_shutdown);
852 LASSERT(the_lnet.ln_refcount == 0);
853 LASSERT(list_empty(&the_lnet.ln_nis_zombie));
854
855 lnet_net_lock(LNET_LOCK_EX);
856 the_lnet.ln_shutdown = 1; /* flag shutdown */
857
858 /* Unlink NIs from the global table */
859 while (!list_empty(&the_lnet.ln_nis)) {
860 ni = list_entry(the_lnet.ln_nis.next,
861 lnet_ni_t, ni_list);
862 /* move it to zombie list and nobody can find it anymore */
863 list_move(&ni->ni_list, &the_lnet.ln_nis_zombie);
864 lnet_ni_decref_locked(ni, 0); /* drop ln_nis' ref */
865
866 if (!list_empty(&ni->ni_cptlist)) {
867 list_del_init(&ni->ni_cptlist);
868 lnet_ni_decref_locked(ni, 0);
869 }
870 }
871
872 /* Drop the cached eqwait NI. */
873 if (the_lnet.ln_eq_waitni != NULL) {
874 lnet_ni_decref_locked(the_lnet.ln_eq_waitni, 0);
875 the_lnet.ln_eq_waitni = NULL;
876 }
877
878 /* Drop the cached loopback NI. */
879 if (the_lnet.ln_loni != NULL) {
880 lnet_ni_decref_locked(the_lnet.ln_loni, 0);
881 the_lnet.ln_loni = NULL;
882 }
883
884 lnet_net_unlock(LNET_LOCK_EX);
885
886 /* Clear lazy portals and drop delayed messages which hold refs
887 * on their lnet_msg_t::msg_rxpeer */
888 for (i = 0; i < the_lnet.ln_nportals; i++)
889 LNetClearLazyPortal(i);
890
891 /* Clear the peer table and wait for all peers to go (they hold refs on
892 * their NIs) */
893 lnet_peer_tables_cleanup();
894
895 lnet_net_lock(LNET_LOCK_EX);
896 /* Now wait for the NI's I just nuked to show up on ln_zombie_nis
897 * and shut them down in guaranteed thread context */
898 i = 2;
899 while (!list_empty(&the_lnet.ln_nis_zombie)) {
7e7ab095
MS
900 int *ref;
901 int j;
d7e09d03
PT
902
903 ni = list_entry(the_lnet.ln_nis_zombie.next,
904 lnet_ni_t, ni_list);
905 list_del_init(&ni->ni_list);
906 cfs_percpt_for_each(ref, j, ni->ni_refs) {
907 if (*ref == 0)
908 continue;
909 /* still busy, add it back to zombie list */
910 list_add(&ni->ni_list, &the_lnet.ln_nis_zombie);
911 break;
912 }
913
526cdb4f 914 if (!list_empty(&ni->ni_list)) {
d7e09d03
PT
915 lnet_net_unlock(LNET_LOCK_EX);
916 ++i;
917 if ((i & (-i)) == i) {
526cdb4f 918 CDEBUG(D_WARNING, "Waiting for zombie LNI %s\n",
d7e09d03
PT
919 libcfs_nid2str(ni->ni_nid));
920 }
d3caf4d5
PT
921 set_current_state(TASK_UNINTERRUPTIBLE);
922 schedule_timeout(cfs_time_seconds(1));
d7e09d03
PT
923 lnet_net_lock(LNET_LOCK_EX);
924 continue;
925 }
926
927 ni->ni_lnd->lnd_refcount--;
928 lnet_net_unlock(LNET_LOCK_EX);
929
930 islo = ni->ni_lnd->lnd_type == LOLND;
931
3b7566d9 932 LASSERT(!in_interrupt());
d7e09d03
PT
933 (ni->ni_lnd->lnd_shutdown)(ni);
934
935 /* can't deref lnd anymore now; it might have unregistered
936 * itself... */
937
938 if (!islo)
939 CDEBUG(D_LNI, "Removed LNI %s\n",
940 libcfs_nid2str(ni->ni_nid));
941
942 lnet_ni_free(ni);
526cdb4f
LZ
943 i = 2;
944
d7e09d03
PT
945 lnet_net_lock(LNET_LOCK_EX);
946 }
947
948 the_lnet.ln_shutdown = 0;
949 lnet_net_unlock(LNET_LOCK_EX);
950
951 if (the_lnet.ln_network_tokens != NULL) {
952 LIBCFS_FREE(the_lnet.ln_network_tokens,
953 the_lnet.ln_network_tokens_nob);
954 the_lnet.ln_network_tokens = NULL;
955 }
956}
957
51bd8814 958static int
3b7566d9 959lnet_startup_lndnis(void)
d7e09d03 960{
7e7ab095
MS
961 lnd_t *lnd;
962 struct lnet_ni *ni;
963 struct lnet_tx_queue *tq;
964 struct list_head nilist;
965 int i;
966 int rc = 0;
967 int lnd_type;
968 int nicount = 0;
969 char *nets = lnet_get_networks();
d7e09d03
PT
970
971 INIT_LIST_HEAD(&nilist);
972
973 if (nets == NULL)
974 goto failed;
975
976 rc = lnet_parse_networks(&nilist, nets);
977 if (rc != 0)
978 goto failed;
979
980 while (!list_empty(&nilist)) {
981 ni = list_entry(nilist.next, lnet_ni_t, ni_list);
982 lnd_type = LNET_NETTYP(LNET_NIDNET(ni->ni_nid));
983
3b7566d9 984 LASSERT(libcfs_isknown_lnd(lnd_type));
d7e09d03
PT
985
986 if (lnd_type == CIBLND ||
987 lnd_type == OPENIBLND ||
988 lnd_type == IIBLND ||
989 lnd_type == VIBLND) {
990 CERROR("LND %s obsoleted\n",
991 libcfs_lnd2str(lnd_type));
992 goto failed;
993 }
994
bdd84a6f 995 mutex_lock(&the_lnet.ln_lnd_mutex);
d7e09d03
PT
996 lnd = lnet_find_lnd_by_type(lnd_type);
997
998 if (lnd == NULL) {
bdd84a6f 999 mutex_unlock(&the_lnet.ln_lnd_mutex);
d7e09d03
PT
1000 rc = request_module("%s",
1001 libcfs_lnd2modname(lnd_type));
bdd84a6f 1002 mutex_lock(&the_lnet.ln_lnd_mutex);
d7e09d03
PT
1003
1004 lnd = lnet_find_lnd_by_type(lnd_type);
1005 if (lnd == NULL) {
bdd84a6f 1006 mutex_unlock(&the_lnet.ln_lnd_mutex);
d7e09d03
PT
1007 CERROR("Can't load LND %s, module %s, rc=%d\n",
1008 libcfs_lnd2str(lnd_type),
1009 libcfs_lnd2modname(lnd_type), rc);
1010 goto failed;
1011 }
1012 }
1013
1014 lnet_net_lock(LNET_LOCK_EX);
1015 lnd->lnd_refcount++;
1016 lnet_net_unlock(LNET_LOCK_EX);
1017
1018 ni->ni_lnd = lnd;
1019
1020 rc = (lnd->lnd_startup)(ni);
1021
bdd84a6f 1022 mutex_unlock(&the_lnet.ln_lnd_mutex);
d7e09d03
PT
1023
1024 if (rc != 0) {
8ad5360a 1025 LCONSOLE_ERROR_MSG(0x105, "Error %d starting up LNI %s\n",
d7e09d03
PT
1026 rc, libcfs_lnd2str(lnd->lnd_type));
1027 lnet_net_lock(LNET_LOCK_EX);
1028 lnd->lnd_refcount--;
1029 lnet_net_unlock(LNET_LOCK_EX);
1030 goto failed;
1031 }
1032
3b7566d9 1033 LASSERT(ni->ni_peertimeout <= 0 || lnd->lnd_query != NULL);
d7e09d03
PT
1034
1035 list_del(&ni->ni_list);
1036
1037 lnet_net_lock(LNET_LOCK_EX);
1038 /* refcount for ln_nis */
1039 lnet_ni_addref_locked(ni, 0);
1040 list_add_tail(&ni->ni_list, &the_lnet.ln_nis);
1041 if (ni->ni_cpts != NULL) {
1042 list_add_tail(&ni->ni_cptlist,
1043 &the_lnet.ln_nis_cpt);
1044 lnet_ni_addref_locked(ni, 0);
1045 }
1046
1047 lnet_net_unlock(LNET_LOCK_EX);
1048
1049 if (lnd->lnd_type == LOLND) {
1050 lnet_ni_addref(ni);
3b7566d9 1051 LASSERT(the_lnet.ln_loni == NULL);
d7e09d03
PT
1052 the_lnet.ln_loni = ni;
1053 continue;
1054 }
1055
1056 if (ni->ni_peertxcredits == 0 ||
1057 ni->ni_maxtxcredits == 0) {
1058 LCONSOLE_ERROR_MSG(0x107, "LNI %s has no %scredits\n",
1059 libcfs_lnd2str(lnd->lnd_type),
1060 ni->ni_peertxcredits == 0 ?
1061 "" : "per-peer ");
1062 goto failed;
1063 }
1064
1065 cfs_percpt_for_each(tq, i, ni->ni_tx_queues) {
1066 tq->tq_credits_min =
1067 tq->tq_credits_max =
1068 tq->tq_credits = lnet_ni_tq_credits(ni);
1069 }
1070
1071 CDEBUG(D_LNI, "Added LNI %s [%d/%d/%d/%d]\n",
1072 libcfs_nid2str(ni->ni_nid), ni->ni_peertxcredits,
1073 lnet_ni_tq_credits(ni) * LNET_CPT_NUMBER,
1074 ni->ni_peerrtrcredits, ni->ni_peertimeout);
1075
1076 nicount++;
1077 }
1078
1079 if (the_lnet.ln_eq_waitni != NULL && nicount > 1) {
1080 lnd_type = the_lnet.ln_eq_waitni->ni_lnd->lnd_type;
8ad5360a 1081 LCONSOLE_ERROR_MSG(0x109, "LND %s can only run single-network\n",
d7e09d03
PT
1082 libcfs_lnd2str(lnd_type));
1083 goto failed;
1084 }
1085
1086 return 0;
1087
1088 failed:
1089 lnet_shutdown_lndnis();
1090
1091 while (!list_empty(&nilist)) {
1092 ni = list_entry(nilist.next, lnet_ni_t, ni_list);
1093 list_del(&ni->ni_list);
1094 lnet_ni_free(ni);
1095 }
1096
1097 return -ENETDOWN;
1098}
1099
1100/**
1101 * Initialize LNet library.
1102 *
1103 * Only userspace program needs to call this function - it's automatically
1104 * called in the kernel at module loading time. Caller has to call LNetFini()
1105 * after a call to LNetInit(), if and only if the latter returned 0. It must
1106 * be called exactly once.
1107 *
1108 * \return 0 on success, and -ve on failures.
1109 */
1110int
1111LNetInit(void)
1112{
7e7ab095 1113 int rc;
d7e09d03
PT
1114
1115 lnet_assert_wire_constants();
1116 LASSERT(!the_lnet.ln_init);
1117
1118 memset(&the_lnet, 0, sizeof(the_lnet));
1119
1120 /* refer to global cfs_cpt_table for now */
1121 the_lnet.ln_cpt_table = cfs_cpt_table;
1122 the_lnet.ln_cpt_number = cfs_cpt_number(cfs_cpt_table);
1123
1124 LASSERT(the_lnet.ln_cpt_number > 0);
1125 if (the_lnet.ln_cpt_number > LNET_CPT_MAX) {
1126 /* we are under risk of consuming all lh_cookie */
8ad5360a 1127 CERROR("Can't have %d CPTs for LNet (max allowed is %d), please change setting of CPT-table and retry\n",
d7e09d03
PT
1128 the_lnet.ln_cpt_number, LNET_CPT_MAX);
1129 return -1;
1130 }
1131
1132 while ((1 << the_lnet.ln_cpt_bits) < the_lnet.ln_cpt_number)
1133 the_lnet.ln_cpt_bits++;
1134
1135 rc = lnet_create_locks();
1136 if (rc != 0) {
1137 CERROR("Can't create LNet global locks: %d\n", rc);
1138 return -1;
1139 }
1140
1141 the_lnet.ln_refcount = 0;
1142 the_lnet.ln_init = 1;
1143 LNetInvalidateHandle(&the_lnet.ln_rc_eqh);
1144 INIT_LIST_HEAD(&the_lnet.ln_lnds);
1145 INIT_LIST_HEAD(&the_lnet.ln_rcd_zombie);
1146 INIT_LIST_HEAD(&the_lnet.ln_rcd_deathrow);
1147
1148 /* The hash table size is the number of bits it takes to express the set
1149 * ln_num_routes, minus 1 (better to under estimate than over so we
1150 * don't waste memory). */
1151 if (rnet_htable_size <= 0)
1152 rnet_htable_size = LNET_REMOTE_NETS_HASH_DEFAULT;
1153 else if (rnet_htable_size > LNET_REMOTE_NETS_HASH_MAX)
1154 rnet_htable_size = LNET_REMOTE_NETS_HASH_MAX;
1155 the_lnet.ln_remote_nets_hbits = max_t(int, 1,
1156 order_base_2(rnet_htable_size) - 1);
1157
1158 /* All LNDs apart from the LOLND are in separate modules. They
1159 * register themselves when their module loads, and unregister
1160 * themselves when their module is unloaded. */
1161 lnet_register_lnd(&the_lolnd);
1162 return 0;
1163}
1164EXPORT_SYMBOL(LNetInit);
1165
1166/**
1167 * Finalize LNet library.
1168 *
1169 * Only userspace program needs to call this function. It can be called
1170 * at most once.
1171 *
1172 * \pre LNetInit() called with success.
1173 * \pre All LNet users called LNetNIFini() for matching LNetNIInit() calls.
1174 */
1175void
1176LNetFini(void)
1177{
1178 LASSERT(the_lnet.ln_init);
1179 LASSERT(the_lnet.ln_refcount == 0);
1180
1181 while (!list_empty(&the_lnet.ln_lnds))
1182 lnet_unregister_lnd(list_entry(the_lnet.ln_lnds.next,
1183 lnd_t, lnd_list));
1184 lnet_destroy_locks();
1185
1186 the_lnet.ln_init = 0;
1187}
1188EXPORT_SYMBOL(LNetFini);
1189
1190/**
1191 * Set LNet PID and start LNet interfaces, routing, and forwarding.
1192 *
1193 * Userspace program should call this after a successful call to LNetInit().
1194 * Users must call this function at least once before any other functions.
1195 * For each successful call there must be a corresponding call to
1196 * LNetNIFini(). For subsequent calls to LNetNIInit(), \a requested_pid is
1197 * ignored.
1198 *
1199 * The PID used by LNet may be different from the one requested.
1200 * See LNetGetId().
1201 *
1202 * \param requested_pid PID requested by the caller.
1203 *
1204 * \return >= 0 on success, and < 0 error code on failures.
1205 */
1206int
1207LNetNIInit(lnet_pid_t requested_pid)
1208{
7e7ab095
MS
1209 int im_a_router = 0;
1210 int rc;
d7e09d03 1211
bdd84a6f 1212 mutex_lock(&the_lnet.ln_api_mutex);
d7e09d03 1213
3b7566d9 1214 LASSERT(the_lnet.ln_init);
d7e09d03
PT
1215 CDEBUG(D_OTHER, "refs %d\n", the_lnet.ln_refcount);
1216
1217 if (the_lnet.ln_refcount > 0) {
1218 rc = the_lnet.ln_refcount++;
1219 goto out;
1220 }
1221
d7e09d03
PT
1222 if (requested_pid == LNET_PID_ANY) {
1223 /* Don't instantiate LNET just for me */
1224 rc = -ENETDOWN;
1225 goto failed0;
1226 }
1227
1228 rc = lnet_prepare(requested_pid);
1229 if (rc != 0)
1230 goto failed0;
1231
1232 rc = lnet_startup_lndnis();
1233 if (rc != 0)
1234 goto failed1;
1235
1236 rc = lnet_parse_routes(lnet_get_routes(), &im_a_router);
1237 if (rc != 0)
1238 goto failed2;
1239
1240 rc = lnet_check_routes();
1241 if (rc != 0)
1242 goto failed2;
1243
1244 rc = lnet_rtrpools_alloc(im_a_router);
1245 if (rc != 0)
1246 goto failed2;
1247
1248 rc = lnet_acceptor_start();
1249 if (rc != 0)
1250 goto failed2;
1251
1252 the_lnet.ln_refcount = 1;
1253 /* Now I may use my own API functions... */
1254
1255 /* NB router checker needs the_lnet.ln_ping_info in
1256 * lnet_router_checker -> lnet_update_ni_status_locked */
1257 rc = lnet_ping_target_init();
1258 if (rc != 0)
1259 goto failed3;
1260
1261 rc = lnet_router_checker_start();
1262 if (rc != 0)
1263 goto failed4;
1264
1265 lnet_proc_init();
1266 goto out;
1267
1268 failed4:
1269 lnet_ping_target_fini();
1270 failed3:
1271 the_lnet.ln_refcount = 0;
1272 lnet_acceptor_stop();
1273 failed2:
1274 lnet_destroy_routes();
1275 lnet_shutdown_lndnis();
1276 failed1:
1277 lnet_unprepare();
1278 failed0:
3b7566d9 1279 LASSERT(rc < 0);
d7e09d03 1280 out:
bdd84a6f 1281 mutex_unlock(&the_lnet.ln_api_mutex);
d7e09d03
PT
1282 return rc;
1283}
1284EXPORT_SYMBOL(LNetNIInit);
1285
1286/**
1287 * Stop LNet interfaces, routing, and forwarding.
1288 *
1289 * Users must call this function once for each successful call to LNetNIInit().
1290 * Once the LNetNIFini() operation has been started, the results of pending
1291 * API operations are undefined.
1292 *
1293 * \return always 0 for current implementation.
1294 */
1295int
7d46a21a 1296LNetNIFini(void)
d7e09d03 1297{
bdd84a6f 1298 mutex_lock(&the_lnet.ln_api_mutex);
d7e09d03 1299
3b7566d9
TP
1300 LASSERT(the_lnet.ln_init);
1301 LASSERT(the_lnet.ln_refcount > 0);
d7e09d03
PT
1302
1303 if (the_lnet.ln_refcount != 1) {
1304 the_lnet.ln_refcount--;
1305 } else {
3b7566d9 1306 LASSERT(!the_lnet.ln_niinit_self);
d7e09d03
PT
1307
1308 lnet_proc_fini();
1309 lnet_router_checker_stop();
1310 lnet_ping_target_fini();
1311
1312 /* Teardown fns that use my own API functions BEFORE here */
1313 the_lnet.ln_refcount = 0;
1314
1315 lnet_acceptor_stop();
1316 lnet_destroy_routes();
1317 lnet_shutdown_lndnis();
1318 lnet_unprepare();
1319 }
1320
bdd84a6f 1321 mutex_unlock(&the_lnet.ln_api_mutex);
d7e09d03
PT
1322 return 0;
1323}
1324EXPORT_SYMBOL(LNetNIFini);
1325
1326/**
1327 * This is an ugly hack to export IOC_LIBCFS_DEBUG_PEER and
1328 * IOC_LIBCFS_PORTALS_COMPATIBILITY commands to users, by tweaking the LNet
1329 * internal ioctl handler.
1330 *
1331 * IOC_LIBCFS_PORTALS_COMPATIBILITY is now deprecated, don't use it.
1332 *
1333 * \param cmd IOC_LIBCFS_DEBUG_PEER to print debugging data about a peer.
1334 * The data will be printed to system console. Don't use it excessively.
1335 * \param arg A pointer to lnet_process_id_t, process ID of the peer.
1336 *
1337 * \return Always return 0 when called by users directly (i.e., not via ioctl).
1338 */
1339int
1340LNetCtl(unsigned int cmd, void *arg)
1341{
1342 struct libcfs_ioctl_data *data = arg;
7e7ab095
MS
1343 lnet_process_id_t id = {0};
1344 lnet_ni_t *ni;
1345 int rc;
d7e09d03 1346
3b7566d9
TP
1347 LASSERT(the_lnet.ln_init);
1348 LASSERT(the_lnet.ln_refcount > 0);
d7e09d03
PT
1349
1350 switch (cmd) {
1351 case IOC_LIBCFS_GET_NI:
1352 rc = LNetGetId(data->ioc_count, &id);
1353 data->ioc_nid = id.nid;
1354 return rc;
1355
1356 case IOC_LIBCFS_FAIL_NID:
1357 return lnet_fail_nid(data->ioc_nid, data->ioc_count);
1358
1359 case IOC_LIBCFS_ADD_ROUTE:
1360 rc = lnet_add_route(data->ioc_net, data->ioc_count,
e75fb87f 1361 data->ioc_nid, data->ioc_priority);
d7e09d03
PT
1362 return (rc != 0) ? rc : lnet_check_routes();
1363
1364 case IOC_LIBCFS_DEL_ROUTE:
1365 return lnet_del_route(data->ioc_net, data->ioc_nid);
1366
1367 case IOC_LIBCFS_GET_ROUTE:
1368 return lnet_get_route(data->ioc_count,
1369 &data->ioc_net, &data->ioc_count,
e75fb87f
DO
1370 &data->ioc_nid, &data->ioc_flags,
1371 &data->ioc_priority);
d7e09d03
PT
1372 case IOC_LIBCFS_NOTIFY_ROUTER:
1373 return lnet_notify(NULL, data->ioc_nid, data->ioc_flags,
1374 cfs_time_current() -
7264b8a5 1375 cfs_time_seconds(get_seconds() -
d7e09d03
PT
1376 (time_t)data->ioc_u64[0]));
1377
1378 case IOC_LIBCFS_PORTALS_COMPATIBILITY:
1379 /* This can be removed once lustre stops calling it */
1380 return 0;
1381
1382 case IOC_LIBCFS_LNET_DIST:
1383 rc = LNetDist(data->ioc_nid, &data->ioc_nid, &data->ioc_u32[1]);
1384 if (rc < 0 && rc != -EHOSTUNREACH)
1385 return rc;
1386
1387 data->ioc_u32[0] = rc;
1388 return 0;
1389
1390 case IOC_LIBCFS_TESTPROTOCOMPAT:
1391 lnet_net_lock(LNET_LOCK_EX);
1392 the_lnet.ln_testprotocompat = data->ioc_flags;
1393 lnet_net_unlock(LNET_LOCK_EX);
1394 return 0;
1395
1396 case IOC_LIBCFS_PING:
1397 id.nid = data->ioc_nid;
1398 id.pid = data->ioc_u32[0];
1399 rc = lnet_ping(id, data->ioc_u32[1], /* timeout */
1400 (lnet_process_id_t *)data->ioc_pbuf1,
1401 data->ioc_plen1/sizeof(lnet_process_id_t));
1402 if (rc < 0)
1403 return rc;
1404 data->ioc_count = rc;
1405 return 0;
1406
1407 case IOC_LIBCFS_DEBUG_PEER: {
1408 /* CAVEAT EMPTOR: this one designed for calling directly; not
1409 * via an ioctl */
1410 id = *((lnet_process_id_t *) arg);
1411
1412 lnet_debug_peer(id.nid);
1413
1414 ni = lnet_net2ni(LNET_NIDNET(id.nid));
1415 if (ni == NULL) {
1416 CDEBUG(D_WARNING, "No NI for %s\n", libcfs_id2str(id));
1417 } else {
1418 if (ni->ni_lnd->lnd_ctl == NULL) {
1419 CDEBUG(D_WARNING, "No ctl for %s\n",
1420 libcfs_id2str(id));
1421 } else {
1422 (void)ni->ni_lnd->lnd_ctl(ni, cmd, arg);
1423 }
1424
1425 lnet_ni_decref(ni);
1426 }
1427 return 0;
1428 }
1429
1430 default:
1431 ni = lnet_net2ni(data->ioc_net);
1432 if (ni == NULL)
1433 return -EINVAL;
1434
1435 if (ni->ni_lnd->lnd_ctl == NULL)
1436 rc = -EINVAL;
1437 else
1438 rc = ni->ni_lnd->lnd_ctl(ni, cmd, arg);
1439
1440 lnet_ni_decref(ni);
1441 return rc;
1442 }
1443 /* not reached */
1444}
1445EXPORT_SYMBOL(LNetCtl);
1446
1447/**
1448 * Retrieve the lnet_process_id_t ID of LNet interface at \a index. Note that
1449 * all interfaces share a same PID, as requested by LNetNIInit().
1450 *
1451 * \param index Index of the interface to look up.
1452 * \param id On successful return, this location will hold the
1453 * lnet_process_id_t ID of the interface.
1454 *
1455 * \retval 0 If an interface exists at \a index.
1456 * \retval -ENOENT If no interface has been found.
1457 */
1458int
1459LNetGetId(unsigned int index, lnet_process_id_t *id)
1460{
7e7ab095
MS
1461 struct lnet_ni *ni;
1462 struct list_head *tmp;
1463 int cpt;
1464 int rc = -ENOENT;
d7e09d03
PT
1465
1466 LASSERT(the_lnet.ln_init);
4b1e84ed
PT
1467
1468 /* LNetNI initilization failed? */
1469 if (the_lnet.ln_refcount == 0)
1470 return rc;
d7e09d03
PT
1471
1472 cpt = lnet_net_lock_current();
1473
1474 list_for_each(tmp, &the_lnet.ln_nis) {
1475 if (index-- != 0)
1476 continue;
1477
1478 ni = list_entry(tmp, lnet_ni_t, ni_list);
1479
1480 id->nid = ni->ni_nid;
1481 id->pid = the_lnet.ln_pid;
1482 rc = 0;
1483 break;
1484 }
1485
1486 lnet_net_unlock(cpt);
1487 return rc;
1488}
1489EXPORT_SYMBOL(LNetGetId);
1490
1491/**
1492 * Print a string representation of handle \a h into buffer \a str of
1493 * \a len bytes.
1494 */
1495void
1496LNetSnprintHandle(char *str, int len, lnet_handle_any_t h)
1497{
55f5a824 1498 snprintf(str, len, "%#llx", h.cookie);
d7e09d03
PT
1499}
1500EXPORT_SYMBOL(LNetSnprintHandle);
1501
1502static int
1503lnet_create_ping_info(void)
1504{
7e7ab095
MS
1505 int i;
1506 int n;
1507 int rc;
1508 unsigned int infosz;
1509 lnet_ni_t *ni;
d7e09d03
PT
1510 lnet_process_id_t id;
1511 lnet_ping_info_t *pinfo;
1512
1513 for (n = 0; ; n++) {
1514 rc = LNetGetId(n, &id);
1515 if (rc == -ENOENT)
1516 break;
1517
3b7566d9 1518 LASSERT(rc == 0);
d7e09d03
PT
1519 }
1520
1521 infosz = offsetof(lnet_ping_info_t, pi_ni[n]);
1522 LIBCFS_ALLOC(pinfo, infosz);
1523 if (pinfo == NULL) {
1524 CERROR("Can't allocate ping info[%d]\n", n);
1525 return -ENOMEM;
1526 }
1527
1528 pinfo->pi_nnis = n;
1529 pinfo->pi_pid = the_lnet.ln_pid;
1530 pinfo->pi_magic = LNET_PROTO_PING_MAGIC;
1531 pinfo->pi_features = LNET_PING_FEAT_NI_STATUS;
1532
1533 for (i = 0; i < n; i++) {
1534 lnet_ni_status_t *ns = &pinfo->pi_ni[i];
1535
1536 rc = LNetGetId(i, &id);
3b7566d9 1537 LASSERT(rc == 0);
d7e09d03
PT
1538
1539 ns->ns_nid = id.nid;
1540 ns->ns_status = LNET_NI_STATUS_UP;
1541
1542 lnet_net_lock(0);
1543
1544 ni = lnet_nid2ni_locked(id.nid, 0);
1545 LASSERT(ni != NULL);
1546
1547 lnet_ni_lock(ni);
1548 LASSERT(ni->ni_status == NULL);
1549 ni->ni_status = ns;
1550 lnet_ni_unlock(ni);
1551
1552 lnet_ni_decref_locked(ni, 0);
1553 lnet_net_unlock(0);
1554 }
1555
1556 the_lnet.ln_ping_info = pinfo;
1557 return 0;
1558}
1559
1560static void
1561lnet_destroy_ping_info(void)
1562{
7e7ab095 1563 struct lnet_ni *ni;
d7e09d03
PT
1564
1565 lnet_net_lock(0);
1566
1567 list_for_each_entry(ni, &the_lnet.ln_nis, ni_list) {
1568 lnet_ni_lock(ni);
1569 ni->ni_status = NULL;
1570 lnet_ni_unlock(ni);
1571 }
1572
1573 lnet_net_unlock(0);
1574
1575 LIBCFS_FREE(the_lnet.ln_ping_info,
1576 offsetof(lnet_ping_info_t,
1577 pi_ni[the_lnet.ln_ping_info->pi_nnis]));
1578 the_lnet.ln_ping_info = NULL;
d7e09d03
PT
1579}
1580
1581int
1582lnet_ping_target_init(void)
1583{
7e7ab095
MS
1584 lnet_md_t md = { NULL };
1585 lnet_handle_me_t meh;
d7e09d03 1586 lnet_process_id_t id;
7e7ab095
MS
1587 int rc;
1588 int rc2;
1589 int infosz;
d7e09d03
PT
1590
1591 rc = lnet_create_ping_info();
1592 if (rc != 0)
1593 return rc;
1594
1595 /* We can have a tiny EQ since we only need to see the unlink event on
1596 * teardown, which by definition is the last one! */
1597 rc = LNetEQAlloc(2, LNET_EQ_HANDLER_NONE, &the_lnet.ln_ping_target_eq);
1598 if (rc != 0) {
1599 CERROR("Can't allocate ping EQ: %d\n", rc);
1600 goto failed_0;
1601 }
1602
1603 memset(&id, 0, sizeof(lnet_process_id_t));
1604 id.nid = LNET_NID_ANY;
1605 id.pid = LNET_PID_ANY;
1606
1607 rc = LNetMEAttach(LNET_RESERVED_PORTAL, id,
1608 LNET_PROTO_PING_MATCHBITS, 0,
1609 LNET_UNLINK, LNET_INS_AFTER,
1610 &meh);
1611 if (rc != 0) {
1612 CERROR("Can't create ping ME: %d\n", rc);
1613 goto failed_1;
1614 }
1615
1616 /* initialize md content */
1617 infosz = offsetof(lnet_ping_info_t,
1618 pi_ni[the_lnet.ln_ping_info->pi_nnis]);
1619 md.start = the_lnet.ln_ping_info;
1620 md.length = infosz;
1621 md.threshold = LNET_MD_THRESH_INF;
1622 md.max_size = 0;
1623 md.options = LNET_MD_OP_GET | LNET_MD_TRUNCATE |
1624 LNET_MD_MANAGE_REMOTE;
1625 md.user_ptr = NULL;
1626 md.eq_handle = the_lnet.ln_ping_target_eq;
1627
1628 rc = LNetMDAttach(meh, md,
1629 LNET_RETAIN,
1630 &the_lnet.ln_ping_target_md);
1631 if (rc != 0) {
1632 CERROR("Can't attach ping MD: %d\n", rc);
1633 goto failed_2;
1634 }
1635
1636 return 0;
1637
1638 failed_2:
1639 rc2 = LNetMEUnlink(meh);
3b7566d9 1640 LASSERT(rc2 == 0);
d7e09d03
PT
1641 failed_1:
1642 rc2 = LNetEQFree(the_lnet.ln_ping_target_eq);
3b7566d9 1643 LASSERT(rc2 == 0);
d7e09d03
PT
1644 failed_0:
1645 lnet_destroy_ping_info();
1646 return rc;
1647}
1648
1649void
1650lnet_ping_target_fini(void)
1651{
7e7ab095
MS
1652 lnet_event_t event;
1653 int rc;
1654 int which;
1655 int timeout_ms = 1000;
1656 sigset_t blocked = cfs_block_allsigs();
d7e09d03
PT
1657
1658 LNetMDUnlink(the_lnet.ln_ping_target_md);
1659 /* NB md could be busy; this just starts the unlink */
1660
1661 for (;;) {
1662 rc = LNetEQPoll(&the_lnet.ln_ping_target_eq, 1,
1663 timeout_ms, &event, &which);
1664
1665 /* I expect overflow... */
3b7566d9 1666 LASSERT(rc >= 0 || rc == -EOVERFLOW);
d7e09d03
PT
1667
1668 if (rc == 0) {
1669 /* timed out: provide a diagnostic */
1670 CWARN("Still waiting for ping MD to unlink\n");
1671 timeout_ms *= 2;
1672 continue;
1673 }
1674
1675 /* Got a valid event */
1676 if (event.unlinked)
1677 break;
1678 }
1679
1680 rc = LNetEQFree(the_lnet.ln_ping_target_eq);
3b7566d9 1681 LASSERT(rc == 0);
d7e09d03
PT
1682 lnet_destroy_ping_info();
1683 cfs_restore_sigs(blocked);
1684}
1685
1686int
3b7566d9 1687lnet_ping(lnet_process_id_t id, int timeout_ms, lnet_process_id_t *ids, int n_ids)
d7e09d03 1688{
7e7ab095
MS
1689 lnet_handle_eq_t eqh;
1690 lnet_handle_md_t mdh;
1691 lnet_event_t event;
1692 lnet_md_t md = { NULL };
1693 int which;
1694 int unlinked = 0;
1695 int replied = 0;
1696 const int a_long_time = 60000; /* mS */
1697 int infosz = offsetof(lnet_ping_info_t, pi_ni[n_ids]);
1698 lnet_ping_info_t *info;
1699 lnet_process_id_t tmpid;
1700 int i;
1701 int nob;
1702 int rc;
1703 int rc2;
1704 sigset_t blocked;
d7e09d03
PT
1705
1706 if (n_ids <= 0 ||
1707 id.nid == LNET_NID_ANY ||
1708 timeout_ms > 500000 || /* arbitrary limit! */
1709 n_ids > 20) /* arbitrary limit! */
1710 return -EINVAL;
1711
1712 if (id.pid == LNET_PID_ANY)
1713 id.pid = LUSTRE_SRV_LNET_PID;
1714
1715 LIBCFS_ALLOC(info, infosz);
1716 if (info == NULL)
1717 return -ENOMEM;
1718
1719 /* NB 2 events max (including any unlink event) */
1720 rc = LNetEQAlloc(2, LNET_EQ_HANDLER_NONE, &eqh);
1721 if (rc != 0) {
1722 CERROR("Can't allocate EQ: %d\n", rc);
1723 goto out_0;
1724 }
1725
1726 /* initialize md content */
1727 md.start = info;
1728 md.length = infosz;
1729 md.threshold = 2; /*GET/REPLY*/
1730 md.max_size = 0;
1731 md.options = LNET_MD_TRUNCATE;
1732 md.user_ptr = NULL;
1733 md.eq_handle = eqh;
1734
1735 rc = LNetMDBind(md, LNET_UNLINK, &mdh);
1736 if (rc != 0) {
1737 CERROR("Can't bind MD: %d\n", rc);
1738 goto out_1;
1739 }
1740
1741 rc = LNetGet(LNET_NID_ANY, mdh, id,
1742 LNET_RESERVED_PORTAL,
1743 LNET_PROTO_PING_MATCHBITS, 0);
1744
1745 if (rc != 0) {
1746 /* Don't CERROR; this could be deliberate! */
1747
1748 rc2 = LNetMDUnlink(mdh);
3b7566d9 1749 LASSERT(rc2 == 0);
d7e09d03
PT
1750
1751 /* NB must wait for the UNLINK event below... */
1752 unlinked = 1;
1753 timeout_ms = a_long_time;
1754 }
1755
1756 do {
1757 /* MUST block for unlink to complete */
1758 if (unlinked)
1759 blocked = cfs_block_allsigs();
1760
1761 rc2 = LNetEQPoll(&eqh, 1, timeout_ms, &event, &which);
1762
1763 if (unlinked)
1764 cfs_restore_sigs(blocked);
1765
1766 CDEBUG(D_NET, "poll %d(%d %d)%s\n", rc2,
1767 (rc2 <= 0) ? -1 : event.type,
1768 (rc2 <= 0) ? -1 : event.status,
1769 (rc2 > 0 && event.unlinked) ? " unlinked" : "");
1770
3b7566d9 1771 LASSERT(rc2 != -EOVERFLOW); /* can't miss anything */
d7e09d03
PT
1772
1773 if (rc2 <= 0 || event.status != 0) {
1774 /* timeout or error */
1775 if (!replied && rc == 0)
1776 rc = (rc2 < 0) ? rc2 :
1777 (rc2 == 0) ? -ETIMEDOUT :
1778 event.status;
1779
1780 if (!unlinked) {
1781 /* Ensure completion in finite time... */
1782 LNetMDUnlink(mdh);
1783 /* No assertion (racing with network) */
1784 unlinked = 1;
1785 timeout_ms = a_long_time;
1786 } else if (rc2 == 0) {
1787 /* timed out waiting for unlink */
1788 CWARN("ping %s: late network completion\n",
1789 libcfs_id2str(id));
1790 }
1791 } else if (event.type == LNET_EVENT_REPLY) {
1792 replied = 1;
1793 rc = event.mlength;
1794 }
1795
1796 } while (rc2 <= 0 || !event.unlinked);
1797
1798 if (!replied) {
1799 if (rc >= 0)
1800 CWARN("%s: Unexpected rc >= 0 but no reply!\n",
1801 libcfs_id2str(id));
1802 rc = -EIO;
1803 goto out_1;
1804 }
1805
1806 nob = rc;
3b7566d9 1807 LASSERT(nob >= 0 && nob <= infosz);
d7e09d03
PT
1808
1809 rc = -EPROTO; /* if I can't parse... */
1810
1811 if (nob < 8) {
1812 /* can't check magic/version */
1813 CERROR("%s: ping info too short %d\n",
1814 libcfs_id2str(id), nob);
1815 goto out_1;
1816 }
1817
1818 if (info->pi_magic == __swab32(LNET_PROTO_PING_MAGIC)) {
1819 lnet_swap_pinginfo(info);
1820 } else if (info->pi_magic != LNET_PROTO_PING_MAGIC) {
1821 CERROR("%s: Unexpected magic %08x\n",
1822 libcfs_id2str(id), info->pi_magic);
1823 goto out_1;
1824 }
1825
1826 if ((info->pi_features & LNET_PING_FEAT_NI_STATUS) == 0) {
1827 CERROR("%s: ping w/o NI status: 0x%x\n",
1828 libcfs_id2str(id), info->pi_features);
1829 goto out_1;
1830 }
1831
1832 if (nob < offsetof(lnet_ping_info_t, pi_ni[0])) {
1833 CERROR("%s: Short reply %d(%d min)\n", libcfs_id2str(id),
1834 nob, (int)offsetof(lnet_ping_info_t, pi_ni[0]));
1835 goto out_1;
1836 }
1837
1838 if (info->pi_nnis < n_ids)
1839 n_ids = info->pi_nnis;
1840
1841 if (nob < offsetof(lnet_ping_info_t, pi_ni[n_ids])) {
1842 CERROR("%s: Short reply %d(%d expected)\n", libcfs_id2str(id),
1843 nob, (int)offsetof(lnet_ping_info_t, pi_ni[n_ids]));
1844 goto out_1;
1845 }
1846
1847 rc = -EFAULT; /* If I SEGV... */
1848
751a624a 1849 memset(&tmpid, 0, sizeof(tmpid));
d7e09d03
PT
1850 for (i = 0; i < n_ids; i++) {
1851 tmpid.pid = info->pi_pid;
1852 tmpid.nid = info->pi_ni[i].ns_nid;
1853 if (copy_to_user(&ids[i], &tmpid, sizeof(tmpid)))
1854 goto out_1;
1855 }
1856 rc = info->pi_nnis;
1857
1858 out_1:
1859 rc2 = LNetEQFree(eqh);
1860 if (rc2 != 0)
1861 CERROR("rc2 %d\n", rc2);
3b7566d9 1862 LASSERT(rc2 == 0);
d7e09d03
PT
1863
1864 out_0:
1865 LIBCFS_FREE(info, infosz);
1866 return rc;
1867}
This page took 0.404207 seconds and 5 git commands to generate.