1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34#define DEBUG_SUBSYSTEM S_LNET
35#include <linux/log2.h>
36#include <linux/ktime.h>
37
38#include <linux/lnet/lib-lnet.h>
39#include <uapi/linux/lnet/lnet-dlc.h>
40
41#define D_LNI D_CONSOLE
42
43struct lnet the_lnet;
44EXPORT_SYMBOL(the_lnet);
45
46static char *ip2nets = "";
47module_param(ip2nets, charp, 0444);
48MODULE_PARM_DESC(ip2nets, "LNET network <- IP table");
49
50static char *networks = "";
51module_param(networks, charp, 0444);
52MODULE_PARM_DESC(networks, "local networks");
53
54static char *routes = "";
55module_param(routes, charp, 0444);
56MODULE_PARM_DESC(routes, "routes to non-local networks");
57
58static int rnet_htable_size = LNET_REMOTE_NETS_HASH_DEFAULT;
59module_param(rnet_htable_size, int, 0444);
60MODULE_PARM_DESC(rnet_htable_size, "size of remote network hash table");
61
62static int lnet_ping(struct lnet_process_id id, int timeout_ms,
63 struct lnet_process_id __user *ids, int n_ids);
64
65static char *
66lnet_get_routes(void)
67{
68 return routes;
69}
70
71static char *
72lnet_get_networks(void)
73{
74 char *nets;
75 int rc;
76
77 if (*networks && *ip2nets) {
78 LCONSOLE_ERROR_MSG(0x101, "Please specify EITHER 'networks' or 'ip2nets' but not both at once\n");
79 return NULL;
80 }
81
82 if (*ip2nets) {
83 rc = lnet_parse_ip2nets(&nets, ip2nets);
84 return !rc ? nets : NULL;
85 }
86
87 if (*networks)
88 return networks;
89
90 return "tcp";
91}
92
93static void
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 init_waitqueue_head(&the_lnet.ln_rc_waitq);
99 mutex_init(&the_lnet.ln_lnd_mutex);
100 mutex_init(&the_lnet.ln_api_mutex);
101}
102
103static int
104lnet_create_remote_nets_table(void)
105{
106 int i;
107 struct list_head *hash;
108
109 LASSERT(!the_lnet.ln_remote_nets_hash);
110 LASSERT(the_lnet.ln_remote_nets_hbits > 0);
111 hash = kvmalloc_array(LNET_REMOTE_NETS_HASH_SIZE, sizeof(*hash),
112 GFP_KERNEL);
113 if (!hash) {
114 CERROR("Failed to create remote nets hash table\n");
115 return -ENOMEM;
116 }
117
118 for (i = 0; i < LNET_REMOTE_NETS_HASH_SIZE; i++)
119 INIT_LIST_HEAD(&hash[i]);
120 the_lnet.ln_remote_nets_hash = hash;
121 return 0;
122}
123
124static void
125lnet_destroy_remote_nets_table(void)
126{
127 int i;
128
129 if (!the_lnet.ln_remote_nets_hash)
130 return;
131
132 for (i = 0; i < LNET_REMOTE_NETS_HASH_SIZE; i++)
133 LASSERT(list_empty(&the_lnet.ln_remote_nets_hash[i]));
134
135 kvfree(the_lnet.ln_remote_nets_hash);
136 the_lnet.ln_remote_nets_hash = NULL;
137}
138
139static void
140lnet_destroy_locks(void)
141{
142 if (the_lnet.ln_res_lock) {
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) {
148 cfs_percpt_lock_free(the_lnet.ln_net_lock);
149 the_lnet.ln_net_lock = NULL;
150 }
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)
160 goto failed;
161
162 the_lnet.ln_net_lock = cfs_percpt_lock_alloc(lnet_cpt_table());
163 if (!the_lnet.ln_net_lock)
164 goto failed;
165
166 return 0;
167
168 failed:
169 lnet_destroy_locks();
170 return -ENOMEM;
171}
172
173static void lnet_assert_wire_constants(void)
174{
175
176
177
178
179
180
181
182
183 BUILD_BUG_ON(LNET_PROTO_TCP_MAGIC != 0xeebc0ded);
184 BUILD_BUG_ON(LNET_PROTO_TCP_VERSION_MAJOR != 1);
185 BUILD_BUG_ON(LNET_PROTO_TCP_VERSION_MINOR != 0);
186 BUILD_BUG_ON(LNET_MSG_ACK != 0);
187 BUILD_BUG_ON(LNET_MSG_PUT != 1);
188 BUILD_BUG_ON(LNET_MSG_GET != 2);
189 BUILD_BUG_ON(LNET_MSG_REPLY != 3);
190 BUILD_BUG_ON(LNET_MSG_HELLO != 4);
191
192
193 BUILD_BUG_ON((int)sizeof(struct lnet_handle_wire) != 16);
194 BUILD_BUG_ON((int)offsetof(struct lnet_handle_wire, wh_interface_cookie) != 0);
195 BUILD_BUG_ON((int)sizeof(((struct lnet_handle_wire *)0)->wh_interface_cookie) != 8);
196 BUILD_BUG_ON((int)offsetof(struct lnet_handle_wire, wh_object_cookie) != 8);
197 BUILD_BUG_ON((int)sizeof(((struct lnet_handle_wire *)0)->wh_object_cookie) != 8);
198
199
200 BUILD_BUG_ON((int)sizeof(struct lnet_magicversion) != 8);
201 BUILD_BUG_ON((int)offsetof(struct lnet_magicversion, magic) != 0);
202 BUILD_BUG_ON((int)sizeof(((struct lnet_magicversion *)0)->magic) != 4);
203 BUILD_BUG_ON((int)offsetof(struct lnet_magicversion, version_major) != 4);
204 BUILD_BUG_ON((int)sizeof(((struct lnet_magicversion *)0)->version_major) != 2);
205 BUILD_BUG_ON((int)offsetof(struct lnet_magicversion, version_minor) != 6);
206 BUILD_BUG_ON((int)sizeof(((struct lnet_magicversion *)0)->version_minor) != 2);
207
208
209 BUILD_BUG_ON((int)sizeof(struct lnet_hdr) != 72);
210 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, dest_nid) != 0);
211 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->dest_nid) != 8);
212 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, src_nid) != 8);
213 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->src_nid) != 8);
214 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, dest_pid) != 16);
215 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->dest_pid) != 4);
216 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, src_pid) != 20);
217 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->src_pid) != 4);
218 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, type) != 24);
219 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->type) != 4);
220 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, payload_length) != 28);
221 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->payload_length) != 4);
222 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg) != 32);
223 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg) != 40);
224
225
226 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.ack.dst_wmd) != 32);
227 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.ack.dst_wmd) != 16);
228 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.ack.match_bits) != 48);
229 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.ack.match_bits) != 8);
230 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.ack.mlength) != 56);
231 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.ack.mlength) != 4);
232
233
234 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.put.ack_wmd) != 32);
235 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.put.ack_wmd) != 16);
236 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.put.match_bits) != 48);
237 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.put.match_bits) != 8);
238 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.put.hdr_data) != 56);
239 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.put.hdr_data) != 8);
240 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.put.ptl_index) != 64);
241 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.put.ptl_index) != 4);
242 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.put.offset) != 68);
243 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.put.offset) != 4);
244
245
246 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.get.return_wmd) != 32);
247 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.get.return_wmd) != 16);
248 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.get.match_bits) != 48);
249 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.get.match_bits) != 8);
250 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.get.ptl_index) != 56);
251 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.get.ptl_index) != 4);
252 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.get.src_offset) != 60);
253 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.get.src_offset) != 4);
254 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.get.sink_length) != 64);
255 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.get.sink_length) != 4);
256
257
258 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.reply.dst_wmd) != 32);
259 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.reply.dst_wmd) != 16);
260
261
262 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.hello.incarnation) != 32);
263 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.hello.incarnation) != 8);
264 BUILD_BUG_ON((int)offsetof(struct lnet_hdr, msg.hello.type) != 40);
265 BUILD_BUG_ON((int)sizeof(((struct lnet_hdr *)0)->msg.hello.type) != 4);
266}
267
268static struct lnet_lnd *
269lnet_find_lnd_by_type(__u32 type)
270{
271 struct lnet_lnd *lnd;
272 struct list_head *tmp;
273
274
275 list_for_each(tmp, &the_lnet.ln_lnds) {
276 lnd = list_entry(tmp, struct lnet_lnd, lnd_list);
277
278 if (lnd->lnd_type == type)
279 return lnd;
280 }
281
282 return NULL;
283}
284
285void
286lnet_register_lnd(struct lnet_lnd *lnd)
287{
288 mutex_lock(&the_lnet.ln_lnd_mutex);
289
290 LASSERT(libcfs_isknown_lnd(lnd->lnd_type));
291 LASSERT(!lnet_find_lnd_by_type(lnd->lnd_type));
292
293 list_add_tail(&lnd->lnd_list, &the_lnet.ln_lnds);
294 lnd->lnd_refcount = 0;
295
296 CDEBUG(D_NET, "%s LND registered\n", libcfs_lnd2str(lnd->lnd_type));
297
298 mutex_unlock(&the_lnet.ln_lnd_mutex);
299}
300EXPORT_SYMBOL(lnet_register_lnd);
301
302void
303lnet_unregister_lnd(struct lnet_lnd *lnd)
304{
305 mutex_lock(&the_lnet.ln_lnd_mutex);
306
307 LASSERT(lnet_find_lnd_by_type(lnd->lnd_type) == lnd);
308 LASSERT(!lnd->lnd_refcount);
309
310 list_del(&lnd->lnd_list);
311 CDEBUG(D_NET, "%s LND unregistered\n", libcfs_lnd2str(lnd->lnd_type));
312
313 mutex_unlock(&the_lnet.ln_lnd_mutex);
314}
315EXPORT_SYMBOL(lnet_unregister_lnd);
316
317void
318lnet_counters_get(struct lnet_counters *counters)
319{
320 struct lnet_counters *ctr;
321 int i;
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;
334 counters->drop_count += ctr->drop_count;
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 lnet_net_unlock(LNET_LOCK_EX);
341}
342EXPORT_SYMBOL(lnet_counters_get);
343
344void
345lnet_counters_reset(void)
346{
347 struct lnet_counters *counters;
348 int i;
349
350 lnet_net_lock(LNET_LOCK_EX);
351
352 cfs_percpt_for_each(counters, i, the_lnet.ln_counters)
353 memset(counters, 0, sizeof(struct lnet_counters));
354
355 lnet_net_unlock(LNET_LOCK_EX);
356}
357
358static char *
359lnet_res_type2str(int type)
360{
361 switch (type) {
362 default:
363 LBUG();
364 case LNET_COOKIE_TYPE_MD:
365 return "MD";
366 case LNET_COOKIE_TYPE_ME:
367 return "ME";
368 case LNET_COOKIE_TYPE_EQ:
369 return "EQ";
370 }
371}
372
373static void
374lnet_res_container_cleanup(struct lnet_res_container *rec)
375{
376 int count = 0;
377
378 if (!rec->rec_type)
379 return;
380
381 while (!list_empty(&rec->rec_active)) {
382 struct list_head *e = rec->rec_active.next;
383
384 list_del_init(e);
385 if (rec->rec_type == LNET_COOKIE_TYPE_EQ) {
386 kfree(list_entry(e, struct lnet_eq, eq_list));
387
388 } else if (rec->rec_type == LNET_COOKIE_TYPE_MD) {
389 kfree(list_entry(e, struct lnet_libmd, md_list));
390
391 } else {
392 LBUG();
393 }
394 count++;
395 }
396
397 if (count > 0) {
398
399
400
401
402
403 CERROR("%d active elements on exit of %s container\n",
404 count, lnet_res_type2str(rec->rec_type));
405 }
406
407 kfree(rec->rec_lh_hash);
408 rec->rec_lh_hash = NULL;
409
410 rec->rec_type = 0;
411}
412
413static int
414lnet_res_container_setup(struct lnet_res_container *rec, int cpt, int type)
415{
416 int rc = 0;
417 int i;
418
419 LASSERT(!rec->rec_type);
420
421 rec->rec_type = type;
422 INIT_LIST_HEAD(&rec->rec_active);
423 rec->rec_lh_cookie = (cpt << LNET_COOKIE_TYPE_BITS) | type;
424
425
426 rec->rec_lh_hash = kvmalloc_cpt(LNET_LH_HASH_SIZE * sizeof(rec->rec_lh_hash[0]),
427 GFP_KERNEL, cpt);
428 if (!rec->rec_lh_hash) {
429 rc = -ENOMEM;
430 goto out;
431 }
432
433 for (i = 0; i < LNET_LH_HASH_SIZE; i++)
434 INIT_LIST_HEAD(&rec->rec_lh_hash[i]);
435
436 return 0;
437
438out:
439 CERROR("Failed to setup %s resource container\n",
440 lnet_res_type2str(type));
441 lnet_res_container_cleanup(rec);
442 return rc;
443}
444
445static void
446lnet_res_containers_destroy(struct lnet_res_container **recs)
447{
448 struct lnet_res_container *rec;
449 int i;
450
451 cfs_percpt_for_each(rec, i, recs)
452 lnet_res_container_cleanup(rec);
453
454 cfs_percpt_free(recs);
455}
456
457static struct lnet_res_container **
458lnet_res_containers_create(int type)
459{
460 struct lnet_res_container **recs;
461 struct lnet_res_container *rec;
462 int rc;
463 int i;
464
465 recs = cfs_percpt_alloc(lnet_cpt_table(), sizeof(*rec));
466 if (!recs) {
467 CERROR("Failed to allocate %s resource containers\n",
468 lnet_res_type2str(type));
469 return NULL;
470 }
471
472 cfs_percpt_for_each(rec, i, recs) {
473 rc = lnet_res_container_setup(rec, i, type);
474 if (rc) {
475 lnet_res_containers_destroy(recs);
476 return NULL;
477 }
478 }
479
480 return recs;
481}
482
483struct lnet_libhandle *
484lnet_res_lh_lookup(struct lnet_res_container *rec, __u64 cookie)
485{
486
487 struct list_head *head;
488 struct lnet_libhandle *lh;
489 unsigned int hash;
490
491 if ((cookie & LNET_COOKIE_MASK) != rec->rec_type)
492 return NULL;
493
494 hash = cookie >> (LNET_COOKIE_TYPE_BITS + LNET_CPT_BITS);
495 head = &rec->rec_lh_hash[hash & LNET_LH_HASH_MASK];
496
497 list_for_each_entry(lh, head, lh_hash_chain) {
498 if (lh->lh_cookie == cookie)
499 return lh;
500 }
501
502 return NULL;
503}
504
505void
506lnet_res_lh_initialize(struct lnet_res_container *rec,
507 struct lnet_libhandle *lh)
508{
509
510 unsigned int ibits = LNET_COOKIE_TYPE_BITS + LNET_CPT_BITS;
511 unsigned int hash;
512
513 lh->lh_cookie = rec->rec_lh_cookie;
514 rec->rec_lh_cookie += 1 << ibits;
515
516 hash = (lh->lh_cookie >> ibits) & LNET_LH_HASH_MASK;
517
518 list_add(&lh->lh_hash_chain, &rec->rec_lh_hash[hash]);
519}
520
521static int lnet_unprepare(void);
522
523static int
524lnet_prepare(lnet_pid_t requested_pid)
525{
526
527 struct lnet_res_container **recs;
528 int rc = 0;
529
530 if (requested_pid == LNET_PID_ANY) {
531
532 return -ENETDOWN;
533 }
534
535 LASSERT(!the_lnet.ln_refcount);
536
537 the_lnet.ln_routing = 0;
538
539 LASSERT(!(requested_pid & LNET_PID_USERFLAG));
540 the_lnet.ln_pid = requested_pid;
541
542 INIT_LIST_HEAD(&the_lnet.ln_test_peers);
543 INIT_LIST_HEAD(&the_lnet.ln_nis);
544 INIT_LIST_HEAD(&the_lnet.ln_nis_cpt);
545 INIT_LIST_HEAD(&the_lnet.ln_nis_zombie);
546 INIT_LIST_HEAD(&the_lnet.ln_routers);
547 INIT_LIST_HEAD(&the_lnet.ln_drop_rules);
548 INIT_LIST_HEAD(&the_lnet.ln_delay_rules);
549
550 rc = lnet_create_remote_nets_table();
551 if (rc)
552 goto failed;
553
554
555
556
557 the_lnet.ln_interface_cookie = ktime_get_ns();
558
559 the_lnet.ln_counters = cfs_percpt_alloc(lnet_cpt_table(),
560 sizeof(struct lnet_counters));
561 if (!the_lnet.ln_counters) {
562 CERROR("Failed to allocate counters for LNet\n");
563 rc = -ENOMEM;
564 goto failed;
565 }
566
567 rc = lnet_peer_tables_create();
568 if (rc)
569 goto failed;
570
571 rc = lnet_msg_containers_create();
572 if (rc)
573 goto failed;
574
575 rc = lnet_res_container_setup(&the_lnet.ln_eq_container, 0,
576 LNET_COOKIE_TYPE_EQ);
577 if (rc)
578 goto failed;
579
580 recs = lnet_res_containers_create(LNET_COOKIE_TYPE_ME);
581 if (!recs) {
582 rc = -ENOMEM;
583 goto failed;
584 }
585
586 the_lnet.ln_me_containers = recs;
587
588 recs = lnet_res_containers_create(LNET_COOKIE_TYPE_MD);
589 if (!recs) {
590 rc = -ENOMEM;
591 goto failed;
592 }
593
594 the_lnet.ln_md_containers = recs;
595
596 rc = lnet_portals_create();
597 if (rc) {
598 CERROR("Failed to create portals for LNet: %d\n", rc);
599 goto failed;
600 }
601
602 return 0;
603
604 failed:
605 lnet_unprepare();
606 return rc;
607}
608
609static int
610lnet_unprepare(void)
611{
612
613
614
615
616
617
618 lnet_fail_nid(LNET_NID_ANY, 0);
619
620 LASSERT(!the_lnet.ln_refcount);
621 LASSERT(list_empty(&the_lnet.ln_test_peers));
622 LASSERT(list_empty(&the_lnet.ln_nis));
623 LASSERT(list_empty(&the_lnet.ln_nis_cpt));
624 LASSERT(list_empty(&the_lnet.ln_nis_zombie));
625
626 lnet_portals_destroy();
627
628 if (the_lnet.ln_md_containers) {
629 lnet_res_containers_destroy(the_lnet.ln_md_containers);
630 the_lnet.ln_md_containers = NULL;
631 }
632
633 if (the_lnet.ln_me_containers) {
634 lnet_res_containers_destroy(the_lnet.ln_me_containers);
635 the_lnet.ln_me_containers = NULL;
636 }
637
638 lnet_res_container_cleanup(&the_lnet.ln_eq_container);
639
640 lnet_msg_containers_destroy();
641 lnet_peer_tables_destroy();
642 lnet_rtrpools_free(0);
643
644 if (the_lnet.ln_counters) {
645 cfs_percpt_free(the_lnet.ln_counters);
646 the_lnet.ln_counters = NULL;
647 }
648 lnet_destroy_remote_nets_table();
649
650 return 0;
651}
652
653struct lnet_ni *
654lnet_net2ni_locked(__u32 net, int cpt)
655{
656 struct list_head *tmp;
657 struct lnet_ni *ni;
658
659 LASSERT(cpt != LNET_LOCK_EX);
660
661 list_for_each(tmp, &the_lnet.ln_nis) {
662 ni = list_entry(tmp, struct lnet_ni, ni_list);
663
664 if (LNET_NIDNET(ni->ni_nid) == net) {
665 lnet_ni_addref_locked(ni, cpt);
666 return ni;
667 }
668 }
669
670 return NULL;
671}
672
673struct lnet_ni *
674lnet_net2ni(__u32 net)
675{
676 struct lnet_ni *ni;
677
678 lnet_net_lock(0);
679 ni = lnet_net2ni_locked(net, 0);
680 lnet_net_unlock(0);
681
682 return ni;
683}
684EXPORT_SYMBOL(lnet_net2ni);
685
686static unsigned int
687lnet_nid_cpt_hash(lnet_nid_t nid, unsigned int number)
688{
689 __u64 key = nid;
690 unsigned int val;
691
692 LASSERT(number >= 1 && number <= LNET_CPT_NUMBER);
693
694 if (number == 1)
695 return 0;
696
697 val = hash_long(key, LNET_CPT_BITS);
698
699 if (val < number)
700 return val;
701
702 return (unsigned int)(key + val + (val >> 1)) % number;
703}
704
705int
706lnet_cpt_of_nid_locked(lnet_nid_t nid)
707{
708 struct lnet_ni *ni;
709
710
711 if (LNET_CPT_NUMBER == 1)
712 return 0;
713
714
715 if (!list_empty(&the_lnet.ln_nis_cpt)) {
716 list_for_each_entry(ni, &the_lnet.ln_nis_cpt, ni_cptlist) {
717 if (LNET_NIDNET(ni->ni_nid) != LNET_NIDNET(nid))
718 continue;
719
720 LASSERT(ni->ni_cpts);
721 return ni->ni_cpts[lnet_nid_cpt_hash
722 (nid, ni->ni_ncpts)];
723 }
724 }
725
726 return lnet_nid_cpt_hash(nid, LNET_CPT_NUMBER);
727}
728
729int
730lnet_cpt_of_nid(lnet_nid_t nid)
731{
732 int cpt;
733 int cpt2;
734
735 if (LNET_CPT_NUMBER == 1)
736 return 0;
737
738 if (list_empty(&the_lnet.ln_nis_cpt))
739 return lnet_nid_cpt_hash(nid, LNET_CPT_NUMBER);
740
741 cpt = lnet_net_lock_current();
742 cpt2 = lnet_cpt_of_nid_locked(nid);
743 lnet_net_unlock(cpt);
744
745 return cpt2;
746}
747EXPORT_SYMBOL(lnet_cpt_of_nid);
748
749int
750lnet_islocalnet(__u32 net)
751{
752 struct lnet_ni *ni;
753 int cpt;
754
755 cpt = lnet_net_lock_current();
756
757 ni = lnet_net2ni_locked(net, cpt);
758 if (ni)
759 lnet_ni_decref_locked(ni, cpt);
760
761 lnet_net_unlock(cpt);
762
763 return !!ni;
764}
765
766struct lnet_ni *
767lnet_nid2ni_locked(lnet_nid_t nid, int cpt)
768{
769 struct lnet_ni *ni;
770 struct list_head *tmp;
771
772 LASSERT(cpt != LNET_LOCK_EX);
773
774 list_for_each(tmp, &the_lnet.ln_nis) {
775 ni = list_entry(tmp, struct lnet_ni, ni_list);
776
777 if (ni->ni_nid == nid) {
778 lnet_ni_addref_locked(ni, cpt);
779 return ni;
780 }
781 }
782
783 return NULL;
784}
785
786int
787lnet_islocalnid(lnet_nid_t nid)
788{
789 struct lnet_ni *ni;
790 int cpt;
791
792 cpt = lnet_net_lock_current();
793 ni = lnet_nid2ni_locked(nid, cpt);
794 if (ni)
795 lnet_ni_decref_locked(ni, cpt);
796 lnet_net_unlock(cpt);
797
798 return !!ni;
799}
800
801int
802lnet_count_acceptor_nis(void)
803{
804
805 int count = 0;
806 struct list_head *tmp;
807 struct lnet_ni *ni;
808 int cpt;
809
810 cpt = lnet_net_lock_current();
811 list_for_each(tmp, &the_lnet.ln_nis) {
812 ni = list_entry(tmp, struct lnet_ni, ni_list);
813
814 if (ni->ni_lnd->lnd_accept)
815 count++;
816 }
817
818 lnet_net_unlock(cpt);
819
820 return count;
821}
822
823static struct lnet_ping_info *
824lnet_ping_info_create(int num_ni)
825{
826 struct lnet_ping_info *ping_info;
827 unsigned int infosz;
828
829 infosz = offsetof(struct lnet_ping_info, pi_ni[num_ni]);
830 ping_info = kvzalloc(infosz, GFP_KERNEL);
831 if (!ping_info) {
832 CERROR("Can't allocate ping info[%d]\n", num_ni);
833 return NULL;
834 }
835
836 ping_info->pi_nnis = num_ni;
837 ping_info->pi_pid = the_lnet.ln_pid;
838 ping_info->pi_magic = LNET_PROTO_PING_MAGIC;
839 ping_info->pi_features = LNET_PING_FEAT_NI_STATUS;
840
841 return ping_info;
842}
843
844static inline int
845lnet_get_ni_count(void)
846{
847 struct lnet_ni *ni;
848 int count = 0;
849
850 lnet_net_lock(0);
851
852 list_for_each_entry(ni, &the_lnet.ln_nis, ni_list)
853 count++;
854
855 lnet_net_unlock(0);
856
857 return count;
858}
859
860static inline void
861lnet_ping_info_free(struct lnet_ping_info *pinfo)
862{
863 kvfree(pinfo);
864}
865
866static void
867lnet_ping_info_destroy(void)
868{
869 struct lnet_ni *ni;
870
871 lnet_net_lock(LNET_LOCK_EX);
872
873 list_for_each_entry(ni, &the_lnet.ln_nis, ni_list) {
874 lnet_ni_lock(ni);
875 ni->ni_status = NULL;
876 lnet_ni_unlock(ni);
877 }
878
879 lnet_ping_info_free(the_lnet.ln_ping_info);
880 the_lnet.ln_ping_info = NULL;
881
882 lnet_net_unlock(LNET_LOCK_EX);
883}
884
885static void
886lnet_ping_event_handler(struct lnet_event *event)
887{
888 struct lnet_ping_info *pinfo = event->md.user_ptr;
889
890 if (event->unlinked)
891 pinfo->pi_features = LNET_PING_FEAT_INVAL;
892}
893
894static int
895lnet_ping_info_setup(struct lnet_ping_info **ppinfo,
896 struct lnet_handle_md *md_handle,
897 int ni_count, bool set_eq)
898{
899 struct lnet_process_id id = {LNET_NID_ANY, LNET_PID_ANY};
900 struct lnet_handle_me me_handle;
901 struct lnet_md md = { NULL };
902 int rc, rc2;
903
904 if (set_eq) {
905 rc = LNetEQAlloc(0, lnet_ping_event_handler,
906 &the_lnet.ln_ping_target_eq);
907 if (rc) {
908 CERROR("Can't allocate ping EQ: %d\n", rc);
909 return rc;
910 }
911 }
912
913 *ppinfo = lnet_ping_info_create(ni_count);
914 if (!*ppinfo) {
915 rc = -ENOMEM;
916 goto failed_0;
917 }
918
919 rc = LNetMEAttach(LNET_RESERVED_PORTAL, id,
920 LNET_PROTO_PING_MATCHBITS, 0,
921 LNET_UNLINK, LNET_INS_AFTER,
922 &me_handle);
923 if (rc) {
924 CERROR("Can't create ping ME: %d\n", rc);
925 goto failed_1;
926 }
927
928
929 md.start = *ppinfo;
930 md.length = offsetof(struct lnet_ping_info,
931 pi_ni[(*ppinfo)->pi_nnis]);
932 md.threshold = LNET_MD_THRESH_INF;
933 md.max_size = 0;
934 md.options = LNET_MD_OP_GET | LNET_MD_TRUNCATE |
935 LNET_MD_MANAGE_REMOTE;
936 md.user_ptr = NULL;
937 md.eq_handle = the_lnet.ln_ping_target_eq;
938 md.user_ptr = *ppinfo;
939
940 rc = LNetMDAttach(me_handle, md, LNET_RETAIN, md_handle);
941 if (rc) {
942 CERROR("Can't attach ping MD: %d\n", rc);
943 goto failed_2;
944 }
945
946 return 0;
947
948failed_2:
949 rc2 = LNetMEUnlink(me_handle);
950 LASSERT(!rc2);
951failed_1:
952 lnet_ping_info_free(*ppinfo);
953 *ppinfo = NULL;
954failed_0:
955 if (set_eq)
956 LNetEQFree(the_lnet.ln_ping_target_eq);
957 return rc;
958}
959
960static void
961lnet_ping_md_unlink(struct lnet_ping_info *pinfo,
962 struct lnet_handle_md *md_handle)
963{
964 sigset_t blocked = cfs_block_allsigs();
965
966 LNetMDUnlink(*md_handle);
967 LNetInvalidateMDHandle(md_handle);
968
969
970 while (pinfo->pi_features != LNET_PING_FEAT_INVAL) {
971 CDEBUG(D_NET, "Still waiting for ping MD to unlink\n");
972 set_current_state(TASK_UNINTERRUPTIBLE);
973 schedule_timeout(cfs_time_seconds(1));
974 }
975
976 cfs_restore_sigs(blocked);
977}
978
979static void
980lnet_ping_info_install_locked(struct lnet_ping_info *ping_info)
981{
982 struct lnet_ni_status *ns;
983 struct lnet_ni *ni;
984 int i = 0;
985
986 list_for_each_entry(ni, &the_lnet.ln_nis, ni_list) {
987 LASSERT(i < ping_info->pi_nnis);
988
989 ns = &ping_info->pi_ni[i];
990
991 ns->ns_nid = ni->ni_nid;
992
993 lnet_ni_lock(ni);
994 ns->ns_status = (ni->ni_status) ?
995 ni->ni_status->ns_status : LNET_NI_STATUS_UP;
996 ni->ni_status = ns;
997 lnet_ni_unlock(ni);
998
999 i++;
1000 }
1001}
1002
1003static void
1004lnet_ping_target_update(struct lnet_ping_info *pinfo,
1005 struct lnet_handle_md md_handle)
1006{
1007 struct lnet_ping_info *old_pinfo = NULL;
1008 struct lnet_handle_md old_md;
1009
1010
1011 lnet_net_lock(LNET_LOCK_EX);
1012
1013 if (!the_lnet.ln_routing)
1014 pinfo->pi_features |= LNET_PING_FEAT_RTE_DISABLED;
1015 lnet_ping_info_install_locked(pinfo);
1016
1017 if (the_lnet.ln_ping_info) {
1018 old_pinfo = the_lnet.ln_ping_info;
1019 old_md = the_lnet.ln_ping_target_md;
1020 }
1021 the_lnet.ln_ping_target_md = md_handle;
1022 the_lnet.ln_ping_info = pinfo;
1023
1024 lnet_net_unlock(LNET_LOCK_EX);
1025
1026 if (old_pinfo) {
1027
1028 lnet_ping_md_unlink(old_pinfo, &old_md);
1029 lnet_ping_info_free(old_pinfo);
1030 }
1031}
1032
1033static void
1034lnet_ping_target_fini(void)
1035{
1036 int rc;
1037
1038 lnet_ping_md_unlink(the_lnet.ln_ping_info,
1039 &the_lnet.ln_ping_target_md);
1040
1041 rc = LNetEQFree(the_lnet.ln_ping_target_eq);
1042 LASSERT(!rc);
1043
1044 lnet_ping_info_destroy();
1045}
1046
1047static int
1048lnet_ni_tq_credits(struct lnet_ni *ni)
1049{
1050 int credits;
1051
1052 LASSERT(ni->ni_ncpts >= 1);
1053
1054 if (ni->ni_ncpts == 1)
1055 return ni->ni_maxtxcredits;
1056
1057 credits = ni->ni_maxtxcredits / ni->ni_ncpts;
1058 credits = max(credits, 8 * ni->ni_peertxcredits);
1059 credits = min(credits, ni->ni_maxtxcredits);
1060
1061 return credits;
1062}
1063
1064static void
1065lnet_ni_unlink_locked(struct lnet_ni *ni)
1066{
1067 if (!list_empty(&ni->ni_cptlist)) {
1068 list_del_init(&ni->ni_cptlist);
1069 lnet_ni_decref_locked(ni, 0);
1070 }
1071
1072
1073 LASSERT(!list_empty(&ni->ni_list));
1074 list_move(&ni->ni_list, &the_lnet.ln_nis_zombie);
1075 lnet_ni_decref_locked(ni, 0);
1076}
1077
1078static void
1079lnet_clear_zombies_nis_locked(void)
1080{
1081 int i;
1082 int islo;
1083 struct lnet_ni *ni;
1084 struct lnet_ni *temp;
1085
1086
1087
1088
1089
1090 i = 2;
1091 list_for_each_entry_safe(ni, temp, &the_lnet.ln_nis_zombie, ni_list) {
1092 int *ref;
1093 int j;
1094
1095 list_del_init(&ni->ni_list);
1096 cfs_percpt_for_each(ref, j, ni->ni_refs) {
1097 if (!*ref)
1098 continue;
1099
1100 list_add(&ni->ni_list, &the_lnet.ln_nis_zombie);
1101 break;
1102 }
1103
1104 if (!list_empty(&ni->ni_list)) {
1105 lnet_net_unlock(LNET_LOCK_EX);
1106 ++i;
1107 if ((i & (-i)) == i) {
1108 CDEBUG(D_WARNING, "Waiting for zombie LNI %s\n",
1109 libcfs_nid2str(ni->ni_nid));
1110 }
1111 set_current_state(TASK_UNINTERRUPTIBLE);
1112 schedule_timeout(cfs_time_seconds(1));
1113 lnet_net_lock(LNET_LOCK_EX);
1114 continue;
1115 }
1116
1117 ni->ni_lnd->lnd_refcount--;
1118 lnet_net_unlock(LNET_LOCK_EX);
1119
1120 islo = ni->ni_lnd->lnd_type == LOLND;
1121
1122 LASSERT(!in_interrupt());
1123 ni->ni_lnd->lnd_shutdown(ni);
1124
1125
1126
1127
1128
1129 if (!islo)
1130 CDEBUG(D_LNI, "Removed LNI %s\n",
1131 libcfs_nid2str(ni->ni_nid));
1132
1133 lnet_ni_free(ni);
1134 i = 2;
1135
1136 lnet_net_lock(LNET_LOCK_EX);
1137 }
1138}
1139
1140static void
1141lnet_shutdown_lndnis(void)
1142{
1143 struct lnet_ni *ni;
1144 struct lnet_ni *temp;
1145 int i;
1146
1147
1148
1149
1150 LASSERT(!the_lnet.ln_shutdown);
1151 LASSERT(!the_lnet.ln_refcount);
1152 LASSERT(list_empty(&the_lnet.ln_nis_zombie));
1153
1154 lnet_net_lock(LNET_LOCK_EX);
1155 the_lnet.ln_shutdown = 1;
1156
1157
1158 list_for_each_entry_safe(ni, temp, &the_lnet.ln_nis, ni_list) {
1159 lnet_ni_unlink_locked(ni);
1160 }
1161
1162
1163 if (the_lnet.ln_loni) {
1164 lnet_ni_decref_locked(the_lnet.ln_loni, 0);
1165 the_lnet.ln_loni = NULL;
1166 }
1167
1168 lnet_net_unlock(LNET_LOCK_EX);
1169
1170
1171
1172
1173
1174 for (i = 0; i < the_lnet.ln_nportals; i++)
1175 LNetClearLazyPortal(i);
1176
1177
1178
1179
1180
1181 lnet_peer_tables_cleanup(NULL);
1182
1183 lnet_net_lock(LNET_LOCK_EX);
1184
1185 lnet_clear_zombies_nis_locked();
1186 the_lnet.ln_shutdown = 0;
1187 lnet_net_unlock(LNET_LOCK_EX);
1188}
1189
1190
1191static void
1192lnet_shutdown_lndni(struct lnet_ni *ni)
1193{
1194 int i;
1195
1196 lnet_net_lock(LNET_LOCK_EX);
1197 lnet_ni_unlink_locked(ni);
1198 lnet_net_unlock(LNET_LOCK_EX);
1199
1200
1201 for (i = 0; i < the_lnet.ln_nportals; i++)
1202 lnet_clear_lazy_portal(ni, i, "Shutting down NI");
1203
1204
1205 lnet_peer_tables_cleanup(ni);
1206
1207 lnet_net_lock(LNET_LOCK_EX);
1208 lnet_clear_zombies_nis_locked();
1209 lnet_net_unlock(LNET_LOCK_EX);
1210}
1211
1212static int
1213lnet_startup_lndni(struct lnet_ni *ni, struct lnet_ioctl_config_data *conf)
1214{
1215 struct lnet_ioctl_config_lnd_tunables *lnd_tunables = NULL;
1216 int rc = -EINVAL;
1217 int lnd_type;
1218 struct lnet_lnd *lnd;
1219 struct lnet_tx_queue *tq;
1220 int i;
1221
1222 lnd_type = LNET_NETTYP(LNET_NIDNET(ni->ni_nid));
1223
1224 LASSERT(libcfs_isknown_lnd(lnd_type));
1225
1226 if (lnd_type == CIBLND || lnd_type == OPENIBLND ||
1227 lnd_type == IIBLND || lnd_type == VIBLND) {
1228 CERROR("LND %s obsoleted\n", libcfs_lnd2str(lnd_type));
1229 goto failed0;
1230 }
1231
1232
1233 lnet_net_lock(LNET_LOCK_EX);
1234 rc = lnet_net_unique(LNET_NIDNET(ni->ni_nid), &the_lnet.ln_nis);
1235 lnet_net_unlock(LNET_LOCK_EX);
1236 if (!rc) {
1237 if (lnd_type == LOLND) {
1238 lnet_ni_free(ni);
1239 return 0;
1240 }
1241
1242 CERROR("Net %s is not unique\n",
1243 libcfs_net2str(LNET_NIDNET(ni->ni_nid)));
1244 rc = -EEXIST;
1245 goto failed0;
1246 }
1247
1248 mutex_lock(&the_lnet.ln_lnd_mutex);
1249 lnd = lnet_find_lnd_by_type(lnd_type);
1250
1251 if (!lnd) {
1252 mutex_unlock(&the_lnet.ln_lnd_mutex);
1253 rc = request_module("%s", libcfs_lnd2modname(lnd_type));
1254 mutex_lock(&the_lnet.ln_lnd_mutex);
1255
1256 lnd = lnet_find_lnd_by_type(lnd_type);
1257 if (!lnd) {
1258 mutex_unlock(&the_lnet.ln_lnd_mutex);
1259 CERROR("Can't load LND %s, module %s, rc=%d\n",
1260 libcfs_lnd2str(lnd_type),
1261 libcfs_lnd2modname(lnd_type), rc);
1262 rc = -EINVAL;
1263 goto failed0;
1264 }
1265 }
1266
1267 lnet_net_lock(LNET_LOCK_EX);
1268 lnd->lnd_refcount++;
1269 lnet_net_unlock(LNET_LOCK_EX);
1270
1271 ni->ni_lnd = lnd;
1272
1273 if (conf && conf->cfg_hdr.ioc_len > sizeof(*conf))
1274 lnd_tunables = (struct lnet_ioctl_config_lnd_tunables *)conf->cfg_bulk;
1275
1276 if (lnd_tunables) {
1277 ni->ni_lnd_tunables = kzalloc(sizeof(*ni->ni_lnd_tunables),
1278 GFP_NOFS);
1279 if (!ni->ni_lnd_tunables) {
1280 mutex_unlock(&the_lnet.ln_lnd_mutex);
1281 rc = -ENOMEM;
1282 goto failed0;
1283 }
1284 memcpy(ni->ni_lnd_tunables, lnd_tunables,
1285 sizeof(*ni->ni_lnd_tunables));
1286 }
1287
1288
1289
1290
1291
1292 if (conf) {
1293 if (conf->cfg_config_u.cfg_net.net_peer_rtr_credits >= 0)
1294 ni->ni_peerrtrcredits =
1295 conf->cfg_config_u.cfg_net.net_peer_rtr_credits;
1296 if (conf->cfg_config_u.cfg_net.net_peer_timeout >= 0)
1297 ni->ni_peertimeout =
1298 conf->cfg_config_u.cfg_net.net_peer_timeout;
1299 if (conf->cfg_config_u.cfg_net.net_peer_tx_credits != -1)
1300 ni->ni_peertxcredits =
1301 conf->cfg_config_u.cfg_net.net_peer_tx_credits;
1302 if (conf->cfg_config_u.cfg_net.net_max_tx_credits >= 0)
1303 ni->ni_maxtxcredits =
1304 conf->cfg_config_u.cfg_net.net_max_tx_credits;
1305 }
1306
1307 rc = lnd->lnd_startup(ni);
1308
1309 mutex_unlock(&the_lnet.ln_lnd_mutex);
1310
1311 if (rc) {
1312 LCONSOLE_ERROR_MSG(0x105, "Error %d starting up LNI %s\n",
1313 rc, libcfs_lnd2str(lnd->lnd_type));
1314 lnet_net_lock(LNET_LOCK_EX);
1315 lnd->lnd_refcount--;
1316 lnet_net_unlock(LNET_LOCK_EX);
1317 goto failed0;
1318 }
1319
1320 LASSERT(ni->ni_peertimeout <= 0 || lnd->lnd_query);
1321
1322 lnet_net_lock(LNET_LOCK_EX);
1323
1324 lnet_ni_addref_locked(ni, 0);
1325 list_add_tail(&ni->ni_list, &the_lnet.ln_nis);
1326 if (ni->ni_cpts) {
1327 lnet_ni_addref_locked(ni, 0);
1328 list_add_tail(&ni->ni_cptlist, &the_lnet.ln_nis_cpt);
1329 }
1330
1331 lnet_net_unlock(LNET_LOCK_EX);
1332
1333 if (lnd->lnd_type == LOLND) {
1334 lnet_ni_addref(ni);
1335 LASSERT(!the_lnet.ln_loni);
1336 the_lnet.ln_loni = ni;
1337 return 0;
1338 }
1339
1340 if (!ni->ni_peertxcredits || !ni->ni_maxtxcredits) {
1341 LCONSOLE_ERROR_MSG(0x107, "LNI %s has no %scredits\n",
1342 libcfs_lnd2str(lnd->lnd_type),
1343 !ni->ni_peertxcredits ?
1344 "" : "per-peer ");
1345
1346
1347
1348
1349 lnet_shutdown_lndni(ni);
1350 return -EINVAL;
1351 }
1352
1353 cfs_percpt_for_each(tq, i, ni->ni_tx_queues) {
1354 tq->tq_credits_min =
1355 tq->tq_credits_max =
1356 tq->tq_credits = lnet_ni_tq_credits(ni);
1357 }
1358
1359 CDEBUG(D_LNI, "Added LNI %s [%d/%d/%d/%d]\n",
1360 libcfs_nid2str(ni->ni_nid), ni->ni_peertxcredits,
1361 lnet_ni_tq_credits(ni) * LNET_CPT_NUMBER,
1362 ni->ni_peerrtrcredits, ni->ni_peertimeout);
1363
1364 return 0;
1365failed0:
1366 lnet_ni_free(ni);
1367 return rc;
1368}
1369
1370static int
1371lnet_startup_lndnis(struct list_head *nilist)
1372{
1373 struct lnet_ni *ni;
1374 int rc;
1375 int ni_count = 0;
1376
1377 while (!list_empty(nilist)) {
1378 ni = list_entry(nilist->next, struct lnet_ni, ni_list);
1379 list_del(&ni->ni_list);
1380 rc = lnet_startup_lndni(ni, NULL);
1381
1382 if (rc < 0)
1383 goto failed;
1384
1385 ni_count++;
1386 }
1387
1388 return ni_count;
1389failed:
1390 lnet_shutdown_lndnis();
1391
1392 return rc;
1393}
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405int lnet_lib_init(void)
1406{
1407 int rc;
1408
1409 lnet_assert_wire_constants();
1410
1411 memset(&the_lnet, 0, sizeof(the_lnet));
1412
1413
1414 the_lnet.ln_cpt_table = cfs_cpt_table;
1415 the_lnet.ln_cpt_number = cfs_cpt_number(cfs_cpt_table);
1416
1417 LASSERT(the_lnet.ln_cpt_number > 0);
1418 if (the_lnet.ln_cpt_number > LNET_CPT_MAX) {
1419
1420 CERROR("Can't have %d CPTs for LNet (max allowed is %d), please change setting of CPT-table and retry\n",
1421 the_lnet.ln_cpt_number, LNET_CPT_MAX);
1422 return -E2BIG;
1423 }
1424
1425 while ((1 << the_lnet.ln_cpt_bits) < the_lnet.ln_cpt_number)
1426 the_lnet.ln_cpt_bits++;
1427
1428 rc = lnet_create_locks();
1429 if (rc) {
1430 CERROR("Can't create LNet global locks: %d\n", rc);
1431 return rc;
1432 }
1433
1434 the_lnet.ln_refcount = 0;
1435 LNetInvalidateEQHandle(&the_lnet.ln_rc_eqh);
1436 INIT_LIST_HEAD(&the_lnet.ln_lnds);
1437 INIT_LIST_HEAD(&the_lnet.ln_rcd_zombie);
1438 INIT_LIST_HEAD(&the_lnet.ln_rcd_deathrow);
1439
1440
1441
1442
1443
1444
1445 if (rnet_htable_size <= 0)
1446 rnet_htable_size = LNET_REMOTE_NETS_HASH_DEFAULT;
1447 else if (rnet_htable_size > LNET_REMOTE_NETS_HASH_MAX)
1448 rnet_htable_size = LNET_REMOTE_NETS_HASH_MAX;
1449 the_lnet.ln_remote_nets_hbits = max_t(int, 1,
1450 order_base_2(rnet_htable_size) - 1);
1451
1452
1453
1454
1455
1456
1457 lnet_register_lnd(&the_lolnd);
1458 return 0;
1459}
1460
1461
1462
1463
1464
1465
1466
1467void lnet_lib_exit(void)
1468{
1469 LASSERT(!the_lnet.ln_refcount);
1470
1471 while (!list_empty(&the_lnet.ln_lnds))
1472 lnet_unregister_lnd(list_entry(the_lnet.ln_lnds.next,
1473 struct lnet_lnd, lnd_list));
1474 lnet_destroy_locks();
1475}
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492int
1493LNetNIInit(lnet_pid_t requested_pid)
1494{
1495 int im_a_router = 0;
1496 int rc;
1497 int ni_count;
1498 struct lnet_ping_info *pinfo;
1499 struct lnet_handle_md md_handle;
1500 struct list_head net_head;
1501
1502 INIT_LIST_HEAD(&net_head);
1503
1504 mutex_lock(&the_lnet.ln_api_mutex);
1505
1506 CDEBUG(D_OTHER, "refs %d\n", the_lnet.ln_refcount);
1507
1508 if (the_lnet.ln_refcount > 0) {
1509 rc = the_lnet.ln_refcount++;
1510 mutex_unlock(&the_lnet.ln_api_mutex);
1511 return rc;
1512 }
1513
1514 rc = lnet_prepare(requested_pid);
1515 if (rc) {
1516 mutex_unlock(&the_lnet.ln_api_mutex);
1517 return rc;
1518 }
1519
1520
1521 if (!lnet_ni_alloc(LNET_MKNET(LOLND, 0), NULL, &net_head)) {
1522 rc = -ENOMEM;
1523 goto err_empty_list;
1524 }
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534 if (!the_lnet.ln_nis_from_mod_params) {
1535 rc = lnet_parse_networks(&net_head, lnet_get_networks());
1536 if (rc < 0)
1537 goto err_empty_list;
1538 }
1539
1540 ni_count = lnet_startup_lndnis(&net_head);
1541 if (ni_count < 0) {
1542 rc = ni_count;
1543 goto err_empty_list;
1544 }
1545
1546 if (!the_lnet.ln_nis_from_mod_params) {
1547 rc = lnet_parse_routes(lnet_get_routes(), &im_a_router);
1548 if (rc)
1549 goto err_shutdown_lndnis;
1550
1551 rc = lnet_check_routes();
1552 if (rc)
1553 goto err_destroy_routes;
1554
1555 rc = lnet_rtrpools_alloc(im_a_router);
1556 if (rc)
1557 goto err_destroy_routes;
1558 }
1559
1560 rc = lnet_acceptor_start();
1561 if (rc)
1562 goto err_destroy_routes;
1563
1564 the_lnet.ln_refcount = 1;
1565
1566
1567 rc = lnet_ping_info_setup(&pinfo, &md_handle, ni_count, true);
1568 if (rc)
1569 goto err_acceptor_stop;
1570
1571 lnet_ping_target_update(pinfo, md_handle);
1572
1573 rc = lnet_router_checker_start();
1574 if (rc)
1575 goto err_stop_ping;
1576
1577 lnet_fault_init();
1578 lnet_router_debugfs_init();
1579
1580 mutex_unlock(&the_lnet.ln_api_mutex);
1581
1582 return 0;
1583
1584err_stop_ping:
1585 lnet_ping_target_fini();
1586err_acceptor_stop:
1587 the_lnet.ln_refcount = 0;
1588 lnet_acceptor_stop();
1589err_destroy_routes:
1590 if (!the_lnet.ln_nis_from_mod_params)
1591 lnet_destroy_routes();
1592err_shutdown_lndnis:
1593 lnet_shutdown_lndnis();
1594err_empty_list:
1595 lnet_unprepare();
1596 LASSERT(rc < 0);
1597 mutex_unlock(&the_lnet.ln_api_mutex);
1598 while (!list_empty(&net_head)) {
1599 struct lnet_ni *ni;
1600
1601 ni = list_entry(net_head.next, struct lnet_ni, ni_list);
1602 list_del_init(&ni->ni_list);
1603 lnet_ni_free(ni);
1604 }
1605 return rc;
1606}
1607EXPORT_SYMBOL(LNetNIInit);
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618int
1619LNetNIFini(void)
1620{
1621 mutex_lock(&the_lnet.ln_api_mutex);
1622
1623 LASSERT(the_lnet.ln_refcount > 0);
1624
1625 if (the_lnet.ln_refcount != 1) {
1626 the_lnet.ln_refcount--;
1627 } else {
1628 LASSERT(!the_lnet.ln_niinit_self);
1629
1630 lnet_fault_fini();
1631 lnet_router_debugfs_fini();
1632 lnet_router_checker_stop();
1633 lnet_ping_target_fini();
1634
1635
1636 the_lnet.ln_refcount = 0;
1637
1638 lnet_acceptor_stop();
1639 lnet_destroy_routes();
1640 lnet_shutdown_lndnis();
1641 lnet_unprepare();
1642 }
1643
1644 mutex_unlock(&the_lnet.ln_api_mutex);
1645 return 0;
1646}
1647EXPORT_SYMBOL(LNetNIFini);
1648
1649
1650
1651
1652
1653
1654
1655
1656static void
1657lnet_fill_ni_info(struct lnet_ni *ni, struct lnet_ioctl_config_data *config)
1658{
1659 struct lnet_ioctl_config_lnd_tunables *lnd_cfg = NULL;
1660 struct lnet_ioctl_net_config *net_config;
1661 size_t min_size, tunable_size = 0;
1662 int i;
1663
1664 if (!ni || !config)
1665 return;
1666
1667 net_config = (struct lnet_ioctl_net_config *)config->cfg_bulk;
1668 if (!net_config)
1669 return;
1670
1671 BUILD_BUG_ON(ARRAY_SIZE(ni->ni_interfaces) !=
1672 ARRAY_SIZE(net_config->ni_interfaces));
1673
1674 for (i = 0; i < ARRAY_SIZE(ni->ni_interfaces); i++) {
1675 if (!ni->ni_interfaces[i])
1676 break;
1677
1678 strncpy(net_config->ni_interfaces[i],
1679 ni->ni_interfaces[i],
1680 sizeof(net_config->ni_interfaces[i]));
1681 }
1682
1683 config->cfg_nid = ni->ni_nid;
1684 config->cfg_config_u.cfg_net.net_peer_timeout = ni->ni_peertimeout;
1685 config->cfg_config_u.cfg_net.net_max_tx_credits = ni->ni_maxtxcredits;
1686 config->cfg_config_u.cfg_net.net_peer_tx_credits = ni->ni_peertxcredits;
1687 config->cfg_config_u.cfg_net.net_peer_rtr_credits = ni->ni_peerrtrcredits;
1688
1689 net_config->ni_status = ni->ni_status->ns_status;
1690
1691 if (ni->ni_cpts) {
1692 int num_cpts = min(ni->ni_ncpts, LNET_MAX_SHOW_NUM_CPT);
1693
1694 for (i = 0; i < num_cpts; i++)
1695 net_config->ni_cpts[i] = ni->ni_cpts[i];
1696
1697 config->cfg_ncpts = num_cpts;
1698 }
1699
1700
1701
1702
1703
1704 min_size = sizeof(*config) + sizeof(*net_config);
1705
1706 if (config->cfg_hdr.ioc_len > min_size)
1707 tunable_size = config->cfg_hdr.ioc_len - min_size;
1708
1709
1710 min_size = min(tunable_size, sizeof(*ni->ni_lnd_tunables));
1711 lnd_cfg = (struct lnet_ioctl_config_lnd_tunables *)net_config->cfg_bulk;
1712
1713 if (ni->ni_lnd_tunables && lnd_cfg && min_size) {
1714 memcpy(lnd_cfg, ni->ni_lnd_tunables, min_size);
1715 config->cfg_config_u.cfg_net.net_interface_count = 1;
1716
1717
1718 if (tunable_size > sizeof(*ni->ni_lnd_tunables)) {
1719 min_size = tunable_size - sizeof(ni->ni_lnd_tunables);
1720 config->cfg_hdr.ioc_len -= min_size;
1721 }
1722 }
1723}
1724
1725static int
1726lnet_get_net_config(struct lnet_ioctl_config_data *config)
1727{
1728 struct lnet_ni *ni;
1729 struct list_head *tmp;
1730 int idx = config->cfg_count;
1731 int cpt, i = 0;
1732 int rc = -ENOENT;
1733
1734 cpt = lnet_net_lock_current();
1735
1736 list_for_each(tmp, &the_lnet.ln_nis) {
1737 if (i++ != idx)
1738 continue;
1739
1740 ni = list_entry(tmp, struct lnet_ni, ni_list);
1741 lnet_ni_lock(ni);
1742 lnet_fill_ni_info(ni, config);
1743 lnet_ni_unlock(ni);
1744 rc = 0;
1745 break;
1746 }
1747
1748 lnet_net_unlock(cpt);
1749 return rc;
1750}
1751
1752int
1753lnet_dyn_add_ni(lnet_pid_t requested_pid, struct lnet_ioctl_config_data *conf)
1754{
1755 char *nets = conf->cfg_config_u.cfg_net.net_intf;
1756 struct lnet_ping_info *pinfo;
1757 struct lnet_handle_md md_handle;
1758 struct lnet_ni *ni;
1759 struct list_head net_head;
1760 struct lnet_remotenet *rnet;
1761 int rc;
1762
1763 INIT_LIST_HEAD(&net_head);
1764
1765
1766 rc = lnet_parse_networks(&net_head, nets);
1767 if (rc <= 0)
1768 return !rc ? -EINVAL : rc;
1769
1770 mutex_lock(&the_lnet.ln_api_mutex);
1771
1772 if (rc > 1) {
1773 rc = -EINVAL;
1774 goto failed0;
1775 }
1776
1777 ni = list_entry(net_head.next, struct lnet_ni, ni_list);
1778
1779 lnet_net_lock(LNET_LOCK_EX);
1780 rnet = lnet_find_net_locked(LNET_NIDNET(ni->ni_nid));
1781 lnet_net_unlock(LNET_LOCK_EX);
1782
1783
1784
1785
1786 if (rnet) {
1787 CERROR("Adding net %s will invalidate routing configuration\n",
1788 nets);
1789 rc = -EUSERS;
1790 goto failed0;
1791 }
1792
1793 rc = lnet_ping_info_setup(&pinfo, &md_handle, 1 + lnet_get_ni_count(),
1794 false);
1795 if (rc)
1796 goto failed0;
1797
1798 list_del_init(&ni->ni_list);
1799
1800 rc = lnet_startup_lndni(ni, conf);
1801 if (rc)
1802 goto failed1;
1803
1804 if (ni->ni_lnd->lnd_accept) {
1805 rc = lnet_acceptor_start();
1806 if (rc < 0) {
1807
1808 CERROR("Failed to start up acceptor thread\n");
1809 lnet_shutdown_lndni(ni);
1810 goto failed1;
1811 }
1812 }
1813
1814 lnet_ping_target_update(pinfo, md_handle);
1815 mutex_unlock(&the_lnet.ln_api_mutex);
1816
1817 return 0;
1818
1819failed1:
1820 lnet_ping_md_unlink(pinfo, &md_handle);
1821 lnet_ping_info_free(pinfo);
1822failed0:
1823 mutex_unlock(&the_lnet.ln_api_mutex);
1824 while (!list_empty(&net_head)) {
1825 ni = list_entry(net_head.next, struct lnet_ni, ni_list);
1826 list_del_init(&ni->ni_list);
1827 lnet_ni_free(ni);
1828 }
1829 return rc;
1830}
1831
1832int
1833lnet_dyn_del_ni(__u32 net)
1834{
1835 struct lnet_ni *ni;
1836 struct lnet_ping_info *pinfo;
1837 struct lnet_handle_md md_handle;
1838 int rc;
1839
1840
1841 if (LNET_NETTYP(net) == LOLND)
1842 return -EINVAL;
1843
1844 mutex_lock(&the_lnet.ln_api_mutex);
1845
1846 rc = lnet_ping_info_setup(&pinfo, &md_handle,
1847 lnet_get_ni_count() - 1, false);
1848 if (rc)
1849 goto out;
1850
1851 ni = lnet_net2ni(net);
1852 if (!ni) {
1853 rc = -EINVAL;
1854 goto failed;
1855 }
1856
1857
1858 lnet_ni_decref_locked(ni, 0);
1859
1860 lnet_shutdown_lndni(ni);
1861
1862 if (!lnet_count_acceptor_nis())
1863 lnet_acceptor_stop();
1864
1865 lnet_ping_target_update(pinfo, md_handle);
1866 goto out;
1867failed:
1868 lnet_ping_md_unlink(pinfo, &md_handle);
1869 lnet_ping_info_free(pinfo);
1870out:
1871 mutex_unlock(&the_lnet.ln_api_mutex);
1872
1873 return rc;
1874}
1875
1876
1877
1878
1879
1880int
1881LNetCtl(unsigned int cmd, void *arg)
1882{
1883 struct libcfs_ioctl_data *data = arg;
1884 struct lnet_ioctl_config_data *config;
1885 struct lnet_process_id id = {0};
1886 struct lnet_ni *ni;
1887 int rc;
1888 unsigned long secs_passed;
1889
1890 BUILD_BUG_ON(LIBCFS_IOC_DATA_MAX <
1891 sizeof(struct lnet_ioctl_net_config) +
1892 sizeof(struct lnet_ioctl_config_data));
1893
1894 switch (cmd) {
1895 case IOC_LIBCFS_GET_NI:
1896 rc = LNetGetId(data->ioc_count, &id);
1897 data->ioc_nid = id.nid;
1898 return rc;
1899
1900 case IOC_LIBCFS_FAIL_NID:
1901 return lnet_fail_nid(data->ioc_nid, data->ioc_count);
1902
1903 case IOC_LIBCFS_ADD_ROUTE:
1904 config = arg;
1905
1906 if (config->cfg_hdr.ioc_len < sizeof(*config))
1907 return -EINVAL;
1908
1909 mutex_lock(&the_lnet.ln_api_mutex);
1910 rc = lnet_add_route(config->cfg_net,
1911 config->cfg_config_u.cfg_route.rtr_hop,
1912 config->cfg_nid,
1913 config->cfg_config_u.cfg_route.rtr_priority);
1914 if (!rc) {
1915 rc = lnet_check_routes();
1916 if (rc)
1917 lnet_del_route(config->cfg_net,
1918 config->cfg_nid);
1919 }
1920 mutex_unlock(&the_lnet.ln_api_mutex);
1921 return rc;
1922
1923 case IOC_LIBCFS_DEL_ROUTE:
1924 config = arg;
1925
1926 if (config->cfg_hdr.ioc_len < sizeof(*config))
1927 return -EINVAL;
1928
1929 mutex_lock(&the_lnet.ln_api_mutex);
1930 rc = lnet_del_route(config->cfg_net, config->cfg_nid);
1931 mutex_unlock(&the_lnet.ln_api_mutex);
1932 return rc;
1933
1934 case IOC_LIBCFS_GET_ROUTE:
1935 config = arg;
1936
1937 if (config->cfg_hdr.ioc_len < sizeof(*config))
1938 return -EINVAL;
1939
1940 return lnet_get_route(config->cfg_count,
1941 &config->cfg_net,
1942 &config->cfg_config_u.cfg_route.rtr_hop,
1943 &config->cfg_nid,
1944 &config->cfg_config_u.cfg_route.rtr_flags,
1945 &config->cfg_config_u.cfg_route.rtr_priority);
1946
1947 case IOC_LIBCFS_GET_NET: {
1948 size_t total = sizeof(*config) +
1949 sizeof(struct lnet_ioctl_net_config);
1950 config = arg;
1951
1952 if (config->cfg_hdr.ioc_len < total)
1953 return -EINVAL;
1954
1955 return lnet_get_net_config(config);
1956 }
1957
1958 case IOC_LIBCFS_GET_LNET_STATS: {
1959 struct lnet_ioctl_lnet_stats *lnet_stats = arg;
1960
1961 if (lnet_stats->st_hdr.ioc_len < sizeof(*lnet_stats))
1962 return -EINVAL;
1963
1964 lnet_counters_get(&lnet_stats->st_cntrs);
1965 return 0;
1966 }
1967
1968 case IOC_LIBCFS_CONFIG_RTR:
1969 config = arg;
1970
1971 if (config->cfg_hdr.ioc_len < sizeof(*config))
1972 return -EINVAL;
1973
1974 mutex_lock(&the_lnet.ln_api_mutex);
1975 if (config->cfg_config_u.cfg_buffers.buf_enable) {
1976 rc = lnet_rtrpools_enable();
1977 mutex_unlock(&the_lnet.ln_api_mutex);
1978 return rc;
1979 }
1980 lnet_rtrpools_disable();
1981 mutex_unlock(&the_lnet.ln_api_mutex);
1982 return 0;
1983
1984 case IOC_LIBCFS_ADD_BUF:
1985 config = arg;
1986
1987 if (config->cfg_hdr.ioc_len < sizeof(*config))
1988 return -EINVAL;
1989
1990 mutex_lock(&the_lnet.ln_api_mutex);
1991 rc = lnet_rtrpools_adjust(config->cfg_config_u.cfg_buffers.buf_tiny,
1992 config->cfg_config_u.cfg_buffers.buf_small,
1993 config->cfg_config_u.cfg_buffers.buf_large);
1994 mutex_unlock(&the_lnet.ln_api_mutex);
1995 return rc;
1996
1997 case IOC_LIBCFS_GET_BUF: {
1998 struct lnet_ioctl_pool_cfg *pool_cfg;
1999 size_t total = sizeof(*config) + sizeof(*pool_cfg);
2000
2001 config = arg;
2002
2003 if (config->cfg_hdr.ioc_len < total)
2004 return -EINVAL;
2005
2006 pool_cfg = (struct lnet_ioctl_pool_cfg *)config->cfg_bulk;
2007 return lnet_get_rtr_pool_cfg(config->cfg_count, pool_cfg);
2008 }
2009
2010 case IOC_LIBCFS_GET_PEER_INFO: {
2011 struct lnet_ioctl_peer *peer_info = arg;
2012
2013 if (peer_info->pr_hdr.ioc_len < sizeof(*peer_info))
2014 return -EINVAL;
2015
2016 return lnet_get_peer_info(peer_info->pr_count,
2017 &peer_info->pr_nid,
2018 peer_info->pr_lnd_u.pr_peer_credits.cr_aliveness,
2019 &peer_info->pr_lnd_u.pr_peer_credits.cr_ncpt,
2020 &peer_info->pr_lnd_u.pr_peer_credits.cr_refcount,
2021 &peer_info->pr_lnd_u.pr_peer_credits.cr_ni_peer_tx_credits,
2022 &peer_info->pr_lnd_u.pr_peer_credits.cr_peer_tx_credits,
2023 &peer_info->pr_lnd_u.pr_peer_credits.cr_peer_rtr_credits,
2024 &peer_info->pr_lnd_u.pr_peer_credits.cr_peer_min_rtr_credits,
2025 &peer_info->pr_lnd_u.pr_peer_credits.cr_peer_tx_qnob);
2026 }
2027
2028 case IOC_LIBCFS_NOTIFY_ROUTER:
2029 secs_passed = (ktime_get_real_seconds() - data->ioc_u64[0]);
2030 secs_passed *= msecs_to_jiffies(MSEC_PER_SEC);
2031
2032 return lnet_notify(NULL, data->ioc_nid, data->ioc_flags,
2033 jiffies - secs_passed);
2034
2035 case IOC_LIBCFS_LNET_DIST:
2036 rc = LNetDist(data->ioc_nid, &data->ioc_nid, &data->ioc_u32[1]);
2037 if (rc < 0 && rc != -EHOSTUNREACH)
2038 return rc;
2039
2040 data->ioc_u32[0] = rc;
2041 return 0;
2042
2043 case IOC_LIBCFS_TESTPROTOCOMPAT:
2044 lnet_net_lock(LNET_LOCK_EX);
2045 the_lnet.ln_testprotocompat = data->ioc_flags;
2046 lnet_net_unlock(LNET_LOCK_EX);
2047 return 0;
2048
2049 case IOC_LIBCFS_LNET_FAULT:
2050 return lnet_fault_ctl(data->ioc_flags, data);
2051
2052 case IOC_LIBCFS_PING:
2053 id.nid = data->ioc_nid;
2054 id.pid = data->ioc_u32[0];
2055 rc = lnet_ping(id, data->ioc_u32[1],
2056 data->ioc_pbuf1,
2057 data->ioc_plen1 / sizeof(struct lnet_process_id));
2058 if (rc < 0)
2059 return rc;
2060 data->ioc_count = rc;
2061 return 0;
2062
2063 default:
2064 ni = lnet_net2ni(data->ioc_net);
2065 if (!ni)
2066 return -EINVAL;
2067
2068 if (!ni->ni_lnd->lnd_ctl)
2069 rc = -EINVAL;
2070 else
2071 rc = ni->ni_lnd->lnd_ctl(ni, cmd, arg);
2072
2073 lnet_ni_decref(ni);
2074 return rc;
2075 }
2076
2077}
2078EXPORT_SYMBOL(LNetCtl);
2079
2080void LNetDebugPeer(struct lnet_process_id id)
2081{
2082 lnet_debug_peer(id.nid);
2083}
2084EXPORT_SYMBOL(LNetDebugPeer);
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097int
2098LNetGetId(unsigned int index, struct lnet_process_id *id)
2099{
2100 struct lnet_ni *ni;
2101 struct list_head *tmp;
2102 int cpt;
2103 int rc = -ENOENT;
2104
2105 LASSERT(the_lnet.ln_refcount > 0);
2106
2107 cpt = lnet_net_lock_current();
2108
2109 list_for_each(tmp, &the_lnet.ln_nis) {
2110 if (index--)
2111 continue;
2112
2113 ni = list_entry(tmp, struct lnet_ni, ni_list);
2114
2115 id->nid = ni->ni_nid;
2116 id->pid = the_lnet.ln_pid;
2117 rc = 0;
2118 break;
2119 }
2120
2121 lnet_net_unlock(cpt);
2122 return rc;
2123}
2124EXPORT_SYMBOL(LNetGetId);
2125
2126static int lnet_ping(struct lnet_process_id id, int timeout_ms,
2127 struct lnet_process_id __user *ids, int n_ids)
2128{
2129 struct lnet_handle_eq eqh;
2130 struct lnet_handle_md mdh;
2131 struct lnet_event event;
2132 struct lnet_md md = { NULL };
2133 int which;
2134 int unlinked = 0;
2135 int replied = 0;
2136 const int a_long_time = 60000;
2137 int infosz;
2138 struct lnet_ping_info *info;
2139 struct lnet_process_id tmpid;
2140 int i;
2141 int nob;
2142 int rc;
2143 int rc2;
2144 sigset_t blocked;
2145
2146 infosz = offsetof(struct lnet_ping_info, pi_ni[n_ids]);
2147
2148 if (n_ids <= 0 ||
2149 id.nid == LNET_NID_ANY ||
2150 timeout_ms > 500000 ||
2151 n_ids > 20)
2152 return -EINVAL;
2153
2154 if (id.pid == LNET_PID_ANY)
2155 id.pid = LNET_PID_LUSTRE;
2156
2157 info = kzalloc(infosz, GFP_KERNEL);
2158 if (!info)
2159 return -ENOMEM;
2160
2161
2162 rc = LNetEQAlloc(2, LNET_EQ_HANDLER_NONE, &eqh);
2163 if (rc) {
2164 CERROR("Can't allocate EQ: %d\n", rc);
2165 goto out_0;
2166 }
2167
2168
2169 md.start = info;
2170 md.length = infosz;
2171 md.threshold = 2;
2172 md.max_size = 0;
2173 md.options = LNET_MD_TRUNCATE;
2174 md.user_ptr = NULL;
2175 md.eq_handle = eqh;
2176
2177 rc = LNetMDBind(md, LNET_UNLINK, &mdh);
2178 if (rc) {
2179 CERROR("Can't bind MD: %d\n", rc);
2180 goto out_1;
2181 }
2182
2183 rc = LNetGet(LNET_NID_ANY, mdh, id,
2184 LNET_RESERVED_PORTAL,
2185 LNET_PROTO_PING_MATCHBITS, 0);
2186
2187 if (rc) {
2188
2189
2190 rc2 = LNetMDUnlink(mdh);
2191 LASSERT(!rc2);
2192
2193
2194 unlinked = 1;
2195 timeout_ms = a_long_time;
2196 }
2197
2198 do {
2199
2200 if (unlinked)
2201 blocked = cfs_block_allsigs();
2202
2203 rc2 = LNetEQPoll(&eqh, 1, timeout_ms, &event, &which);
2204
2205 if (unlinked)
2206 cfs_restore_sigs(blocked);
2207
2208 CDEBUG(D_NET, "poll %d(%d %d)%s\n", rc2,
2209 (rc2 <= 0) ? -1 : event.type,
2210 (rc2 <= 0) ? -1 : event.status,
2211 (rc2 > 0 && event.unlinked) ? " unlinked" : "");
2212
2213 LASSERT(rc2 != -EOVERFLOW);
2214
2215 if (rc2 <= 0 || event.status) {
2216
2217 if (!replied && !rc)
2218 rc = (rc2 < 0) ? rc2 :
2219 !rc2 ? -ETIMEDOUT :
2220 event.status;
2221
2222 if (!unlinked) {
2223
2224 LNetMDUnlink(mdh);
2225
2226 unlinked = 1;
2227 timeout_ms = a_long_time;
2228 } else if (!rc2) {
2229
2230 CWARN("ping %s: late network completion\n",
2231 libcfs_id2str(id));
2232 }
2233 } else if (event.type == LNET_EVENT_REPLY) {
2234 replied = 1;
2235 rc = event.mlength;
2236 }
2237
2238 } while (rc2 <= 0 || !event.unlinked);
2239
2240 if (!replied) {
2241 if (rc >= 0)
2242 CWARN("%s: Unexpected rc >= 0 but no reply!\n",
2243 libcfs_id2str(id));
2244 rc = -EIO;
2245 goto out_1;
2246 }
2247
2248 nob = rc;
2249 LASSERT(nob >= 0 && nob <= infosz);
2250
2251 rc = -EPROTO;
2252
2253 if (nob < 8) {
2254
2255 CERROR("%s: ping info too short %d\n",
2256 libcfs_id2str(id), nob);
2257 goto out_1;
2258 }
2259
2260 if (info->pi_magic == __swab32(LNET_PROTO_PING_MAGIC)) {
2261 lnet_swap_pinginfo(info);
2262 } else if (info->pi_magic != LNET_PROTO_PING_MAGIC) {
2263 CERROR("%s: Unexpected magic %08x\n",
2264 libcfs_id2str(id), info->pi_magic);
2265 goto out_1;
2266 }
2267
2268 if (!(info->pi_features & LNET_PING_FEAT_NI_STATUS)) {
2269 CERROR("%s: ping w/o NI status: 0x%x\n",
2270 libcfs_id2str(id), info->pi_features);
2271 goto out_1;
2272 }
2273
2274 if (nob < offsetof(struct lnet_ping_info, pi_ni[0])) {
2275 CERROR("%s: Short reply %d(%d min)\n", libcfs_id2str(id),
2276 nob, (int)offsetof(struct lnet_ping_info, pi_ni[0]));
2277 goto out_1;
2278 }
2279
2280 if (info->pi_nnis < n_ids)
2281 n_ids = info->pi_nnis;
2282
2283 if (nob < offsetof(struct lnet_ping_info, pi_ni[n_ids])) {
2284 CERROR("%s: Short reply %d(%d expected)\n", libcfs_id2str(id),
2285 nob, (int)offsetof(struct lnet_ping_info, pi_ni[n_ids]));
2286 goto out_1;
2287 }
2288
2289 rc = -EFAULT;
2290
2291 memset(&tmpid, 0, sizeof(tmpid));
2292 for (i = 0; i < n_ids; i++) {
2293 tmpid.pid = info->pi_pid;
2294 tmpid.nid = info->pi_ni[i].ns_nid;
2295 if (copy_to_user(&ids[i], &tmpid, sizeof(tmpid)))
2296 goto out_1;
2297 }
2298 rc = info->pi_nnis;
2299
2300 out_1:
2301 rc2 = LNetEQFree(eqh);
2302 if (rc2)
2303 CERROR("rc2 %d\n", rc2);
2304 LASSERT(!rc2);
2305
2306 out_0:
2307 kfree(info);
2308 return rc;
2309}
2310