Whamcloud - gitweb
19ac77c0be3cb695c93480f81d83fd5ab876861f
[fs/lustre-release.git] / lnet / klnds / gnilnd / gnilnd_proc.c
1 /*
2  * Copyright (C) 2009-2012 Cray, Inc.
3  *
4  * Copyright (c) 2013, Intel Corporation.
5  *
6  *   Author: Nic Henke <nic@cray.com>
7  *
8  *   This file is part of Lustre, http://www.lustre.org.
9  *
10  *   Lustre is free software; you can redistribute it and/or
11  *   modify it under the terms of version 2 of the GNU General Public
12  *   License as published by the Free Software Foundation.
13  *
14  *   Lustre is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *   GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with Lustre; if not, write to the Free Software
21  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 /* this code liberated and modified from lnet/lnet/router_proc.c */
25
26 #define DEBUG_SUBSYSTEM S_LND
27 #include "gnilnd.h"
28 #include <linux/seq_file.h>
29 #include <lprocfs_status.h>
30
31 #define GNILND_PROC_STATS       "stats"
32 #define GNILND_PROC_MDD         "mdd"
33 #define GNILND_PROC_SMSG        "smsg"
34 #define GNILND_PROC_CONN        "conn"
35 #define GNILND_PROC_PEER_CONNS  "peer_conns"
36 #define GNILND_PROC_PEER        "peer"
37 #define GNILND_PROC_CKSUM_TEST  "cksum_test"
38
39 static int
40 _kgnilnd_proc_run_cksum_test(int caseno, int nloops, int nob)
41 {
42         lnet_kiov_t              *src, *dest;
43         struct timespec          begin, end, diff;
44         int                      niov;
45         int                      rc = 0;
46         int                      i = 0, j = 0, n;
47         __u16                    cksum, cksum2;
48         __u64                    mbytes;
49
50         LIBCFS_ALLOC(src, LNET_MAX_IOV * sizeof(lnet_kiov_t));
51         LIBCFS_ALLOC(dest, LNET_MAX_IOV * sizeof(lnet_kiov_t));
52
53         if (src == NULL || dest == NULL) {
54                 CERROR("couldn't allocate iovs\n");
55                 GOTO(unwind, rc = -ENOMEM);
56         }
57
58         for (i = 0; i < LNET_MAX_IOV; i++) {
59                 src[i].kiov_offset = 0;
60                 src[i].kiov_len = PAGE_SIZE;
61                 src[i].kiov_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
62
63                 if (src[i].kiov_page == NULL) {
64                         CERROR("couldn't allocate page %d\n", i);
65                         GOTO(unwind, rc = -ENOMEM);
66                 }
67
68                 dest[i].kiov_offset = 0;
69                 dest[i].kiov_len = PAGE_SIZE;
70                 dest[i].kiov_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
71
72                 if (dest[i].kiov_page == NULL) {
73                         CERROR("couldn't allocate page %d\n", i);
74                         GOTO(unwind, rc = -ENOMEM);
75                 }
76         }
77
78         /* add extra 2 pages - one for offset of src, 2nd to allow dest offset */
79         niov = (nob / PAGE_SIZE) + 2;
80         if (niov > LNET_MAX_IOV) {
81                 CERROR("bytes %d too large, requires niov %d > %d\n",
82                         nob, niov, LNET_MAX_IOV);
83                 GOTO(unwind, rc = -E2BIG);
84         }
85
86         /* setup real data */
87         src[0].kiov_offset = 317;
88         dest[0].kiov_offset = 592;
89         switch (caseno) {
90         default:
91                 /* odd -> even */
92                 break;
93         case 1:
94                 /* odd -> odd */
95                 dest[0].kiov_offset -= 1;
96                 break;
97         case 2:
98                 /* even -> even */
99                 src[0].kiov_offset += 1;
100                 break;
101         case 3:
102                 /* even -> odd */
103                 src[0].kiov_offset += 1;
104                 dest[0].kiov_offset -= 1;
105         }
106         src[0].kiov_len = PAGE_SIZE - src[0].kiov_offset;
107         dest[0].kiov_len = PAGE_SIZE - dest[0].kiov_offset;
108
109         for (i = 0; i < niov; i++) {
110                 memset(page_address(src[i].kiov_page) + src[i].kiov_offset,
111                        0xf0 + i, src[i].kiov_len);
112         }
113
114         lnet_copy_kiov2kiov(niov, dest, 0, niov, src, 0, nob);
115
116         getnstimeofday(&begin);
117
118         for (n = 0; n < nloops; n++) {
119                 CDEBUG(D_BUFFS, "case %d loop %d src %d dest %d nob %d niov %d\n",
120                        caseno, n, src[0].kiov_offset, dest[0].kiov_offset, nob, niov);
121                 cksum = kgnilnd_cksum_kiov(niov, src, 0, nob - (n % nob), 1);
122                 cksum2 = kgnilnd_cksum_kiov(niov, dest, 0, nob - (n % nob), 1);
123
124                 if (cksum != cksum2) {
125                         CERROR("case %d loop %d different checksums %x expected %x\n",
126                                j, n, cksum2, cksum);
127                         GOTO(unwind, rc = -ENOKEY);
128                 }
129         }
130
131         getnstimeofday(&end);
132
133         mbytes = ((__u64)nloops * nob * 2) / (1024*1024);
134
135         diff = kgnilnd_ts_sub(end, begin);
136
137         LCONSOLE_INFO("running "LPD64"MB took %ld.%ld seconds\n",
138                       mbytes, diff.tv_sec, diff.tv_nsec);
139
140 unwind:
141         CDEBUG(D_NET, "freeing %d pages\n", i);
142         for (i -= 1; i >= 0; i--) {
143                 if (src[i].kiov_page != NULL) {
144                         __free_page(src[i].kiov_page);
145                 }
146                 if (dest[i].kiov_page != NULL) {
147                         __free_page(dest[i].kiov_page);
148                 }
149         }
150
151         if (src != NULL)
152                 LIBCFS_FREE(src, LNET_MAX_IOV * sizeof(lnet_kiov_t));
153         if (dest != NULL)
154                 LIBCFS_FREE(dest, LNET_MAX_IOV * sizeof(lnet_kiov_t));
155         return rc;
156 }
157
158 static int
159 kgnilnd_proc_cksum_test_write(struct file *file, const char *ubuffer,
160                               unsigned long count, void *data)
161 {
162         char                    dummy[256 + 1] = { '\0' };
163         int                     testno, nloops, nbytes;
164         int                     rc;
165         ENTRY;
166
167         if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
168                 CERROR("can't run cksum test, kgnilnd is not initialized yet\n");
169                 RETURN(-ENOSYS);
170         }
171
172         if (count >= sizeof(dummy) || count == 0)
173                 RETURN(-EINVAL);
174
175         if (copy_from_user(dummy, ubuffer, count))
176                 RETURN(-EFAULT);
177
178         if (sscanf(dummy, "%d:%d:%d", &testno, &nloops, &nbytes) == 3) {
179                 rc = _kgnilnd_proc_run_cksum_test(testno, nloops, nbytes);
180                 if (rc < 0) {
181                         RETURN(rc);
182                 } else {
183                         /* spurious, but lets us know the parse was ok */
184                         RETURN(count);
185                 }
186         }
187         RETURN(count);
188 }
189
190 static int
191 kgnilnd_proc_stats_read(char *page, char **start, off_t off,
192                              int count, int *eof, void *data)
193 {
194         kgn_device_t           *dev;
195         struct timeval          now;
196         int                     rc;
197
198         if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
199                 rc = sprintf(page,
200                         "kgnilnd is not initialized yet\n");
201                 return rc;
202         }
203
204         /* only do the first device */
205         dev = &kgnilnd_data.kgn_devices[0];
206
207         /* sampling is racy, but so is reading this file! */
208         smp_rmb();
209         do_gettimeofday(&now);
210
211         rc = sprintf(page, "time: %lu.%lu\n"
212                            "ntx: %d\n"
213                            "npeers: %d\n"
214                            "nconns: %d\n"
215                            "nEPs: %d\n"
216                            "ndgrams: %d\n"
217                            "nfmablk: %d\n"
218                            "n_mdd: %d\n"
219                            "n_mdd_held: %d\n"
220                            "n_eager_allocs: %d\n"
221                            "GART map bytes: %ld\n"
222                            "TX queued maps: %d\n"
223                            "TX phys nmaps: %d\n"
224                            "TX phys bytes: %lu\n"
225                            "TX virt nmaps: %d\n"
226                            "TX virt bytes: "LPU64"\n"
227                            "RDMAQ bytes_auth: %ld\n"
228                            "RDMAQ bytes_left: %ld\n"
229                            "RDMAQ nstalls: %d\n"
230                            "dev mutex delay: %ld\n"
231                            "dev n_yield: %d\n"
232                            "dev n_schedule: %d\n"
233                            "SMSG fast_try: %d\n"
234                            "SMSG fast_ok: %d\n"
235                            "SMSG fast_block: %d\n"
236                            "SMSG ntx: %d\n"
237                            "SMSG tx_bytes: %ld\n"
238                            "SMSG nrx: %d\n"
239                            "SMSG rx_bytes: %ld\n"
240                            "RDMA ntx: %d\n"
241                            "RDMA tx_bytes: %ld\n"
242                            "RDMA nrx: %d\n"
243                            "RDMA rx_bytes: %ld\n"
244                            "VMAP short: %d\n"
245                            "VMAP cksum: %d\n"
246                            "KMAP short: %d\n"
247                            "RDMA REV length: %d\n"
248                            "RDMA REV offset: %d\n"
249                            "RDMA REV copy: %d\n",
250                 now.tv_sec, now.tv_usec,
251                 atomic_read(&kgnilnd_data.kgn_ntx),
252                 atomic_read(&kgnilnd_data.kgn_npeers),
253                 atomic_read(&kgnilnd_data.kgn_nconns),
254                 atomic_read(&dev->gnd_neps),
255                 atomic_read(&dev->gnd_ndgrams),
256                 atomic_read(&dev->gnd_nfmablk),
257                 atomic_read(&dev->gnd_n_mdd), atomic_read(&dev->gnd_n_mdd_held),
258                 atomic_read(&kgnilnd_data.kgn_neager_allocs),
259                 atomic64_read(&dev->gnd_nbytes_map),
260                 atomic_read(&dev->gnd_nq_map),
261                 dev->gnd_map_nphys, dev->gnd_map_physnop * PAGE_SIZE,
262                 dev->gnd_map_nvirt, dev->gnd_map_virtnob,
263                 atomic64_read(&dev->gnd_rdmaq_bytes_out),
264                 atomic64_read(&dev->gnd_rdmaq_bytes_ok),
265                 atomic_read(&dev->gnd_rdmaq_nstalls),
266                 dev->gnd_mutex_delay,
267                 atomic_read(&dev->gnd_n_yield), atomic_read(&dev->gnd_n_schedule),
268                 atomic_read(&dev->gnd_fast_try), atomic_read(&dev->gnd_fast_ok),
269                 atomic_read(&dev->gnd_fast_block),
270                 atomic_read(&dev->gnd_short_ntx), atomic64_read(&dev->gnd_short_txbytes),
271                 atomic_read(&dev->gnd_short_nrx), atomic64_read(&dev->gnd_short_rxbytes),
272                 atomic_read(&dev->gnd_rdma_ntx), atomic64_read(&dev->gnd_rdma_txbytes),
273                 atomic_read(&dev->gnd_rdma_nrx), atomic64_read(&dev->gnd_rdma_rxbytes),
274                 atomic_read(&kgnilnd_data.kgn_nvmap_short),
275                 atomic_read(&kgnilnd_data.kgn_nvmap_cksum),
276                 atomic_read(&kgnilnd_data.kgn_nkmap_short),
277                 atomic_read(&kgnilnd_data.kgn_rev_length),
278                 atomic_read(&kgnilnd_data.kgn_rev_offset),
279                 atomic_read(&kgnilnd_data.kgn_rev_copy_buff));
280
281         return rc;
282 }
283
284 static int
285 kgnilnd_proc_stats_write(struct file *file, const char *ubuffer,
286                      unsigned long count, void *data)
287 {
288         kgn_device_t           *dev;
289
290         if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
291                 CERROR("kgnilnd is not initialized for stats write\n");
292                 return -EINVAL;
293         }
294
295         /* only do the first device */
296         dev = &kgnilnd_data.kgn_devices[0];
297
298         atomic_set(&dev->gnd_short_ntx, 0);
299         atomic_set(&dev->gnd_short_nrx, 0);
300         atomic64_set(&dev->gnd_short_txbytes, 0);
301         atomic64_set(&dev->gnd_short_rxbytes, 0);
302         atomic_set(&dev->gnd_rdma_ntx, 0);
303         atomic_set(&dev->gnd_rdma_nrx, 0);
304         atomic_set(&dev->gnd_fast_ok, 0);
305         atomic_set(&dev->gnd_fast_try, 0);
306         atomic_set(&dev->gnd_fast_block, 0);
307         atomic64_set(&dev->gnd_rdma_txbytes, 0);
308         atomic64_set(&dev->gnd_rdma_rxbytes, 0);
309         atomic_set(&dev->gnd_rdmaq_nstalls, 0);
310         set_mb(dev->gnd_mutex_delay, 0);
311         atomic_set(&dev->gnd_n_yield, 0);
312         atomic_set(&dev->gnd_n_schedule, 0);
313         atomic_set(&kgnilnd_data.kgn_nvmap_short, 0);
314         atomic_set(&kgnilnd_data.kgn_nvmap_cksum, 0);
315         atomic_set(&kgnilnd_data.kgn_nkmap_short, 0);
316         /* sampling is racy, but so is writing this file! */
317         smp_wmb();
318         return count;
319 }
320
321 typedef struct {
322         kgn_device_t           *gmdd_dev;
323         kgn_tx_t               *gmdd_tx;
324         loff_t                  gmdd_off;
325 } kgn_mdd_seq_iter_t;
326
327 int
328 kgnilnd_mdd_seq_seek(kgn_mdd_seq_iter_t *gseq, loff_t off)
329 {
330         kgn_tx_t                *tx;
331         struct list_head        *r;
332         loff_t                  here;
333         int                     rc = 0;
334
335         if (off == 0) {
336                 gseq->gmdd_tx = NULL;
337                 gseq->gmdd_off = 0;
338                 return 0;
339         }
340
341         tx = gseq->gmdd_tx;
342
343         if (tx == NULL || gseq->gmdd_off > off) {
344                 /* search from start */
345                 r = gseq->gmdd_dev->gnd_map_list.next;
346                 here = 1;
347         } else {
348                 /* continue current search */
349                 r = &tx->tx_map_list;
350                 here = gseq->gmdd_off;
351         }
352
353         gseq->gmdd_off = off;
354
355         while (r != &gseq->gmdd_dev->gnd_map_list) {
356                 kgn_tx_t      *t;
357
358                 t = list_entry(r, kgn_tx_t, tx_map_list);
359
360                 if (here == off) {
361                         gseq->gmdd_tx = t;
362                         rc = 0;
363                         goto out;
364                 }
365                 r = r->next;
366                 here++;
367         }
368
369         gseq->gmdd_tx = NULL;
370         rc = -ENOENT;
371 out:
372         return rc;
373 }
374
375 static void *
376 kgnilnd_mdd_seq_start(struct seq_file *s, loff_t *pos)
377 {
378
379         kgn_mdd_seq_iter_t      *gseq;
380         int                      rc;
381
382         if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
383                 return NULL;
384         }
385
386         LIBCFS_ALLOC(gseq, sizeof(*gseq));
387         if (gseq == NULL) {
388                 CERROR("could not allocate mdd sequence iterator\n");
389                 return NULL;
390         }
391
392         /* only doing device 0 for now */
393         gseq->gmdd_dev = &kgnilnd_data.kgn_devices[0];
394         gseq->gmdd_tx = NULL;
395
396         /* need to lock map while we poke - huge disturbance
397          * but without it, no way to get the data printed */
398         spin_lock(&gseq->gmdd_dev->gnd_map_lock);
399
400         /* set private to gseq for stop */
401         s->private = gseq;
402
403         rc = kgnilnd_mdd_seq_seek(gseq, *pos);
404         if (rc == 0)
405                 return gseq;
406         else
407                 return NULL;
408 }
409
410 static void
411 kgnilnd_mdd_seq_stop(struct seq_file *s, void *iter)
412 {
413         kgn_mdd_seq_iter_t     *gseq = s->private;
414
415         if (gseq != NULL) {
416                 spin_unlock(&gseq->gmdd_dev->gnd_map_lock);
417                 LIBCFS_FREE(gseq, sizeof(*gseq));
418         }
419 }
420
421 static void *
422 kgnilnd_mdd_seq_next(struct seq_file *s, void *iter, loff_t *pos)
423 {
424         kgn_mdd_seq_iter_t     *gseq = iter;
425         int                     rc;
426         loff_t                  next = *pos + 1;
427
428         rc = kgnilnd_mdd_seq_seek(gseq, next);
429         if (rc != 0) {
430                 return NULL;
431         }
432         *pos = next;
433         return gseq;
434 }
435
436 static int
437 kgnilnd_mdd_seq_show(struct seq_file *s, void *iter)
438 {
439         kgn_mdd_seq_iter_t     *gseq = iter;
440         kgn_tx_t               *tx;
441         __u64                   nob;
442         __u32                   physnop;
443         int                     id;
444         int                     buftype;
445         gni_mem_handle_t        hndl;
446
447         if (gseq->gmdd_off == 0) {
448                 seq_printf(s, "%s %22s %16s %8s %8s %37s\n",
449                         "tx", "tx_id", "nob", "physnop",
450                         "buftype", "mem handle");
451                 return 0;
452         }
453
454         tx = gseq->gmdd_tx;
455         LASSERT(tx != NULL);
456
457         id = tx->tx_id.txe_smsg_id;
458         nob = tx->tx_nob;
459         physnop = tx->tx_phys_npages;
460         buftype = tx->tx_buftype;
461         hndl.qword1 = tx->tx_map_key.qword1;
462         hndl.qword2 = tx->tx_map_key.qword2;
463
464         seq_printf(s, "%p %x %16"LPF64"u %8d %#8x "LPX64"."LPX64"x\n",
465                 tx, id, nob, physnop, buftype,
466                 hndl.qword1, hndl.qword2);
467
468         return 0;
469 }
470
471 static struct seq_operations kgn_mdd_sops = {
472         .start = kgnilnd_mdd_seq_start,
473         .stop  = kgnilnd_mdd_seq_stop,
474         .next  = kgnilnd_mdd_seq_next,
475         .show  = kgnilnd_mdd_seq_show,
476
477 };
478
479 static int
480 kgnilnd_mdd_seq_open(struct inode *inode, struct file *file)
481 {
482         struct seq_file       *sf;
483         int                    rc;
484
485         rc = seq_open(file, &kgn_mdd_sops);
486         if (rc == 0) {
487                 sf = file->private_data;
488
489                 /* NULL means we've not yet open() */
490                 sf->private = NULL;
491         }
492         return rc;
493 }
494
495 static struct file_operations kgn_mdd_fops = {
496         .owner   = THIS_MODULE,
497         .open    = kgnilnd_mdd_seq_open,
498         .read    = seq_read,
499         .llseek  = seq_lseek,
500         .release = seq_release,
501 };
502
503 typedef struct {
504         __u64                   gsmsg_version;
505         kgn_device_t           *gsmsg_dev;
506         kgn_fma_memblock_t     *gsmsg_fmablk;
507         loff_t                  gsmsg_off;
508 } kgn_smsg_seq_iter_t;
509
510 int
511 kgnilnd_smsg_seq_seek(kgn_smsg_seq_iter_t *gseq, loff_t off)
512 {
513         kgn_fma_memblock_t             *fmablk;
514         kgn_device_t                   *dev;
515         struct list_head               *r;
516         loff_t                          here;
517         int                             rc = 0;
518
519         /* offset 0 is the header, so we start real entries at
520          * here == off == 1 */
521         if (off == 0) {
522                 gseq->gsmsg_fmablk = NULL;
523                 gseq->gsmsg_off = 0;
524                 return 0;
525         }
526
527         fmablk = gseq->gsmsg_fmablk;
528         dev = gseq->gsmsg_dev;
529
530         spin_lock(&dev->gnd_fmablk_lock);
531
532         if (fmablk != NULL &&
533                 gseq->gsmsg_version != atomic_read(&dev->gnd_fmablk_vers)) {
534                 /* list changed */
535                 rc = -ESTALE;
536                 goto out;
537         }
538
539         if (fmablk == NULL || gseq->gsmsg_off > off) {
540                 /* search from start */
541                 r = dev->gnd_fma_buffs.next;
542                 here = 1;
543         } else {
544                 /* continue current search */
545                 r = &fmablk->gnm_bufflist;
546                 here = gseq->gsmsg_off;
547         }
548
549         gseq->gsmsg_version = atomic_read(&dev->gnd_fmablk_vers);
550         gseq->gsmsg_off = off;
551
552         while (r != &dev->gnd_fma_buffs) {
553                 kgn_fma_memblock_t      *t;
554
555                 t = list_entry(r, kgn_fma_memblock_t, gnm_bufflist);
556
557                 if (here == off) {
558                         gseq->gsmsg_fmablk = t;
559                         rc = 0;
560                         goto out;
561                 }
562                 r = r->next;
563                 here++;
564         }
565
566         gseq->gsmsg_fmablk = NULL;
567         rc = -ENOENT;
568 out:
569         spin_unlock(&dev->gnd_fmablk_lock);
570         return rc;
571 }
572
573 static void *
574 kgnilnd_smsg_seq_start(struct seq_file *s, loff_t *pos)
575 {
576
577         kgn_smsg_seq_iter_t     *gseq;
578         int                      rc;
579
580         if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
581                 return NULL;
582         }
583
584         LIBCFS_ALLOC(gseq, sizeof(*gseq));
585         if (gseq == NULL) {
586                 CERROR("could not allocate smsg sequence iterator\n");
587                 return NULL;
588         }
589
590         /* only doing device 0 for now */
591         gseq->gsmsg_dev = &kgnilnd_data.kgn_devices[0];
592         gseq->gsmsg_fmablk = NULL;
593         rc = kgnilnd_smsg_seq_seek(gseq, *pos);
594         if (rc == 0)
595                 return gseq;
596
597         LIBCFS_FREE(gseq, sizeof(*gseq));
598         return NULL;
599 }
600
601 static void
602 kgnilnd_smsg_seq_stop(struct seq_file *s, void *iter)
603 {
604         kgn_smsg_seq_iter_t     *gseq = iter;
605
606         if (gseq != NULL)
607                 LIBCFS_FREE(gseq, sizeof(*gseq));
608 }
609
610 static void *
611 kgnilnd_smsg_seq_next(struct seq_file *s, void *iter, loff_t *pos)
612 {
613         kgn_smsg_seq_iter_t    *gseq = iter;
614         int                     rc;
615         loff_t                  next = *pos + 1;
616
617         rc = kgnilnd_smsg_seq_seek(gseq, next);
618         if (rc != 0) {
619                 LIBCFS_FREE(gseq, sizeof(*gseq));
620                 return NULL;
621         }
622         *pos = next;
623         return gseq;
624 }
625
626 static int
627 kgnilnd_smsg_seq_show(struct seq_file *s, void *iter)
628 {
629         kgn_smsg_seq_iter_t    *gseq = iter;
630         kgn_fma_memblock_t     *fmablk;
631         kgn_device_t           *dev;
632         int                     avail_mboxs, held_mboxs, num_mboxs;
633         unsigned int            blk_size;
634         int                     live;
635         kgn_fmablk_state_t      state;
636         gni_mem_handle_t        hndl;
637
638         if (gseq->gsmsg_off == 0) {
639                 seq_printf(s, "%5s %4s %6s/%5s/%5s %9s %18s %37s\n",
640                         "blk#", "type", "avail", "held", "total", "size",
641                         "fmablk", "mem handle");
642                 return 0;
643         }
644
645         fmablk = gseq->gsmsg_fmablk;
646         dev = gseq->gsmsg_dev;
647         LASSERT(fmablk != NULL);
648
649         spin_lock(&dev->gnd_fmablk_lock);
650
651         if (gseq->gsmsg_version != atomic_read(&dev->gnd_fmablk_vers)) {
652                 /* list changed */
653                 spin_unlock(&dev->gnd_fmablk_lock);
654                 return -ESTALE;
655         }
656
657         live = fmablk->gnm_hold_timeout == 0;
658         /* none are available if it isn't live... */
659         avail_mboxs = live ? fmablk->gnm_avail_mboxs : 0;
660         held_mboxs = fmablk->gnm_held_mboxs;
661         num_mboxs = fmablk->gnm_num_mboxs;
662         blk_size = fmablk->gnm_blk_size;
663         state = fmablk->gnm_state;
664         hndl.qword1 = fmablk->gnm_hndl.qword1;
665         hndl.qword2 = fmablk->gnm_hndl.qword2;
666
667         spin_unlock(&dev->gnd_fmablk_lock);
668
669         if (live) {
670                 seq_printf(s, "%5d %4s %6d/%5d/%5d %9d %18p   "LPX64"."LPX64"\n",
671                            (int) gseq->gsmsg_off, kgnilnd_fmablk_state2str(state),
672                            avail_mboxs, held_mboxs, num_mboxs, blk_size,
673                            fmablk, hndl.qword1, hndl.qword2);
674         } else {
675                 seq_printf(s, "%5d %4s %6d/%5d/%5d %9d %18p %37s\n",
676                            (int) gseq->gsmsg_off, kgnilnd_fmablk_state2str(state),
677                            avail_mboxs, held_mboxs, num_mboxs, blk_size,
678                            fmablk, "PURGATORY.HOLD");
679         }
680
681         return 0;
682 }
683
684 static struct seq_operations kgn_smsg_sops = {
685         .start = kgnilnd_smsg_seq_start,
686         .stop  = kgnilnd_smsg_seq_stop,
687         .next  = kgnilnd_smsg_seq_next,
688         .show  = kgnilnd_smsg_seq_show,
689
690 };
691
692 static int
693 kgnilnd_smsg_seq_open(struct inode *inode, struct file *file)
694 {
695         struct seq_file       *sf;
696         int                    rc;
697
698         rc = seq_open(file, &kgn_smsg_sops);
699         if (rc == 0) {
700                 sf = file->private_data;
701                 sf->private = PDE_DATA(inode);
702         }
703
704         return rc;
705 }
706
707 static struct file_operations kgn_smsg_fops = {
708         .owner   = THIS_MODULE,
709         .open    = kgnilnd_smsg_seq_open,
710         .read    = seq_read,
711         .llseek  = seq_lseek,
712         .release = seq_release,
713 };
714
715 typedef struct {
716         __u64                   gconn_version;
717         struct list_head       *gconn_list;
718         kgn_conn_t             *gconn_conn;
719         loff_t                  gconn_off;
720         int                     gconn_hashidx;
721 } kgn_conn_seq_iter_t;
722
723 int
724 kgnilnd_conn_seq_seek(kgn_conn_seq_iter_t *gseq, loff_t off)
725 {
726         struct list_head       *list, *tmp;
727         loff_t                  here = 0;
728         int                     rc = 0;
729
730         if (off == 0) {
731                 gseq->gconn_hashidx = 0;
732                 gseq->gconn_list = NULL;
733         }
734
735         if (off > atomic_read(&kgnilnd_data.kgn_nconns)) {
736                 gseq->gconn_list = NULL;
737                 rc = -ENOENT;
738         }
739
740         read_lock(&kgnilnd_data.kgn_peer_conn_lock);
741         if (gseq->gconn_list != NULL &&
742                 gseq->gconn_version != kgnilnd_data.kgn_conn_version) {
743                 /* list changed */
744                 rc = -ESTALE;
745                 goto out;
746         }
747
748         if ((gseq->gconn_list == NULL) ||
749                 (gseq->gconn_off > off) ||
750                 (gseq->gconn_hashidx >= *kgnilnd_tunables.kgn_peer_hash_size)) {
751                 /* search from start */
752                 gseq->gconn_hashidx = 0;
753                 list = &kgnilnd_data.kgn_conns[gseq->gconn_hashidx];
754                 here = 0;
755         } else {
756                 /* continue current search */
757                 list = gseq->gconn_list;
758         }
759
760         gseq->gconn_version = kgnilnd_data.kgn_conn_version;
761         gseq->gconn_off = off;
762
763 start_list:
764
765         list_for_each(tmp, list) {
766                 if (here == off) {
767                         kgn_conn_t *conn;
768                         conn = list_entry(tmp, kgn_conn_t, gnc_hashlist);
769                         gseq->gconn_conn = conn;
770                         rc = 0;
771                         goto out;
772                 }
773                 here++;
774         }
775         /* if we got through this hash bucket with 'off' still to go, try next*/
776         gseq->gconn_hashidx++;
777         if ((here <= off) &&
778                 (gseq->gconn_hashidx < *kgnilnd_tunables.kgn_peer_hash_size)) {
779                 list = &kgnilnd_data.kgn_conns[gseq->gconn_hashidx];
780                 goto start_list;
781         }
782
783         gseq->gconn_list = NULL;
784         rc = -ENOENT;
785 out:
786         read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
787         return rc;
788 }
789
790 static void *
791 kgnilnd_conn_seq_start(struct seq_file *s, loff_t *pos)
792 {
793
794         kgn_conn_seq_iter_t     *gseq;
795         int                      rc;
796
797         if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
798                 return NULL;
799         }
800
801         LIBCFS_ALLOC(gseq, sizeof(*gseq));
802         if (gseq == NULL) {
803                 CERROR("could not allocate conn sequence iterator\n");
804                 return NULL;
805         }
806
807         /* only doing device 0 for now */
808         gseq->gconn_list = NULL;
809         rc = kgnilnd_conn_seq_seek(gseq, *pos);
810         if (rc == 0)
811                 return gseq;
812
813         LIBCFS_FREE(gseq, sizeof(*gseq));
814         return NULL;
815 }
816
817 static void
818 kgnilnd_conn_seq_stop(struct seq_file *s, void *iter)
819 {
820         kgn_conn_seq_iter_t     *gseq = iter;
821
822         if (gseq != NULL)
823                 LIBCFS_FREE(gseq, sizeof(*gseq));
824 }
825
826 static void *
827 kgnilnd_conn_seq_next(struct seq_file *s, void *iter, loff_t *pos)
828 {
829         kgn_conn_seq_iter_t    *gseq = iter;
830         int                     rc;
831         loff_t                  next = *pos + 1;
832
833         rc = kgnilnd_conn_seq_seek(gseq, next);
834         if (rc != 0) {
835                 LIBCFS_FREE(gseq, sizeof(*gseq));
836                 return NULL;
837         }
838         *pos = next;
839         return gseq;
840 }
841
842 static int
843 kgnilnd_conn_seq_show(struct seq_file *s, void *iter)
844 {
845         kgn_conn_seq_iter_t    *gseq = iter;
846         kgn_peer_t             *peer = NULL;
847         kgn_conn_t             *conn;
848
849         /* there is no header data for conns, so offset 0 is the first
850          * real entry. */
851
852         conn = gseq->gconn_conn;
853         LASSERT(conn != NULL);
854
855         read_lock(&kgnilnd_data.kgn_peer_conn_lock);
856         if (gseq->gconn_list != NULL &&
857                 gseq->gconn_version != kgnilnd_data.kgn_conn_version) {
858                 /* list changed */
859                 read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
860                 return -ESTALE;
861         }
862
863         /* instead of saving off the data, just refcount */
864         kgnilnd_conn_addref(conn);
865         if (conn->gnc_peer) {
866                 /* don't use link - after unlock it could get nuked */
867                 peer = conn->gnc_peer;
868                 kgnilnd_peer_addref(peer);
869         }
870
871         read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
872
873         seq_printf(s, "%p->%s [%d] q %d/%d/%d "
874                 "tx sq %u %dms/%dms "
875                 "rx sq %u %dms/%dms "
876                 "noop r/s %d/%d w/s/cq %lds/%lds/%lds "
877                 "sched a/d %lds/%lds "
878                 "tx_re "LPD64" TO %ds %s\n",
879                 conn, peer ? libcfs_nid2str(peer->gnp_nid) : "<?>",
880                 atomic_read(&conn->gnc_refcount),
881                 kgnilnd_count_list(&conn->gnc_fmaq),
882                 atomic_read(&conn->gnc_nlive_fma),
883                 atomic_read(&conn->gnc_nlive_rdma),
884                 conn->gnc_tx_seq,
885                 jiffies_to_msecs(jiffies - conn->gnc_last_tx),
886                 jiffies_to_msecs(jiffies - conn->gnc_last_tx_cq),
887                 conn->gnc_rx_seq,
888                 jiffies_to_msecs(jiffies - conn->gnc_last_rx),
889                 jiffies_to_msecs(jiffies - conn->gnc_last_rx_cq),
890                 atomic_read(&conn->gnc_reaper_noop),
891                 atomic_read(&conn->gnc_sched_noop),
892                 cfs_duration_sec(jiffies - conn->gnc_last_noop_want),
893                 cfs_duration_sec(jiffies - conn->gnc_last_noop_sent),
894                 cfs_duration_sec(jiffies - conn->gnc_last_noop_cq),
895                 cfs_duration_sec(jiffies - conn->gnc_last_sched_ask),
896                 cfs_duration_sec(jiffies - conn->gnc_last_sched_do),
897                 conn->gnc_tx_retrans, conn->gnc_timeout,
898                 kgnilnd_conn_state2str(conn));
899
900         if (peer)
901                 kgnilnd_peer_decref(peer);
902         kgnilnd_conn_decref(conn);
903
904         return 0;
905 }
906
907 static struct seq_operations kgn_conn_sops = {
908         .start = kgnilnd_conn_seq_start,
909         .stop  = kgnilnd_conn_seq_stop,
910         .next  = kgnilnd_conn_seq_next,
911         .show  = kgnilnd_conn_seq_show,
912
913 };
914
915 #define KGN_DEBUG_PEER_NID_DEFAULT -1
916 static int kgnilnd_debug_peer_nid = KGN_DEBUG_PEER_NID_DEFAULT;
917
918 static int
919 kgnilnd_proc_peer_conns_write(struct file *file, const char *ubuffer,
920                               unsigned long count, void *data)
921 {
922         char dummy[8];
923         int  rc;
924
925         if (count >= sizeof(dummy) || count == 0)
926                 return -EINVAL;
927
928         if (copy_from_user(dummy, ubuffer, count))
929                 return -EFAULT;
930
931         rc = sscanf(dummy, "%d", &kgnilnd_debug_peer_nid);
932
933         if (rc != 1) {
934                 return -EINVAL;
935         }
936
937         RETURN(count);
938 }
939
940 /* debug data to print from conns associated with peer nid
941   -  date/time
942   -  peer nid
943   -  mbox_addr (msg_buffer + mbox_offset)
944   -  gnc_dgram_type
945   -  gnc_in_purgatory
946   -  gnc_state
947   -  gnc_error
948   -  gnc_peer_error
949   -  gnc_tx_seq
950   -  gnc_last_tx
951   -  gnc_last_tx_cq
952   -  gnc_rx_seq
953   -  gnc_first_rx
954   -  gnc_last_rx
955   -  gnc_last_rx_cq
956   -  gnc_tx_retrans
957   -  gnc_close_sent
958   -  gnc_close_recvd
959 */
960
961 static int
962 kgnilnd_proc_peer_conns_read(char *page, char **start, off_t off,
963                              int count, int *eof, void *data)
964 {
965         kgn_peer_t      *peer;
966         kgn_conn_t      *conn;
967         struct tm       ctm;
968         struct timespec now;
969         unsigned long   jifs;
970         int             len = 0;
971         int             rc;
972
973         if (kgnilnd_debug_peer_nid == KGN_DEBUG_PEER_NID_DEFAULT) {
974                 rc = sprintf(page, "peer_conns not initialized\n");
975                 return rc;
976         }
977
978         /* sample date/time stamp - print time in UTC
979          * 2012-12-11T16:06:16.966751 123@gni ...
980          */
981         getnstimeofday(&now);
982         time_to_tm(now.tv_sec, 0, &ctm);
983         jifs = jiffies;
984
985         write_lock(&kgnilnd_data.kgn_peer_conn_lock);
986         peer = kgnilnd_find_peer_locked(kgnilnd_debug_peer_nid);
987
988         if (peer == NULL) {
989                 rc = sprintf(page, "peer not found for this nid %d\n",
990                              kgnilnd_debug_peer_nid);
991                 write_unlock(&kgnilnd_data.kgn_peer_conn_lock);
992                 return rc;
993         }
994
995         list_for_each_entry(conn, &peer->gnp_conns, gnc_list) {
996                 len += scnprintf(page, count - len,
997                         "%04ld-%02d-%02dT%02d:%02d:%02d.%06ld %s "
998                         "mbox adr %p "
999                         "dg type %s "
1000                         "%s "
1001                         "purg %d "
1002                         "close s/r %d/%d "
1003                         "err %d peer err %d "
1004                         "tx sq %u %dms/%dms "
1005                         "rx sq %u %dms/%dms/%dms "
1006                         "tx retran %lld\n",
1007                         ctm.tm_year+1900, ctm.tm_mon+1, ctm.tm_mday,
1008                         ctm.tm_hour, ctm.tm_min, ctm.tm_sec, now.tv_nsec,
1009                         libcfs_nid2str(peer->gnp_nid),
1010                         conn->remote_mbox_addr,
1011                         kgnilnd_conn_dgram_type2str(conn->gnc_dgram_type),
1012                         kgnilnd_conn_state2str(conn),
1013                         conn->gnc_in_purgatory,
1014                         conn->gnc_close_sent,
1015                         conn->gnc_close_recvd,
1016                         conn->gnc_error,
1017                         conn->gnc_peer_error,
1018                         conn->gnc_tx_seq,
1019                         jiffies_to_msecs(jifs - conn->gnc_last_tx),
1020                         jiffies_to_msecs(jifs - conn->gnc_last_tx_cq),
1021                         conn->gnc_rx_seq,
1022                         jiffies_to_msecs(jifs - conn->gnc_first_rx),
1023                         jiffies_to_msecs(jifs - conn->gnc_last_rx),
1024                         jiffies_to_msecs(jifs - conn->gnc_last_rx_cq),
1025                         conn->gnc_tx_retrans);
1026         }
1027
1028         write_unlock(&kgnilnd_data.kgn_peer_conn_lock);
1029         return len;
1030 }
1031
1032 static int
1033 kgnilnd_conn_seq_open(struct inode *inode, struct file *file)
1034 {
1035         struct seq_file       *sf;
1036         int                    rc;
1037
1038         rc = seq_open(file, &kgn_conn_sops);
1039         if (rc == 0) {
1040                 sf = file->private_data;
1041                 sf->private = PDE_DATA(inode);
1042         }
1043
1044         return rc;
1045 }
1046
1047 static struct file_operations kgn_conn_fops = {
1048         .owner   = THIS_MODULE,
1049         .open    = kgnilnd_conn_seq_open,
1050         .read    = seq_read,
1051         .llseek  = seq_lseek,
1052         .release = seq_release,
1053 };
1054
1055 typedef struct {
1056         __u64                   gpeer_version;
1057         struct list_head       *gpeer_list;
1058         kgn_peer_t             *gpeer_peer;
1059         loff_t                  gpeer_off;
1060         int                     gpeer_hashidx;
1061 } kgn_peer_seq_iter_t;
1062
1063 int
1064 kgnilnd_peer_seq_seek(kgn_peer_seq_iter_t *gseq, loff_t off)
1065 {
1066         struct list_head       *list, *tmp;
1067         loff_t                  here = 0;
1068         int                     rc = 0;
1069
1070         if (off == 0) {
1071                 gseq->gpeer_hashidx = 0;
1072                 gseq->gpeer_list = NULL;
1073         }
1074
1075         if (off > atomic_read(&kgnilnd_data.kgn_npeers)) {
1076                 gseq->gpeer_list = NULL;
1077                 rc = -ENOENT;
1078         }
1079
1080         read_lock(&kgnilnd_data.kgn_peer_conn_lock);
1081         if (gseq->gpeer_list != NULL &&
1082                 gseq->gpeer_version != kgnilnd_data.kgn_peer_version) {
1083                 /* list changed */
1084                 rc = -ESTALE;
1085                 goto out;
1086         }
1087
1088         if ((gseq->gpeer_list == NULL) ||
1089                 (gseq->gpeer_off > off) ||
1090                 (gseq->gpeer_hashidx >= *kgnilnd_tunables.kgn_peer_hash_size)) {
1091                 /* search from start */
1092                 gseq->gpeer_hashidx = 0;
1093                 list = &kgnilnd_data.kgn_peers[gseq->gpeer_hashidx];
1094                 here = 0;
1095         } else {
1096                 /* continue current search */
1097                 list = gseq->gpeer_list;
1098         }
1099
1100         gseq->gpeer_version = kgnilnd_data.kgn_peer_version;
1101         gseq->gpeer_off = off;
1102
1103 start_list:
1104
1105         list_for_each(tmp, list) {
1106                 if (here == off) {
1107                         kgn_peer_t *peer;
1108                         peer = list_entry(tmp, kgn_peer_t, gnp_list);
1109                         gseq->gpeer_peer = peer;
1110                         rc = 0;
1111                         goto out;
1112                 }
1113                 here++;
1114         }
1115         /* if we got through this hash bucket with 'off' still to go, try next*/
1116         gseq->gpeer_hashidx++;
1117         if ((here <= off) &&
1118                 (gseq->gpeer_hashidx < *kgnilnd_tunables.kgn_peer_hash_size)) {
1119                 list = &kgnilnd_data.kgn_peers[gseq->gpeer_hashidx];
1120                 goto start_list;
1121         }
1122
1123         gseq->gpeer_list = NULL;
1124         rc = -ENOENT;
1125 out:
1126         read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
1127         return rc;
1128 }
1129
1130 static void *
1131 kgnilnd_peer_seq_start(struct seq_file *s, loff_t *pos)
1132 {
1133
1134         kgn_peer_seq_iter_t     *gseq;
1135         int                      rc;
1136
1137         if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
1138                 return NULL;
1139         }
1140
1141         LIBCFS_ALLOC(gseq, sizeof(*gseq));
1142         if (gseq == NULL) {
1143                 CERROR("could not allocate peer sequence iterator\n");
1144                 return NULL;
1145         }
1146
1147         /* only doing device 0 for now */
1148         gseq->gpeer_list = NULL;
1149         rc = kgnilnd_peer_seq_seek(gseq, *pos);
1150         if (rc == 0)
1151                 return gseq;
1152
1153         LIBCFS_FREE(gseq, sizeof(*gseq));
1154         return NULL;
1155 }
1156
1157 static void
1158 kgnilnd_peer_seq_stop(struct seq_file *s, void *iter)
1159 {
1160         kgn_peer_seq_iter_t     *gseq = iter;
1161
1162         if (gseq != NULL)
1163                 LIBCFS_FREE(gseq, sizeof(*gseq));
1164 }
1165
1166 static void *
1167 kgnilnd_peer_seq_next(struct seq_file *s, void *iter, loff_t *pos)
1168 {
1169         kgn_peer_seq_iter_t    *gseq = iter;
1170         int                     rc;
1171         loff_t                  next = *pos + 1;
1172
1173         rc = kgnilnd_peer_seq_seek(gseq, next);
1174         if (rc != 0) {
1175                 LIBCFS_FREE(gseq, sizeof(*gseq));
1176                 return NULL;
1177         }
1178         *pos = next;
1179         return gseq;
1180 }
1181
1182 static int
1183 kgnilnd_peer_seq_show(struct seq_file *s, void *iter)
1184 {
1185         kgn_peer_seq_iter_t    *gseq = iter;
1186         kgn_peer_t             *peer;
1187         kgn_conn_t             *conn;
1188         char                   conn_str;
1189         int                    purg_count = 0;
1190         /* there is no header data for peers, so offset 0 is the first
1191          * real entry. */
1192
1193         peer = gseq->gpeer_peer;
1194         LASSERT(peer != NULL);
1195
1196         read_lock(&kgnilnd_data.kgn_peer_conn_lock);
1197         if (gseq->gpeer_list != NULL &&
1198                 gseq->gpeer_version != kgnilnd_data.kgn_peer_version) {
1199                 /* list changed */
1200                 read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
1201                 return -ESTALE;
1202         }
1203
1204         /* instead of saving off the data, just refcount */
1205         kgnilnd_peer_addref(peer);
1206         conn = kgnilnd_find_conn_locked(peer);
1207
1208         if (peer->gnp_connecting) {
1209                 conn_str = 'S';
1210         } else if (conn != NULL) {
1211                 conn_str = 'C';
1212         } else {
1213                 conn_str = 'D';
1214         }
1215
1216         list_for_each_entry(conn, &peer->gnp_conns, gnc_list) {
1217                 if (conn->gnc_in_purgatory) {
1218                         purg_count++;
1219                 }
1220         }
1221
1222         read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
1223
1224         seq_printf(s, "%p->%s [%d] %s NIC 0x%x q %d conn %c purg %d "
1225                 "last %d@%dms dgram %d@%dms "
1226                 "reconn %dms to %lus \n",
1227                 peer, libcfs_nid2str(peer->gnp_nid),
1228                 atomic_read(&peer->gnp_refcount),
1229                 (peer->gnp_down == GNILND_RCA_NODE_DOWN) ? "down" : "up",
1230                 peer->gnp_host_id,
1231                 kgnilnd_count_list(&peer->gnp_tx_queue),
1232                 conn_str,
1233                 purg_count,
1234                 peer->gnp_last_errno,
1235                 jiffies_to_msecs(jiffies - peer->gnp_last_alive),
1236                 peer->gnp_last_dgram_errno,
1237                 jiffies_to_msecs(jiffies - peer->gnp_last_dgram_time),
1238                 peer->gnp_reconnect_interval != 0
1239                         ? jiffies_to_msecs(jiffies - peer->gnp_reconnect_time)
1240                         : 0,
1241                 peer->gnp_reconnect_interval);
1242
1243         kgnilnd_peer_decref(peer);
1244
1245         return 0;
1246 }
1247
1248 static struct seq_operations kgn_peer_sops = {
1249         .start = kgnilnd_peer_seq_start,
1250         .stop  = kgnilnd_peer_seq_stop,
1251         .next  = kgnilnd_peer_seq_next,
1252         .show  = kgnilnd_peer_seq_show,
1253 };
1254
1255 static int
1256 kgnilnd_peer_seq_open(struct inode *inode, struct file *file)
1257 {
1258         struct seq_file       *sf;
1259         int                    rc;
1260
1261         rc = seq_open(file, &kgn_peer_sops);
1262         if (rc == 0) {
1263                 sf = file->private_data;
1264                 sf->private = PDE_DATA(inode);
1265         }
1266
1267         return rc;
1268 }
1269
1270 static struct file_operations kgn_peer_fops = {
1271         .owner   = THIS_MODULE,
1272         .open    = kgnilnd_peer_seq_open,
1273         .read    = seq_read,
1274         .llseek  = seq_lseek,
1275         .release = seq_release,
1276 };
1277
1278 static struct proc_dir_entry *kgn_proc_root;
1279
1280 void
1281 kgnilnd_proc_init(void)
1282 {
1283         struct proc_dir_entry *pde;
1284         int             rc = 0;
1285         ENTRY;
1286
1287         /* setup dir */
1288         kgn_proc_root = proc_mkdir(libcfs_lnd2modname(GNILND), NULL);
1289         if (kgn_proc_root == NULL) {
1290                 CERROR("couldn't create proc dir %s\n",
1291                         libcfs_lnd2modname(GNILND));
1292                 return;
1293         }
1294
1295         /* Initialize CKSUM_TEST */
1296         pde = create_proc_entry(GNILND_PROC_CKSUM_TEST, 0200, kgn_proc_root);
1297         if (pde == NULL) {
1298                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_CKSUM_TEST);
1299                 GOTO(remove_dir, rc = -ENOENT);
1300         }
1301
1302         pde->data = NULL;
1303         pde->write_proc = kgnilnd_proc_cksum_test_write;
1304
1305         /* Initialize STATS */
1306         pde = create_proc_entry(GNILND_PROC_STATS, 0644, kgn_proc_root);
1307         if (pde == NULL) {
1308                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_STATS);
1309                 GOTO(remove_test, rc = -ENOENT);
1310         }
1311
1312         pde->data = NULL;
1313         pde->read_proc = kgnilnd_proc_stats_read;
1314         pde->write_proc = kgnilnd_proc_stats_write;
1315
1316         /* Initialize MDD */
1317         pde = create_proc_entry(GNILND_PROC_MDD, 0444, kgn_proc_root);
1318         if (pde == NULL) {
1319                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_MDD);
1320                 GOTO(remove_stats, rc = -ENOENT);
1321         }
1322
1323         pde->data = NULL;
1324         pde->proc_fops = &kgn_mdd_fops;
1325
1326         /* Initialize SMSG */
1327         pde = create_proc_entry(GNILND_PROC_SMSG, 0444, kgn_proc_root);
1328         if (pde == NULL) {
1329                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_SMSG);
1330                 GOTO(remove_mdd, rc = -ENOENT);
1331         }
1332
1333         pde->data = NULL;
1334         pde->proc_fops = &kgn_smsg_fops;
1335
1336         /* Initialize CONN */
1337         pde = create_proc_entry(GNILND_PROC_CONN, 0444, kgn_proc_root);
1338         if (pde == NULL) {
1339                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_CONN);
1340                 GOTO(remove_smsg, rc = -ENOENT);
1341         }
1342
1343         pde->data = NULL;
1344         pde->proc_fops = &kgn_conn_fops;
1345
1346         /* Initialize peer conns debug */
1347         pde = create_proc_entry(GNILND_PROC_PEER_CONNS, 0644, kgn_proc_root);
1348         if (pde == NULL) {
1349                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_PEER_CONNS);
1350                 GOTO(remove_conn, rc = -ENOENT);
1351         }
1352
1353         pde->data = NULL;
1354         pde->read_proc = kgnilnd_proc_peer_conns_read;
1355         pde->write_proc = kgnilnd_proc_peer_conns_write;
1356
1357         /* Initialize PEER */
1358         pde = create_proc_entry(GNILND_PROC_PEER, 0444, kgn_proc_root);
1359         if (pde == NULL) {
1360                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_PEER);
1361                 GOTO(remove_pc, rc = -ENOENT);
1362         }
1363
1364         pde->data = NULL;
1365         pde->proc_fops = &kgn_peer_fops;
1366         RETURN_EXIT;
1367
1368 remove_pc:
1369         remove_proc_entry(GNILND_PROC_PEER_CONNS, kgn_proc_root);
1370 remove_conn:
1371         remove_proc_entry(GNILND_PROC_CONN, kgn_proc_root);
1372 remove_smsg:
1373         remove_proc_entry(GNILND_PROC_SMSG, kgn_proc_root);
1374 remove_mdd:
1375         remove_proc_entry(GNILND_PROC_MDD, kgn_proc_root);
1376 remove_stats:
1377         remove_proc_entry(GNILND_PROC_STATS, kgn_proc_root);
1378 remove_test:
1379         remove_proc_entry(GNILND_PROC_CKSUM_TEST, kgn_proc_root);
1380 remove_dir:
1381         remove_proc_entry(kgn_proc_root->name, NULL);
1382
1383         RETURN_EXIT;
1384 }
1385
1386 void
1387 kgnilnd_proc_fini(void)
1388 {
1389         remove_proc_entry(GNILND_PROC_PEER_CONNS, kgn_proc_root);
1390         remove_proc_entry(GNILND_PROC_PEER, kgn_proc_root);
1391         remove_proc_entry(GNILND_PROC_CONN, kgn_proc_root);
1392         remove_proc_entry(GNILND_PROC_MDD, kgn_proc_root);
1393         remove_proc_entry(GNILND_PROC_SMSG, kgn_proc_root);
1394         remove_proc_entry(GNILND_PROC_STATS, kgn_proc_root);
1395         remove_proc_entry(GNILND_PROC_CKSUM_TEST, kgn_proc_root);
1396         remove_proc_entry(kgn_proc_root->name, NULL);
1397 }