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