Whamcloud - gitweb
LU-6142 lustre: change all 'struct seq_operations' to const
[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, *tmp;
758         loff_t                  here = 0;
759         int                     rc = 0;
760
761         if (off == 0) {
762                 gseq->gconn_hashidx = 0;
763                 gseq->gconn_list = NULL;
764         }
765
766         if (off > atomic_read(&kgnilnd_data.kgn_nconns)) {
767                 gseq->gconn_list = NULL;
768                 rc = -ENOENT;
769         }
770
771         read_lock(&kgnilnd_data.kgn_peer_conn_lock);
772         if (gseq->gconn_list != NULL &&
773                 gseq->gconn_version != kgnilnd_data.kgn_conn_version) {
774                 /* list changed */
775                 rc = -ESTALE;
776                 goto out;
777         }
778
779         if ((gseq->gconn_list == NULL) ||
780                 (gseq->gconn_off > off) ||
781                 (gseq->gconn_hashidx >= *kgnilnd_tunables.kgn_peer_hash_size)) {
782                 /* search from start */
783                 gseq->gconn_hashidx = 0;
784                 list = &kgnilnd_data.kgn_conns[gseq->gconn_hashidx];
785                 here = 0;
786         } else {
787                 /* continue current search */
788                 list = gseq->gconn_list;
789         }
790
791         gseq->gconn_version = kgnilnd_data.kgn_conn_version;
792         gseq->gconn_off = off;
793
794 start_list:
795
796         list_for_each(tmp, list) {
797                 if (here == off) {
798                         kgn_conn_t *conn;
799                         conn = list_entry(tmp, kgn_conn_t, gnc_hashlist);
800                         gseq->gconn_conn = conn;
801                         rc = 0;
802                         goto out;
803                 }
804                 here++;
805         }
806         /* if we got through this hash bucket with 'off' still to go, try next*/
807         gseq->gconn_hashidx++;
808         if ((here <= off) &&
809                 (gseq->gconn_hashidx < *kgnilnd_tunables.kgn_peer_hash_size)) {
810                 list = &kgnilnd_data.kgn_conns[gseq->gconn_hashidx];
811                 goto start_list;
812         }
813
814         gseq->gconn_list = NULL;
815         rc = -ENOENT;
816 out:
817         read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
818         return rc;
819 }
820
821 static void *
822 kgnilnd_conn_seq_start(struct seq_file *s, loff_t *pos)
823 {
824
825         kgn_conn_seq_iter_t     *gseq;
826         int                      rc;
827
828         if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
829                 return NULL;
830         }
831
832         LIBCFS_ALLOC(gseq, sizeof(*gseq));
833         if (gseq == NULL) {
834                 CERROR("could not allocate conn sequence iterator\n");
835                 return NULL;
836         }
837
838         /* only doing device 0 for now */
839         gseq->gconn_list = NULL;
840         rc = kgnilnd_conn_seq_seek(gseq, *pos);
841         if (rc == 0)
842                 return gseq;
843
844         LIBCFS_FREE(gseq, sizeof(*gseq));
845         return NULL;
846 }
847
848 static void
849 kgnilnd_conn_seq_stop(struct seq_file *s, void *iter)
850 {
851         kgn_conn_seq_iter_t     *gseq = iter;
852
853         if (gseq != NULL)
854                 LIBCFS_FREE(gseq, sizeof(*gseq));
855 }
856
857 static void *
858 kgnilnd_conn_seq_next(struct seq_file *s, void *iter, loff_t *pos)
859 {
860         kgn_conn_seq_iter_t    *gseq = iter;
861         int                     rc;
862         loff_t                  next = *pos + 1;
863
864         rc = kgnilnd_conn_seq_seek(gseq, next);
865         *pos = next;
866         if (rc != 0) {
867                 LIBCFS_FREE(gseq, sizeof(*gseq));
868                 return NULL;
869         }
870         return gseq;
871 }
872
873 static int
874 kgnilnd_conn_seq_show(struct seq_file *s, void *iter)
875 {
876         kgn_conn_seq_iter_t    *gseq = iter;
877         kgn_peer_t             *peer = NULL;
878         kgn_conn_t             *conn;
879
880         /* there is no header data for conns, so offset 0 is the first
881          * real entry. */
882
883         conn = gseq->gconn_conn;
884         LASSERT(conn != NULL);
885
886         read_lock(&kgnilnd_data.kgn_peer_conn_lock);
887         if (gseq->gconn_list != NULL &&
888                 gseq->gconn_version != kgnilnd_data.kgn_conn_version) {
889                 /* list changed */
890                 read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
891                 return -ESTALE;
892         }
893
894         /* instead of saving off the data, just refcount */
895         kgnilnd_conn_addref(conn);
896         if (conn->gnc_peer) {
897                 /* don't use link - after unlock it could get nuked */
898                 peer = conn->gnc_peer;
899                 kgnilnd_peer_addref(peer);
900         }
901
902         read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
903
904         seq_printf(s, "%p->%s [%d] q %d/%d/%d "
905                 "tx sq %u %dms/%dms "
906                 "rx sq %u %dms/%dms "
907                 "noop r/s %d/%d w/s/cq %lds/%lds/%lds "
908                 "sched a/d %lds/%lds "
909                 "tx_re %lld TO %ds %s\n",
910                 conn, peer ? libcfs_nid2str(peer->gnp_nid) : "<?>",
911                 atomic_read(&conn->gnc_refcount),
912                 kgnilnd_count_list(&conn->gnc_fmaq),
913                 atomic_read(&conn->gnc_nlive_fma),
914                 atomic_read(&conn->gnc_nlive_rdma),
915                 atomic_read(&conn->gnc_tx_seq),
916                 jiffies_to_msecs(jiffies - conn->gnc_last_tx),
917                 jiffies_to_msecs(jiffies - conn->gnc_last_tx_cq),
918                 atomic_read(&conn->gnc_rx_seq),
919                 jiffies_to_msecs(jiffies - conn->gnc_last_rx),
920                 jiffies_to_msecs(jiffies - conn->gnc_last_rx_cq),
921                 atomic_read(&conn->gnc_reaper_noop),
922                 atomic_read(&conn->gnc_sched_noop),
923                 cfs_duration_sec(jiffies - conn->gnc_last_noop_want),
924                 cfs_duration_sec(jiffies - conn->gnc_last_noop_sent),
925                 cfs_duration_sec(jiffies - conn->gnc_last_noop_cq),
926                 cfs_duration_sec(jiffies - conn->gnc_last_sched_ask),
927                 cfs_duration_sec(jiffies - conn->gnc_last_sched_do),
928                 conn->gnc_tx_retrans, conn->gnc_timeout,
929                 kgnilnd_conn_state2str(conn));
930
931         if (peer)
932                 kgnilnd_peer_decref(peer);
933         kgnilnd_conn_decref(conn);
934
935         return 0;
936 }
937
938 static const struct seq_operations kgn_conn_sops = {
939         .start = kgnilnd_conn_seq_start,
940         .stop  = kgnilnd_conn_seq_stop,
941         .next  = kgnilnd_conn_seq_next,
942         .show  = kgnilnd_conn_seq_show,
943
944 };
945
946 #define KGN_DEBUG_PEER_NID_DEFAULT -1
947 static int kgnilnd_debug_peer_nid = KGN_DEBUG_PEER_NID_DEFAULT;
948
949 static ssize_t
950 kgnilnd_proc_peer_conns_write(struct file *file, const char __user *ubuffer,
951                               size_t count, loff_t *ppos)
952 {
953         char dummy[8];
954         int  rc;
955
956         if (count >= sizeof(dummy) || count == 0)
957                 return -EINVAL;
958
959         if (copy_from_user(dummy, ubuffer, count))
960                 return -EFAULT;
961
962         rc = sscanf(dummy, "%d", &kgnilnd_debug_peer_nid);
963
964         if (rc != 1) {
965                 return -EINVAL;
966         }
967
968         RETURN(count);
969 }
970
971 /* debug data to print from conns associated with peer nid
972   -  date/time
973   -  peer nid
974   -  mbox_addr (msg_buffer + mbox_offset)
975   -  gnc_dgram_type
976   -  gnc_in_purgatory
977   -  gnc_state
978   -  gnc_error
979   -  gnc_peer_error
980   -  gnc_tx_seq
981   -  gnc_last_tx
982   -  gnc_last_tx_cq
983   -  gnc_rx_seq
984   -  gnc_first_rx
985   -  gnc_last_rx
986   -  gnc_last_rx_cq
987   -  gnc_tx_retrans
988   -  gnc_close_sent
989   -  gnc_close_recvd
990 */
991
992 static int
993 kgnilnd_proc_peer_conns_seq_show(struct seq_file *sf, void *v)
994 {
995         kgn_peer_t      *peer;
996         kgn_conn_t      *conn;
997         struct tm       ctm;
998         struct timespec now;
999         unsigned long   jifs;
1000
1001         if (kgnilnd_debug_peer_nid == KGN_DEBUG_PEER_NID_DEFAULT) {
1002                 seq_printf(sf, "peer_conns not initialized\n");
1003                 return 0;
1004         }
1005
1006         /* sample date/time stamp - print time in UTC
1007          * 2012-12-11T16:06:16.966751 123@gni ...
1008          */
1009         getnstimeofday(&now);
1010         time64_to_tm(now.tv_sec, 0, &ctm);
1011         jifs = jiffies;
1012
1013         write_lock(&kgnilnd_data.kgn_peer_conn_lock);
1014         peer = kgnilnd_find_peer_locked(kgnilnd_debug_peer_nid);
1015
1016         if (peer == NULL) {
1017                 seq_printf(sf, "peer not found for this nid %d\n",
1018                              kgnilnd_debug_peer_nid);
1019                 write_unlock(&kgnilnd_data.kgn_peer_conn_lock);
1020                 return 0;
1021         }
1022
1023         list_for_each_entry(conn, &peer->gnp_conns, gnc_list) {
1024                 seq_printf(sf,
1025                            "%04ld-%02d-%02dT%02d:%02d:%02d.%06ld %s "
1026                            "mbox adr %p "
1027                            "dg type %s "
1028                            "%s "
1029                            "purg %d "
1030                            "close s/r %d/%d "
1031                            "err %d peer err %d "
1032                            "tx sq %u %dms/%dms "
1033                            "rx sq %u %dms/%dms/%dms "
1034                            "tx retran %lld\n",
1035                            ctm.tm_year+1900, ctm.tm_mon+1, ctm.tm_mday,
1036                            ctm.tm_hour, ctm.tm_min, ctm.tm_sec, now.tv_nsec,
1037                            libcfs_nid2str(peer->gnp_nid),
1038                            conn->remote_mbox_addr,
1039                            kgnilnd_conn_dgram_type2str(conn->gnc_dgram_type),
1040                            kgnilnd_conn_state2str(conn),
1041                            conn->gnc_in_purgatory,
1042                            conn->gnc_close_sent,
1043                            conn->gnc_close_recvd,
1044                            conn->gnc_error,
1045                            conn->gnc_peer_error,
1046                            atomic_read(&conn->gnc_tx_seq),
1047                            jiffies_to_msecs(jifs - conn->gnc_last_tx),
1048                            jiffies_to_msecs(jifs - conn->gnc_last_tx_cq),
1049                            atomic_read(&conn->gnc_rx_seq),
1050                            jiffies_to_msecs(jifs - conn->gnc_first_rx),
1051                            jiffies_to_msecs(jifs - conn->gnc_last_rx),
1052                            jiffies_to_msecs(jifs - conn->gnc_last_rx_cq),
1053                            conn->gnc_tx_retrans);
1054         }
1055
1056         write_unlock(&kgnilnd_data.kgn_peer_conn_lock);
1057         return 0;
1058 }
1059
1060 static int
1061 kgnilnd_peer_conns_seq_open(struct inode *inode, struct file *file)
1062 {
1063         return single_open(file, kgnilnd_proc_peer_conns_seq_show,
1064                            PDE_DATA(inode));
1065 }
1066
1067 static const struct file_operations kgn_peer_conns_fops = {
1068         .owner   = THIS_MODULE,
1069         .open    = kgnilnd_peer_conns_seq_open,
1070         .read    = seq_read,
1071         .write   = kgnilnd_proc_peer_conns_write,
1072         .llseek  = seq_lseek,
1073         .release = seq_release,
1074 };
1075
1076 static int
1077 kgnilnd_conn_seq_open(struct inode *inode, struct file *file)
1078 {
1079         struct seq_file       *sf;
1080         int                    rc;
1081
1082         rc = seq_open(file, &kgn_conn_sops);
1083         if (rc == 0) {
1084                 sf = file->private_data;
1085                 sf->private = PDE_DATA(inode);
1086         }
1087
1088         return rc;
1089 }
1090
1091 static const struct file_operations kgn_conn_fops = {
1092         .owner          = THIS_MODULE,
1093         .open           = kgnilnd_conn_seq_open,
1094         .read           = seq_read,
1095         .llseek         = seq_lseek,
1096         .release        = seq_release,
1097 };
1098
1099 typedef struct {
1100         __u64                   gpeer_version;
1101         struct list_head       *gpeer_list;
1102         kgn_peer_t             *gpeer_peer;
1103         loff_t                  gpeer_off;
1104         int                     gpeer_hashidx;
1105 } kgn_peer_seq_iter_t;
1106
1107 int
1108 kgnilnd_peer_seq_seek(kgn_peer_seq_iter_t *gseq, loff_t off)
1109 {
1110         struct list_head       *list, *tmp;
1111         loff_t                  here = 0;
1112         int                     rc = 0;
1113
1114         if (off == 0) {
1115                 gseq->gpeer_hashidx = 0;
1116                 gseq->gpeer_list = NULL;
1117         }
1118
1119         if (off > atomic_read(&kgnilnd_data.kgn_npeers)) {
1120                 gseq->gpeer_list = NULL;
1121                 rc = -ENOENT;
1122         }
1123
1124         read_lock(&kgnilnd_data.kgn_peer_conn_lock);
1125         if (gseq->gpeer_list != NULL &&
1126                 gseq->gpeer_version != kgnilnd_data.kgn_peer_version) {
1127                 /* list changed */
1128                 rc = -ESTALE;
1129                 goto out;
1130         }
1131
1132         if ((gseq->gpeer_list == NULL) ||
1133                 (gseq->gpeer_off > off) ||
1134                 (gseq->gpeer_hashidx >= *kgnilnd_tunables.kgn_peer_hash_size)) {
1135                 /* search from start */
1136                 gseq->gpeer_hashidx = 0;
1137                 list = &kgnilnd_data.kgn_peers[gseq->gpeer_hashidx];
1138                 here = 0;
1139         } else {
1140                 /* continue current search */
1141                 list = gseq->gpeer_list;
1142         }
1143
1144         gseq->gpeer_version = kgnilnd_data.kgn_peer_version;
1145         gseq->gpeer_off = off;
1146
1147 start_list:
1148
1149         list_for_each(tmp, list) {
1150                 if (here == off) {
1151                         kgn_peer_t *peer;
1152                         peer = list_entry(tmp, kgn_peer_t, gnp_list);
1153                         gseq->gpeer_peer = peer;
1154                         rc = 0;
1155                         goto out;
1156                 }
1157                 here++;
1158         }
1159         /* if we got through this hash bucket with 'off' still to go, try next*/
1160         gseq->gpeer_hashidx++;
1161         if ((here <= off) &&
1162                 (gseq->gpeer_hashidx < *kgnilnd_tunables.kgn_peer_hash_size)) {
1163                 list = &kgnilnd_data.kgn_peers[gseq->gpeer_hashidx];
1164                 goto start_list;
1165         }
1166
1167         gseq->gpeer_list = NULL;
1168         rc = -ENOENT;
1169 out:
1170         read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
1171         return rc;
1172 }
1173
1174 static void *
1175 kgnilnd_peer_seq_start(struct seq_file *s, loff_t *pos)
1176 {
1177
1178         kgn_peer_seq_iter_t     *gseq;
1179         int                      rc;
1180
1181         if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
1182                 return NULL;
1183         }
1184
1185         LIBCFS_ALLOC(gseq, sizeof(*gseq));
1186         if (gseq == NULL) {
1187                 CERROR("could not allocate peer sequence iterator\n");
1188                 return NULL;
1189         }
1190
1191         /* only doing device 0 for now */
1192         gseq->gpeer_list = NULL;
1193         rc = kgnilnd_peer_seq_seek(gseq, *pos);
1194         if (rc == 0)
1195                 return gseq;
1196
1197         LIBCFS_FREE(gseq, sizeof(*gseq));
1198         return NULL;
1199 }
1200
1201 static void
1202 kgnilnd_peer_seq_stop(struct seq_file *s, void *iter)
1203 {
1204         kgn_peer_seq_iter_t     *gseq = iter;
1205
1206         if (gseq != NULL)
1207                 LIBCFS_FREE(gseq, sizeof(*gseq));
1208 }
1209
1210 static void *
1211 kgnilnd_peer_seq_next(struct seq_file *s, void *iter, loff_t *pos)
1212 {
1213         kgn_peer_seq_iter_t    *gseq = iter;
1214         int                     rc;
1215         loff_t                  next = *pos + 1;
1216
1217         rc = kgnilnd_peer_seq_seek(gseq, next);
1218         *pos = next;
1219         if (rc != 0) {
1220                 LIBCFS_FREE(gseq, sizeof(*gseq));
1221                 return NULL;
1222         }
1223         return gseq;
1224 }
1225
1226 static int
1227 kgnilnd_peer_seq_show(struct seq_file *s, void *iter)
1228 {
1229         kgn_peer_seq_iter_t    *gseq = iter;
1230         kgn_peer_t             *peer;
1231         kgn_conn_t             *conn;
1232         char                   conn_str;
1233         int                    purg_count = 0;
1234         /* there is no header data for peers, so offset 0 is the first
1235          * real entry. */
1236
1237         peer = gseq->gpeer_peer;
1238         LASSERT(peer != NULL);
1239
1240         read_lock(&kgnilnd_data.kgn_peer_conn_lock);
1241         if (gseq->gpeer_list != NULL &&
1242                 gseq->gpeer_version != kgnilnd_data.kgn_peer_version) {
1243                 /* list changed */
1244                 read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
1245                 return -ESTALE;
1246         }
1247
1248         /* instead of saving off the data, just refcount */
1249         kgnilnd_peer_addref(peer);
1250         conn = kgnilnd_find_conn_locked(peer);
1251
1252         if (peer->gnp_connecting) {
1253                 conn_str = 'S';
1254         } else if (conn != NULL) {
1255                 conn_str = 'C';
1256         } else {
1257                 conn_str = 'D';
1258         }
1259
1260         list_for_each_entry(conn, &peer->gnp_conns, gnc_list) {
1261                 if (conn->gnc_in_purgatory) {
1262                         purg_count++;
1263                 }
1264         }
1265
1266         read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
1267
1268         seq_printf(s, "%p->%s [%d] %s NIC 0x%x q %d conn %c purg %d last %d@%lldms dgram %d@%dms reconn %dms to %lus \n",
1269                 peer, libcfs_nid2str(peer->gnp_nid),
1270                 atomic_read(&peer->gnp_refcount),
1271                 (peer->gnp_state == GNILND_PEER_DOWN) ? "down" :
1272                 peer->gnp_state == GNILND_PEER_TIMED_OUT ? "timedout" : "up",
1273                 peer->gnp_host_id,
1274                 kgnilnd_count_list(&peer->gnp_tx_queue),
1275                 conn_str,
1276                 purg_count,
1277                 peer->gnp_last_errno,
1278                 (ktime_get_seconds() - peer->gnp_last_alive) * MSEC_PER_SEC,
1279                 peer->gnp_last_dgram_errno,
1280                 jiffies_to_msecs(jiffies - peer->gnp_last_dgram_time),
1281                 peer->gnp_reconnect_interval != 0
1282                         ? jiffies_to_msecs(jiffies - peer->gnp_reconnect_time)
1283                         : 0,
1284                 peer->gnp_reconnect_interval);
1285
1286         kgnilnd_peer_decref(peer);
1287
1288         return 0;
1289 }
1290
1291 static const struct seq_operations kgn_peer_sops = {
1292         .start = kgnilnd_peer_seq_start,
1293         .stop  = kgnilnd_peer_seq_stop,
1294         .next  = kgnilnd_peer_seq_next,
1295         .show  = kgnilnd_peer_seq_show,
1296 };
1297
1298 static int
1299 kgnilnd_peer_seq_open(struct inode *inode, struct file *file)
1300 {
1301         struct seq_file       *sf;
1302         int                    rc;
1303
1304         rc = seq_open(file, &kgn_peer_sops);
1305         if (rc == 0) {
1306                 sf = file->private_data;
1307                 sf->private = PDE_DATA(inode);
1308         }
1309
1310         return rc;
1311 }
1312
1313 static const struct file_operations kgn_peer_fops = {
1314         .owner          = THIS_MODULE,
1315         .open           = kgnilnd_peer_seq_open,
1316         .read           = seq_read,
1317         .llseek         = seq_lseek,
1318         .release        = seq_release,
1319 };
1320
1321 static struct proc_dir_entry *kgn_proc_root;
1322
1323 void
1324 kgnilnd_proc_init(void)
1325 {
1326         struct proc_dir_entry *pde;
1327         int             rc = 0;
1328         ENTRY;
1329
1330         /* setup dir */
1331         kgn_proc_root = proc_mkdir(libcfs_lnd2modname(GNILND), NULL);
1332         if (kgn_proc_root == NULL) {
1333                 CERROR("couldn't create proc dir %s\n",
1334                         libcfs_lnd2modname(GNILND));
1335                 return;
1336         }
1337
1338         /* Initialize CKSUM_TEST */
1339         pde = proc_create(GNILND_PROC_CKSUM_TEST, 0200, kgn_proc_root,
1340                           &kgn_cksum_test_fops);
1341         if (pde == NULL) {
1342                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_CKSUM_TEST);
1343                 GOTO(remove_dir, rc = -ENOENT);
1344         }
1345
1346         /* Initialize STATS */
1347         pde = proc_create(GNILND_PROC_STATS, 0644, kgn_proc_root,
1348                           &kgn_stats_fops);
1349         if (pde == NULL) {
1350                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_STATS);
1351                 GOTO(remove_test, rc = -ENOENT);
1352         }
1353
1354         /* Initialize MDD */
1355         pde = proc_create(GNILND_PROC_MDD, 0444, kgn_proc_root, &kgn_mdd_fops);
1356         if (pde == NULL) {
1357                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_MDD);
1358                 GOTO(remove_stats, rc = -ENOENT);
1359         }
1360
1361         /* Initialize SMSG */
1362         pde = proc_create(GNILND_PROC_SMSG, 0444, kgn_proc_root,
1363                           &kgn_smsg_fops);
1364         if (pde == NULL) {
1365                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_SMSG);
1366                 GOTO(remove_mdd, rc = -ENOENT);
1367         }
1368
1369         /* Initialize CONN */
1370         pde = proc_create(GNILND_PROC_CONN, 0444, kgn_proc_root,
1371                           &kgn_conn_fops);
1372         if (pde == NULL) {
1373                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_CONN);
1374                 GOTO(remove_smsg, rc = -ENOENT);
1375         }
1376
1377         /* Initialize peer conns debug */
1378         pde = proc_create(GNILND_PROC_PEER_CONNS, 0644, kgn_proc_root,
1379                           &kgn_peer_conns_fops);
1380         if (pde == NULL) {
1381                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_PEER_CONNS);
1382                 GOTO(remove_conn, rc = -ENOENT);
1383         }
1384
1385         /* Initialize PEER */
1386         pde = proc_create(GNILND_PROC_PEER, 0444, kgn_proc_root,
1387                           &kgn_peer_fops);
1388         if (pde == NULL) {
1389                 CERROR("couldn't create proc entry %s\n", GNILND_PROC_PEER);
1390                 GOTO(remove_pc, rc = -ENOENT);
1391         }
1392         RETURN_EXIT;
1393
1394 remove_pc:
1395         remove_proc_entry(GNILND_PROC_PEER_CONNS, kgn_proc_root);
1396 remove_conn:
1397         remove_proc_entry(GNILND_PROC_CONN, kgn_proc_root);
1398 remove_smsg:
1399         remove_proc_entry(GNILND_PROC_SMSG, kgn_proc_root);
1400 remove_mdd:
1401         remove_proc_entry(GNILND_PROC_MDD, kgn_proc_root);
1402 remove_stats:
1403         remove_proc_entry(GNILND_PROC_STATS, kgn_proc_root);
1404 remove_test:
1405         remove_proc_entry(GNILND_PROC_CKSUM_TEST, kgn_proc_root);
1406 remove_dir:
1407         remove_proc_entry(libcfs_lnd2modname(GNILND), NULL);
1408
1409         RETURN_EXIT;
1410 }
1411
1412 void
1413 kgnilnd_proc_fini(void)
1414 {
1415         remove_proc_entry(GNILND_PROC_PEER_CONNS, kgn_proc_root);
1416         remove_proc_entry(GNILND_PROC_PEER, kgn_proc_root);
1417         remove_proc_entry(GNILND_PROC_CONN, kgn_proc_root);
1418         remove_proc_entry(GNILND_PROC_MDD, kgn_proc_root);
1419         remove_proc_entry(GNILND_PROC_SMSG, kgn_proc_root);
1420         remove_proc_entry(GNILND_PROC_STATS, kgn_proc_root);
1421         remove_proc_entry(GNILND_PROC_CKSUM_TEST, kgn_proc_root);
1422         remove_proc_entry(libcfs_lnd2modname(GNILND), NULL);
1423 }