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