Whamcloud - gitweb
LU-17744 ldiskfs: mballoc stats fixes
[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         struct bio_vec          *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         CFS_ALLOC_PTR_ARRAY(src, LNET_MAX_IOV);
52         CFS_ALLOC_PTR_ARRAY(dest, LNET_MAX_IOV);
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].bv_offset = 0;
61                 src[i].bv_len = PAGE_SIZE;
62                 src[i].bv_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
63
64                 if (src[i].bv_page == NULL) {
65                         CERROR("couldn't allocate page %d\n", i);
66                         GOTO(unwind, rc = -ENOMEM);
67                 }
68
69                 dest[i].bv_offset = 0;
70                 dest[i].bv_len = PAGE_SIZE;
71                 dest[i].bv_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
72
73                 if (dest[i].bv_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].bv_offset = 317;
89         dest[0].bv_offset = 592;
90         switch (caseno) {
91         default:
92                 /* odd -> even */
93                 break;
94         case 1:
95                 /* odd -> odd */
96                 dest[0].bv_offset -= 1;
97                 break;
98         case 2:
99                 /* even -> even */
100                 src[0].bv_offset += 1;
101                 break;
102         case 3:
103                 /* even -> odd */
104                 src[0].bv_offset += 1;
105                 dest[0].bv_offset -= 1;
106         }
107         src[0].bv_len = PAGE_SIZE - src[0].bv_offset;
108         dest[0].bv_len = PAGE_SIZE - dest[0].bv_offset;
109
110         for (i = 0; i < niov; i++) {
111                 memset(page_address(src[i].bv_page) + src[i].bv_offset,
112                        0xf0 + i, src[i].bv_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,
121                        "case %d loop %d src %d dest %d nob %d niov %d\n",
122                        caseno, n, src[0].bv_offset, dest[0].bv_offset, nob,
123                        niov);
124                 cksum = kgnilnd_cksum_kiov(niov, src, 0, nob - (n % nob), 1);
125                 cksum2 = kgnilnd_cksum_kiov(niov, dest, 0, nob - (n % nob), 1);
126
127                 if (cksum != cksum2) {
128                         CERROR("case %d loop %d different checksums %x expected %x\n",
129                                j, n, cksum2, cksum);
130                         GOTO(unwind, rc = -ENOKEY);
131                 }
132         }
133
134         getnstimeofday(&end);
135
136         mbytes = ((__u64)nloops * nob * 2) / (1024*1024);
137
138         diff = kgnilnd_ts_sub(end, begin);
139
140         LCONSOLE_INFO("running %lldMB took %ld.%ld seconds\n",
141                       mbytes, diff.tv_sec, diff.tv_nsec);
142
143 unwind:
144         CDEBUG(D_NET, "freeing %d pages\n", i);
145         for (i -= 1; i >= 0; i--) {
146                 if (src[i].bv_page)
147                         __free_page(src[i].bv_page);
148
149                 if (dest[i].bv_page)
150                         __free_page(dest[i].bv_page);
151         }
152
153         if (src != NULL)
154                 CFS_FREE_PTR_ARRAY(src, LNET_MAX_IOV);
155         if (dest != NULL)
156                 CFS_FREE_PTR_ARRAY(dest, LNET_MAX_IOV);
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         .write   = kgnilnd_proc_cksum_test_write,
202         .llseek  = seq_lseek,
203         .release = seq_release,
204 };
205
206 static int
207 kgnilnd_stats_seq_show(struct seq_file *sf, void *v)
208 {
209         kgn_device_t           *dev;
210         struct timespec64 now;
211
212         if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
213                 seq_printf(sf, "kgnilnd is not initialized yet\n");
214                 return 0;
215         }
216
217         /* only do the first device */
218         dev = &kgnilnd_data.kgn_devices[0];
219
220         /* sampling is racy, but so is reading this file! */
221         smp_rmb();
222         ktime_get_ts64(&now);
223
224         seq_printf(sf, "time: %llu.%lu\n"
225                    "ntx: %d\n"
226                    "npeers: %d\n"
227                    "nconns: %d\n"
228                    "nEPs: %d\n"
229                    "ndgrams: %d\n"
230                    "nfmablk: %d\n"
231                    "n_mdd: %d\n"
232                    "n_mdd_held: %d\n"
233                    "n_eager_allocs: %d\n"
234                    "GART map bytes: %lld\n"
235                    "TX queued maps: %d\n"
236                    "TX phys nmaps: %d\n"
237                    "TX phys bytes: %lu\n"
238                    "RDMAQ bytes_auth: %lld\n"
239                    "RDMAQ bytes_left: %lld\n"
240                    "RDMAQ nstalls: %d\n"
241                    "dev mutex delay: %ld\n"
242                    "dev n_yield: %d\n"
243                    "dev n_schedule: %d\n"
244                    "SMSG fast_try: %d\n"
245                    "SMSG fast_ok: %d\n"
246                    "SMSG fast_block: %d\n"
247                    "SMSG ntx: %u\n"
248                    "SMSG tx_bytes: %llu\n"
249                    "SMSG nrx: %u\n"
250                    "SMSG rx_bytes: %llu\n"
251                    "RDMA ntx: %u\n"
252                    "RDMA tx_bytes: %llu\n"
253                    "RDMA nrx: %u\n"
254                    "RDMA rx_bytes: %llu\n"
255                    "VMAP short: %d\n"
256                    "VMAP cksum: %d\n"
257                    "KMAP short: %d\n"
258                    "RDMA REV length: %d\n"
259                    "RDMA REV offset: %d\n"
260                    "RDMA REV copy: %d\n",
261                    (s64)now.tv_sec, now.tv_nsec,
262                    atomic_read(&kgnilnd_data.kgn_ntx),
263                    atomic_read(&kgnilnd_data.kgn_npeers),
264                    atomic_read(&kgnilnd_data.kgn_nconns),
265                    atomic_read(&dev->gnd_neps),
266                    atomic_read(&dev->gnd_ndgrams),
267                    atomic_read(&dev->gnd_nfmablk),
268                    atomic_read(&dev->gnd_n_mdd), atomic_read(&dev->gnd_n_mdd_held),
269                    atomic_read(&kgnilnd_data.kgn_neager_allocs),
270                    (s64)atomic64_read(&dev->gnd_nbytes_map),
271                    atomic_read(&dev->gnd_nq_map),
272                    dev->gnd_map_nphys, dev->gnd_map_physnop * PAGE_SIZE,
273                    (s64)atomic64_read(&dev->gnd_rdmaq_bytes_out),
274                    (s64)atomic64_read(&dev->gnd_rdmaq_bytes_ok),
275                    atomic_read(&dev->gnd_rdmaq_nstalls),
276                    dev->gnd_mutex_delay,
277                    atomic_read(&dev->gnd_n_yield),
278                    atomic_read(&dev->gnd_n_schedule),
279                    atomic_read(&dev->gnd_fast_try),
280                    atomic_read(&dev->gnd_fast_ok),
281                    atomic_read(&dev->gnd_fast_block),
282                    atomic_read(&dev->gnd_short_ntx),
283                    (s64)atomic64_read(&dev->gnd_short_txbytes),
284                    atomic_read(&dev->gnd_short_nrx),
285                    (s64)atomic64_read(&dev->gnd_short_rxbytes),
286                    atomic_read(&dev->gnd_rdma_ntx),
287                    (s64)atomic64_read(&dev->gnd_rdma_txbytes),
288                    atomic_read(&dev->gnd_rdma_nrx),
289                    (s64)atomic64_read(&dev->gnd_rdma_rxbytes),
290                    atomic_read(&kgnilnd_data.kgn_nvmap_short),
291                    atomic_read(&kgnilnd_data.kgn_nvmap_cksum),
292                    atomic_read(&kgnilnd_data.kgn_nkmap_short),
293                    atomic_read(&kgnilnd_data.kgn_rev_length),
294                    atomic_read(&kgnilnd_data.kgn_rev_offset),
295                    atomic_read(&kgnilnd_data.kgn_rev_copy_buff));
296
297         return 0;
298 }
299
300 static ssize_t
301 kgnilnd_proc_stats_write(struct file *file, const char __user *ubuffer,
302                          size_t count, loff_t *ppos)
303 {
304         kgn_device_t           *dev;
305
306         if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
307                 CERROR("kgnilnd is not initialized for stats write\n");
308                 return -EINVAL;
309         }
310
311         /* only do the first device */
312         dev = &kgnilnd_data.kgn_devices[0];
313
314         atomic_set(&dev->gnd_short_ntx, 0);
315         atomic_set(&dev->gnd_short_nrx, 0);
316         atomic64_set(&dev->gnd_short_txbytes, 0);
317         atomic64_set(&dev->gnd_short_rxbytes, 0);
318         atomic_set(&dev->gnd_rdma_ntx, 0);
319         atomic_set(&dev->gnd_rdma_nrx, 0);
320         atomic_set(&dev->gnd_fast_ok, 0);
321         atomic_set(&dev->gnd_fast_try, 0);
322         atomic_set(&dev->gnd_fast_block, 0);
323         atomic64_set(&dev->gnd_rdma_txbytes, 0);
324         atomic64_set(&dev->gnd_rdma_rxbytes, 0);
325         atomic_set(&dev->gnd_rdmaq_nstalls, 0);
326         set_mb(dev->gnd_mutex_delay, 0);
327         atomic_set(&dev->gnd_n_yield, 0);
328         atomic_set(&dev->gnd_n_schedule, 0);
329         atomic_set(&kgnilnd_data.kgn_nvmap_short, 0);
330         atomic_set(&kgnilnd_data.kgn_nvmap_cksum, 0);
331         atomic_set(&kgnilnd_data.kgn_nkmap_short, 0);
332         /* sampling is racy, but so is writing this file! */
333         smp_wmb();
334         return count;
335 }
336
337 static int
338 kgnilnd_stats_seq_open(struct inode *inode, struct file *file)
339 {
340         return single_open(file, kgnilnd_stats_seq_show, PDE_DATA(inode));
341 }
342
343 static const struct file_operations kgn_stats_fops = {
344         .owner   = THIS_MODULE,
345         .open    = kgnilnd_stats_seq_open,
346         .read    = seq_read,
347         .write   = kgnilnd_proc_stats_write,
348         .llseek  = seq_lseek,
349         .release = seq_release,
350 };
351
352 typedef struct {
353         kgn_device_t           *gmdd_dev;
354         kgn_tx_t               *gmdd_tx;
355         loff_t                  gmdd_off;
356 } kgn_mdd_seq_iter_t;
357
358 int
359 kgnilnd_mdd_seq_seek(kgn_mdd_seq_iter_t *gseq, loff_t off)
360 {
361         kgn_tx_t                *tx;
362         struct list_head        *r;
363         loff_t                  here;
364         int                     rc = 0;
365
366         if (off == 0) {
367                 gseq->gmdd_tx = NULL;
368                 gseq->gmdd_off = 0;
369                 return 0;
370         }
371
372         tx = gseq->gmdd_tx;
373
374         if (tx == NULL || gseq->gmdd_off > off) {
375                 /* search from start */
376                 r = gseq->gmdd_dev->gnd_map_list.next;
377                 here = 1;
378         } else {
379                 /* continue current search */
380                 r = &tx->tx_map_list;
381                 here = gseq->gmdd_off;
382         }
383
384         gseq->gmdd_off = off;
385
386         while (r != &gseq->gmdd_dev->gnd_map_list) {
387                 kgn_tx_t      *t;
388
389                 t = list_entry(r, kgn_tx_t, tx_map_list);
390
391                 if (here == off) {
392                         gseq->gmdd_tx = t;
393                         rc = 0;
394                         goto out;
395                 }
396                 r = r->next;
397                 here++;
398         }
399
400         gseq->gmdd_tx = NULL;
401         rc = -ENOENT;
402 out:
403         return rc;
404 }
405
406 static void *
407 kgnilnd_mdd_seq_start(struct seq_file *s, loff_t *pos)
408 {
409
410         kgn_mdd_seq_iter_t      *gseq;
411         int                      rc;
412
413         if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
414                 return NULL;
415         }
416
417         LIBCFS_ALLOC(gseq, sizeof(*gseq));
418         if (gseq == NULL) {
419                 CERROR("could not allocate mdd sequence iterator\n");
420                 return NULL;
421         }
422
423         /* only doing device 0 for now */
424         gseq->gmdd_dev = &kgnilnd_data.kgn_devices[0];
425         gseq->gmdd_tx = NULL;
426
427         /* need to lock map while we poke - huge disturbance
428          * but without it, no way to get the data printed */
429         spin_lock(&gseq->gmdd_dev->gnd_map_lock);
430
431         /* set private to gseq for stop */
432         s->private = gseq;
433
434         rc = kgnilnd_mdd_seq_seek(gseq, *pos);
435         if (rc == 0)
436                 return gseq;
437         else
438                 return NULL;
439 }
440
441 static void
442 kgnilnd_mdd_seq_stop(struct seq_file *s, void *iter)
443 {
444         kgn_mdd_seq_iter_t     *gseq = s->private;
445
446         if (gseq != NULL) {
447                 spin_unlock(&gseq->gmdd_dev->gnd_map_lock);
448                 LIBCFS_FREE(gseq, sizeof(*gseq));
449         }
450 }
451
452 static void *
453 kgnilnd_mdd_seq_next(struct seq_file *s, void *iter, loff_t *pos)
454 {
455         kgn_mdd_seq_iter_t     *gseq = iter;
456         int                     rc;
457         loff_t                  next = *pos + 1;
458
459         rc = kgnilnd_mdd_seq_seek(gseq, next);
460         *pos = next;
461         if (rc != 0) {
462                 return NULL;
463         }
464         return gseq;
465 }
466
467 static int
468 kgnilnd_mdd_seq_show(struct seq_file *s, void *iter)
469 {
470         kgn_mdd_seq_iter_t     *gseq = iter;
471         kgn_tx_t               *tx;
472         __u64                   nob;
473         __u32                   physnop;
474         int                     id;
475         int                     buftype;
476         gni_mem_handle_t        hndl;
477
478         if (gseq->gmdd_off == 0) {
479                 seq_printf(s, "%s %22s %16s %8s %8s %37s\n",
480                         "tx", "tx_id", "nob", "physnop",
481                         "buftype", "mem handle");
482                 return 0;
483         }
484
485         tx = gseq->gmdd_tx;
486         LASSERT(tx != NULL);
487
488         id = tx->tx_id.txe_smsg_id;
489         nob = tx->tx_nob;
490         physnop = tx->tx_phys_npages;
491         buftype = tx->tx_buftype;
492         hndl.qword1 = tx->tx_map_key.qword1;
493         hndl.qword2 = tx->tx_map_key.qword2;
494
495         seq_printf(s, "%p %x %16llu %8d %#8x %#llx.%#llxx\n",
496                 tx, id, nob, physnop, buftype,
497                 hndl.qword1, hndl.qword2);
498
499         return 0;
500 }
501
502 static const struct seq_operations kgn_mdd_sops = {
503         .start = kgnilnd_mdd_seq_start,
504         .stop  = kgnilnd_mdd_seq_stop,
505         .next  = kgnilnd_mdd_seq_next,
506         .show  = kgnilnd_mdd_seq_show,
507
508 };
509
510 static int
511 kgnilnd_mdd_seq_open(struct inode *inode, struct file *file)
512 {
513         struct seq_file       *sf;
514         int                    rc;
515
516         rc = seq_open(file, &kgn_mdd_sops);
517         if (rc == 0) {
518                 sf = file->private_data;
519
520                 /* NULL means we've not yet open() */
521                 sf->private = NULL;
522         }
523         return rc;
524 }
525
526 static const struct file_operations kgn_mdd_fops = {
527         .owner          = THIS_MODULE,
528         .open           = kgnilnd_mdd_seq_open,
529         .read           = seq_read,
530         .llseek         = seq_lseek,
531         .release        = seq_release,
532 };
533
534 typedef struct {
535         __u64                   gsmsg_version;
536         kgn_device_t           *gsmsg_dev;
537         kgn_fma_memblock_t     *gsmsg_fmablk;
538         loff_t                  gsmsg_off;
539 } kgn_smsg_seq_iter_t;
540
541 int
542 kgnilnd_smsg_seq_seek(kgn_smsg_seq_iter_t *gseq, loff_t off)
543 {
544         kgn_fma_memblock_t             *fmablk;
545         kgn_device_t                   *dev;
546         struct list_head               *r;
547         loff_t                          here;
548         int                             rc = 0;
549
550         /* offset 0 is the header, so we start real entries at
551          * here == off == 1 */
552         if (off == 0) {
553                 gseq->gsmsg_fmablk = NULL;
554                 gseq->gsmsg_off = 0;
555                 return 0;
556         }
557
558         fmablk = gseq->gsmsg_fmablk;
559         dev = gseq->gsmsg_dev;
560
561         spin_lock(&dev->gnd_fmablk_lock);
562
563         if (fmablk != NULL &&
564                 gseq->gsmsg_version != atomic_read(&dev->gnd_fmablk_vers)) {
565                 /* list changed */
566                 rc = -ESTALE;
567                 goto out;
568         }
569
570         if (fmablk == NULL || gseq->gsmsg_off > off) {
571                 /* search from start */
572                 r = dev->gnd_fma_buffs.next;
573                 here = 1;
574         } else {
575                 /* continue current search */
576                 r = &fmablk->gnm_bufflist;
577                 here = gseq->gsmsg_off;
578         }
579
580         gseq->gsmsg_version = atomic_read(&dev->gnd_fmablk_vers);
581         gseq->gsmsg_off = off;
582
583         while (r != &dev->gnd_fma_buffs) {
584                 kgn_fma_memblock_t      *t;
585
586                 t = list_entry(r, kgn_fma_memblock_t, gnm_bufflist);
587
588                 if (here == off) {
589                         gseq->gsmsg_fmablk = t;
590                         rc = 0;
591                         goto out;
592                 }
593                 r = r->next;
594                 here++;
595         }
596
597         gseq->gsmsg_fmablk = NULL;
598         rc = -ENOENT;
599 out:
600         spin_unlock(&dev->gnd_fmablk_lock);
601         return rc;
602 }
603
604 static void *
605 kgnilnd_smsg_seq_start(struct seq_file *s, loff_t *pos)
606 {
607
608         kgn_smsg_seq_iter_t     *gseq;
609         int                      rc;
610
611         if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
612                 return NULL;
613         }
614
615         LIBCFS_ALLOC(gseq, sizeof(*gseq));
616         if (gseq == NULL) {
617                 CERROR("could not allocate smsg sequence iterator\n");
618                 return NULL;
619         }
620
621         /* only doing device 0 for now */
622         gseq->gsmsg_dev = &kgnilnd_data.kgn_devices[0];
623         gseq->gsmsg_fmablk = NULL;
624         rc = kgnilnd_smsg_seq_seek(gseq, *pos);
625         if (rc == 0)
626                 return gseq;
627
628         LIBCFS_FREE(gseq, sizeof(*gseq));
629         return NULL;
630 }
631
632 static void
633 kgnilnd_smsg_seq_stop(struct seq_file *s, void *iter)
634 {
635         kgn_smsg_seq_iter_t     *gseq = iter;
636
637         if (gseq != NULL)
638                 LIBCFS_FREE(gseq, sizeof(*gseq));
639 }
640
641 static void *
642 kgnilnd_smsg_seq_next(struct seq_file *s, void *iter, loff_t *pos)
643 {
644         kgn_smsg_seq_iter_t    *gseq = iter;
645         int                     rc;
646         loff_t                  next = *pos + 1;
647
648         rc = kgnilnd_smsg_seq_seek(gseq, next);
649         *pos = next;
650         if (rc != 0) {
651                 LIBCFS_FREE(gseq, sizeof(*gseq));
652                 return NULL;
653         }
654         return gseq;
655 }
656
657 static int
658 kgnilnd_smsg_seq_show(struct seq_file *s, void *iter)
659 {
660         kgn_smsg_seq_iter_t    *gseq = iter;
661         kgn_fma_memblock_t     *fmablk;
662         kgn_device_t           *dev;
663         int                     avail_mboxs, held_mboxs, num_mboxs;
664         unsigned int            blk_size;
665         int                     live;
666         kgn_fmablk_state_t      state;
667         gni_mem_handle_t        hndl;
668
669         if (gseq->gsmsg_off == 0) {
670                 seq_printf(s, "%5s %4s %6s/%5s/%5s %9s %18s %37s\n",
671                         "blk#", "type", "avail", "held", "total", "size",
672                         "fmablk", "mem handle");
673                 return 0;
674         }
675
676         fmablk = gseq->gsmsg_fmablk;
677         dev = gseq->gsmsg_dev;
678         LASSERT(fmablk != NULL);
679
680         spin_lock(&dev->gnd_fmablk_lock);
681
682         if (gseq->gsmsg_version != atomic_read(&dev->gnd_fmablk_vers)) {
683                 /* list changed */
684                 spin_unlock(&dev->gnd_fmablk_lock);
685                 return -ESTALE;
686         }
687
688         live = fmablk->gnm_hold_timeout == 0;
689         /* none are available if it isn't live... */
690         avail_mboxs = live ? fmablk->gnm_avail_mboxs : 0;
691         held_mboxs = fmablk->gnm_held_mboxs;
692         num_mboxs = fmablk->gnm_num_mboxs;
693         blk_size = fmablk->gnm_blk_size;
694         state = fmablk->gnm_state;
695         hndl.qword1 = fmablk->gnm_hndl.qword1;
696         hndl.qword2 = fmablk->gnm_hndl.qword2;
697
698         spin_unlock(&dev->gnd_fmablk_lock);
699
700         if (live) {
701                 seq_printf(s, "%5d %4s %6d/%5d/%5d %9d %18p   %#llx.%#llx\n",
702                            (int) gseq->gsmsg_off, kgnilnd_fmablk_state2str(state),
703                            avail_mboxs, held_mboxs, num_mboxs, blk_size,
704                            fmablk, hndl.qword1, hndl.qword2);
705         } else {
706                 seq_printf(s, "%5d %4s %6d/%5d/%5d %9d %18p %37s\n",
707                            (int) gseq->gsmsg_off, kgnilnd_fmablk_state2str(state),
708                            avail_mboxs, held_mboxs, num_mboxs, blk_size,
709                            fmablk, "PURGATORY.HOLD");
710         }
711
712         return 0;
713 }
714
715 static const struct seq_operations kgn_smsg_sops = {
716         .start = kgnilnd_smsg_seq_start,
717         .stop  = kgnilnd_smsg_seq_stop,
718         .next  = kgnilnd_smsg_seq_next,
719         .show  = kgnilnd_smsg_seq_show,
720
721 };
722
723 static int
724 kgnilnd_smsg_seq_open(struct inode *inode, struct file *file)
725 {
726         struct seq_file       *sf;
727         int                    rc;
728
729         rc = seq_open(file, &kgn_smsg_sops);
730         if (rc == 0) {
731                 sf = file->private_data;
732                 sf->private = PDE_DATA(inode);
733         }
734
735         return rc;
736 }
737
738 static const struct file_operations kgn_smsg_fops = {
739         .owner          = THIS_MODULE,
740         .open           = kgnilnd_smsg_seq_open,
741         .read           = seq_read,
742         .llseek         = seq_lseek,
743         .release        = seq_release,
744 };
745
746 typedef struct {
747         __u64                   gconn_version;
748         struct list_head       *gconn_list;
749         kgn_conn_t             *gconn_conn;
750         loff_t                  gconn_off;
751         int                     gconn_hashidx;
752 } kgn_conn_seq_iter_t;
753
754 int
755 kgnilnd_conn_seq_seek(kgn_conn_seq_iter_t *gseq, loff_t off)
756 {
757         struct list_head       *list;
758         kgn_conn_t *conn;
759         loff_t                  here = 0;
760         int                     rc = 0;
761
762         if (off == 0) {
763                 gseq->gconn_hashidx = 0;
764                 gseq->gconn_list = NULL;
765         }
766
767         if (off > atomic_read(&kgnilnd_data.kgn_nconns)) {
768                 gseq->gconn_list = NULL;
769                 rc = -ENOENT;
770         }
771
772         read_lock(&kgnilnd_data.kgn_peer_conn_lock);
773         if (gseq->gconn_list != NULL &&
774                 gseq->gconn_version != kgnilnd_data.kgn_conn_version) {
775                 /* list changed */
776                 rc = -ESTALE;
777                 goto out;
778         }
779
780         if ((gseq->gconn_list == NULL) ||
781                 (gseq->gconn_off > off) ||
782                 (gseq->gconn_hashidx >= *kgnilnd_tunables.kgn_peer_hash_size)) {
783                 /* search from start */
784                 gseq->gconn_hashidx = 0;
785                 list = &kgnilnd_data.kgn_conns[gseq->gconn_hashidx];
786                 here = 0;
787         } else {
788                 /* continue current search */
789                 list = gseq->gconn_list;
790         }
791
792         gseq->gconn_version = kgnilnd_data.kgn_conn_version;
793         gseq->gconn_off = off;
794
795 start_list:
796
797         list_for_each_entry(conn, list, gnc_hashlist) {
798                 if (here == off) {
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         *pos = next;
865         if (rc != 0) {
866                 LIBCFS_FREE(gseq, sizeof(*gseq));
867                 return NULL;
868         }
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 %lld 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 const 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
1000         if (kgnilnd_debug_peer_nid == KGN_DEBUG_PEER_NID_DEFAULT) {
1001                 seq_printf(sf, "peer_conns not initialized\n");
1002                 return 0;
1003         }
1004
1005         /* sample date/time stamp - print time in UTC
1006          * 2012-12-11T16:06:16.966751 123@gni ...
1007          */
1008         getnstimeofday(&now);
1009         time64_to_tm(now.tv_sec, 0, &ctm);
1010         jifs = jiffies;
1011
1012         write_lock(&kgnilnd_data.kgn_peer_conn_lock);
1013         peer = kgnilnd_find_peer_locked(kgnilnd_debug_peer_nid);
1014
1015         if (peer == NULL) {
1016                 seq_printf(sf, "peer not found for this nid %d\n",
1017                              kgnilnd_debug_peer_nid);
1018                 write_unlock(&kgnilnd_data.kgn_peer_conn_lock);
1019                 return 0;
1020         }
1021
1022         list_for_each_entry(conn, &peer->gnp_conns, gnc_list) {
1023                 seq_printf(sf,
1024                            "%04ld-%02d-%02dT%02d:%02d:%02d.%06ld %s "
1025                            "mbox adr %p "
1026                            "dg type %s "
1027                            "%s "
1028                            "purg %d "
1029                            "close s/r %d/%d "
1030                            "err %d peer err %d "
1031                            "tx sq %u %dms/%dms "
1032                            "rx sq %u %dms/%dms/%dms "
1033                            "tx retran %lld\n",
1034                            ctm.tm_year+1900, ctm.tm_mon+1, ctm.tm_mday,
1035                            ctm.tm_hour, ctm.tm_min, ctm.tm_sec, now.tv_nsec,
1036                            libcfs_nid2str(peer->gnp_nid),
1037                            conn->remote_mbox_addr,
1038                            kgnilnd_conn_dgram_type2str(conn->gnc_dgram_type),
1039                            kgnilnd_conn_state2str(conn),
1040                            conn->gnc_in_purgatory,
1041                            conn->gnc_close_sent,
1042                            conn->gnc_close_recvd,
1043                            conn->gnc_error,
1044                            conn->gnc_peer_error,
1045                            atomic_read(&conn->gnc_tx_seq),
1046                            jiffies_to_msecs(jifs - conn->gnc_last_tx),
1047                            jiffies_to_msecs(jifs - conn->gnc_last_tx_cq),
1048                            atomic_read(&conn->gnc_rx_seq),
1049                            jiffies_to_msecs(jifs - conn->gnc_first_rx),
1050                            jiffies_to_msecs(jifs - conn->gnc_last_rx),
1051                            jiffies_to_msecs(jifs - conn->gnc_last_rx_cq),
1052                            conn->gnc_tx_retrans);
1053         }
1054
1055         write_unlock(&kgnilnd_data.kgn_peer_conn_lock);
1056         return 0;
1057 }
1058
1059 static int
1060 kgnilnd_peer_conns_seq_open(struct inode *inode, struct file *file)
1061 {
1062         return single_open(file, kgnilnd_proc_peer_conns_seq_show,
1063                            PDE_DATA(inode));
1064 }
1065
1066 static const struct file_operations kgn_peer_conns_fops = {
1067         .owner   = THIS_MODULE,
1068         .open    = kgnilnd_peer_conns_seq_open,
1069         .read    = seq_read,
1070         .write   = kgnilnd_proc_peer_conns_write,
1071         .llseek  = seq_lseek,
1072         .release = seq_release,
1073 };
1074
1075 static int
1076 kgnilnd_conn_seq_open(struct inode *inode, struct file *file)
1077 {
1078         struct seq_file       *sf;
1079         int                    rc;
1080
1081         rc = seq_open(file, &kgn_conn_sops);
1082         if (rc == 0) {
1083                 sf = file->private_data;
1084                 sf->private = PDE_DATA(inode);
1085         }
1086
1087         return rc;
1088 }
1089
1090 static const struct file_operations kgn_conn_fops = {
1091         .owner          = THIS_MODULE,
1092         .open           = kgnilnd_conn_seq_open,
1093         .read           = seq_read,
1094         .llseek         = seq_lseek,
1095         .release        = seq_release,
1096 };
1097
1098 typedef struct {
1099         __u64                   gpeer_version;
1100         struct list_head       *gpeer_list;
1101         kgn_peer_t             *gpeer_peer;
1102         loff_t                  gpeer_off;
1103         int                     gpeer_hashidx;
1104 } kgn_peer_seq_iter_t;
1105
1106 int
1107 kgnilnd_peer_seq_seek(kgn_peer_seq_iter_t *gseq, loff_t off)
1108 {
1109         struct list_head *list;
1110         kgn_peer_t *peer;
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_entry(peer, list, gnp_list) {
1150                 if (here == off) {
1151                         gseq->gpeer_peer = peer;
1152                         rc = 0;
1153                         goto out;
1154                 }
1155                 here++;
1156         }
1157         /* if we got through this hash bucket with 'off' still to go, try next*/
1158         gseq->gpeer_hashidx++;
1159         if ((here <= off) &&
1160                 (gseq->gpeer_hashidx < *kgnilnd_tunables.kgn_peer_hash_size)) {
1161                 list = &kgnilnd_data.kgn_peers[gseq->gpeer_hashidx];
1162                 goto start_list;
1163         }
1164
1165         gseq->gpeer_list = NULL;
1166         rc = -ENOENT;
1167 out:
1168         read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
1169         return rc;
1170 }
1171
1172 static void *
1173 kgnilnd_peer_seq_start(struct seq_file *s, loff_t *pos)
1174 {
1175
1176         kgn_peer_seq_iter_t     *gseq;
1177         int                      rc;
1178
1179         if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
1180                 return NULL;
1181         }
1182
1183         LIBCFS_ALLOC(gseq, sizeof(*gseq));
1184         if (gseq == NULL) {
1185                 CERROR("could not allocate peer sequence iterator\n");
1186                 return NULL;
1187         }
1188
1189         /* only doing device 0 for now */
1190         gseq->gpeer_list = NULL;
1191         rc = kgnilnd_peer_seq_seek(gseq, *pos);
1192         if (rc == 0)
1193                 return gseq;
1194
1195         LIBCFS_FREE(gseq, sizeof(*gseq));
1196         return NULL;
1197 }
1198
1199 static void
1200 kgnilnd_peer_seq_stop(struct seq_file *s, void *iter)
1201 {
1202         kgn_peer_seq_iter_t     *gseq = iter;
1203
1204         if (gseq != NULL)
1205                 LIBCFS_FREE(gseq, sizeof(*gseq));
1206 }
1207
1208 static void *
1209 kgnilnd_peer_seq_next(struct seq_file *s, void *iter, loff_t *pos)
1210 {
1211         kgn_peer_seq_iter_t    *gseq = iter;
1212         int                     rc;
1213         loff_t                  next = *pos + 1;
1214
1215         rc = kgnilnd_peer_seq_seek(gseq, next);
1216         *pos = next;
1217         if (rc != 0) {
1218                 LIBCFS_FREE(gseq, sizeof(*gseq));
1219                 return NULL;
1220         }
1221         return gseq;
1222 }
1223
1224 static int
1225 kgnilnd_peer_seq_show(struct seq_file *s, void *iter)
1226 {
1227         kgn_peer_seq_iter_t    *gseq = iter;
1228         kgn_peer_t             *peer;
1229         kgn_conn_t             *conn;
1230         char                   conn_str;
1231         int                    purg_count = 0;
1232         /* there is no header data for peers, so offset 0 is the first
1233          * real entry. */
1234
1235         peer = gseq->gpeer_peer;
1236         LASSERT(peer != NULL);
1237
1238         read_lock(&kgnilnd_data.kgn_peer_conn_lock);
1239         if (gseq->gpeer_list != NULL &&
1240                 gseq->gpeer_version != kgnilnd_data.kgn_peer_version) {
1241                 /* list changed */
1242                 read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
1243                 return -ESTALE;
1244         }
1245
1246         /* instead of saving off the data, just refcount */
1247         kgnilnd_peer_addref(peer);
1248         conn = kgnilnd_find_conn_locked(peer);
1249
1250         if (peer->gnp_connecting) {
1251                 conn_str = 'S';
1252         } else if (conn != NULL) {
1253                 conn_str = 'C';
1254         } else {
1255                 conn_str = 'D';
1256         }
1257
1258         list_for_each_entry(conn, &peer->gnp_conns, gnc_list) {
1259                 if (conn->gnc_in_purgatory) {
1260                         purg_count++;
1261                 }
1262         }
1263
1264         read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
1265
1266         seq_printf(s, "%p->%s [%d] %s NIC 0x%x q %d conn %c purg %d last %d@%lldms dgram %d@%dms reconn %dms to %lus \n",
1267                 peer, libcfs_nid2str(peer->gnp_nid),
1268                 atomic_read(&peer->gnp_refcount),
1269                 (peer->gnp_state == GNILND_PEER_DOWN) ? "down" :
1270                 peer->gnp_state == GNILND_PEER_TIMED_OUT ? "timedout" : "up",
1271                 peer->gnp_host_id,
1272                 kgnilnd_count_list(&peer->gnp_tx_queue),
1273                 conn_str,
1274                 purg_count,
1275                 peer->gnp_last_errno,
1276                 (ktime_get_seconds() - peer->gnp_last_alive) * MSEC_PER_SEC,
1277                 peer->gnp_last_dgram_errno,
1278                 jiffies_to_msecs(jiffies - peer->gnp_last_dgram_time),
1279                 peer->gnp_reconnect_interval != 0
1280                         ? jiffies_to_msecs(jiffies - peer->gnp_reconnect_time)
1281                         : 0,
1282                 peer->gnp_reconnect_interval);
1283
1284         kgnilnd_peer_decref(peer);
1285
1286         return 0;
1287 }
1288
1289 static const struct seq_operations kgn_peer_sops = {
1290         .start = kgnilnd_peer_seq_start,
1291         .stop  = kgnilnd_peer_seq_stop,
1292         .next  = kgnilnd_peer_seq_next,
1293         .show  = kgnilnd_peer_seq_show,
1294 };
1295
1296 static int
1297 kgnilnd_peer_seq_open(struct inode *inode, struct file *file)
1298 {
1299         struct seq_file       *sf;
1300         int                    rc;
1301
1302         rc = seq_open(file, &kgn_peer_sops);
1303         if (rc == 0) {
1304                 sf = file->private_data;
1305                 sf->private = PDE_DATA(inode);
1306         }
1307
1308         return rc;
1309 }
1310
1311 static const struct file_operations kgn_peer_fops = {
1312         .owner          = THIS_MODULE,
1313         .open           = kgnilnd_peer_seq_open,
1314         .read           = seq_read,
1315         .llseek         = seq_lseek,
1316         .release        = seq_release,
1317 };
1318
1319 static struct proc_dir_entry *kgn_proc_root;
1320
1321 void
1322 kgnilnd_proc_init(void)
1323 {
1324         struct proc_dir_entry *pde;
1325         int             rc = 0;
1326         ENTRY;
1327
1328         /* setup dir */
1329         kgn_proc_root = proc_mkdir(libcfs_lnd2modname(GNILND), NULL);
1330         if (kgn_proc_root == NULL) {
1331                 CERROR("couldn't create proc dir %s\n",
1332                         libcfs_lnd2modname(GNILND));
1333                 return;
1334         }
1335
1336         /* Initialize CKSUM_TEST */
1337         pde = proc_create(GNILND_PROC_CKSUM_TEST, 0200, kgn_proc_root,
1338                           &kgn_cksum_test_fops);
1339         if (pde == NULL) {
1340                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_CKSUM_TEST);
1341                 GOTO(remove_dir, rc = -ENOENT);
1342         }
1343
1344         /* Initialize STATS */
1345         pde = proc_create(GNILND_PROC_STATS, 0644, kgn_proc_root,
1346                           &kgn_stats_fops);
1347         if (pde == NULL) {
1348                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_STATS);
1349                 GOTO(remove_test, rc = -ENOENT);
1350         }
1351
1352         /* Initialize MDD */
1353         pde = proc_create(GNILND_PROC_MDD, 0444, kgn_proc_root, &kgn_mdd_fops);
1354         if (pde == NULL) {
1355                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_MDD);
1356                 GOTO(remove_stats, rc = -ENOENT);
1357         }
1358
1359         /* Initialize SMSG */
1360         pde = proc_create(GNILND_PROC_SMSG, 0444, kgn_proc_root,
1361                           &kgn_smsg_fops);
1362         if (pde == NULL) {
1363                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_SMSG);
1364                 GOTO(remove_mdd, rc = -ENOENT);
1365         }
1366
1367         /* Initialize CONN */
1368         pde = proc_create(GNILND_PROC_CONN, 0444, kgn_proc_root,
1369                           &kgn_conn_fops);
1370         if (pde == NULL) {
1371                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_CONN);
1372                 GOTO(remove_smsg, rc = -ENOENT);
1373         }
1374
1375         /* Initialize peer conns debug */
1376         pde = proc_create(GNILND_PROC_PEER_CONNS, 0644, kgn_proc_root,
1377                           &kgn_peer_conns_fops);
1378         if (pde == NULL) {
1379                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_PEER_CONNS);
1380                 GOTO(remove_conn, rc = -ENOENT);
1381         }
1382
1383         /* Initialize PEER */
1384         pde = proc_create(GNILND_PROC_PEER, 0444, kgn_proc_root,
1385                           &kgn_peer_fops);
1386         if (pde == NULL) {
1387                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_PEER);
1388                 GOTO(remove_pc, rc = -ENOENT);
1389         }
1390         RETURN_EXIT;
1391
1392 remove_pc:
1393         remove_proc_entry(GNILND_PROC_PEER_CONNS, kgn_proc_root);
1394 remove_conn:
1395         remove_proc_entry(GNILND_PROC_CONN, kgn_proc_root);
1396 remove_smsg:
1397         remove_proc_entry(GNILND_PROC_SMSG, kgn_proc_root);
1398 remove_mdd:
1399         remove_proc_entry(GNILND_PROC_MDD, kgn_proc_root);
1400 remove_stats:
1401         remove_proc_entry(GNILND_PROC_STATS, kgn_proc_root);
1402 remove_test:
1403         remove_proc_entry(GNILND_PROC_CKSUM_TEST, kgn_proc_root);
1404 remove_dir:
1405         remove_proc_entry(libcfs_lnd2modname(GNILND), NULL);
1406
1407         RETURN_EXIT;
1408 }
1409
1410 void
1411 kgnilnd_proc_fini(void)
1412 {
1413         remove_proc_entry(GNILND_PROC_PEER_CONNS, kgn_proc_root);
1414         remove_proc_entry(GNILND_PROC_PEER, kgn_proc_root);
1415         remove_proc_entry(GNILND_PROC_CONN, kgn_proc_root);
1416         remove_proc_entry(GNILND_PROC_MDD, kgn_proc_root);
1417         remove_proc_entry(GNILND_PROC_SMSG, kgn_proc_root);
1418         remove_proc_entry(GNILND_PROC_STATS, kgn_proc_root);
1419         remove_proc_entry(GNILND_PROC_CKSUM_TEST, kgn_proc_root);
1420         remove_proc_entry(libcfs_lnd2modname(GNILND), NULL);
1421 }