2 * Copyright (C) 2009-2012 Cray, Inc.
4 * Author: Nic Henke <nic@cray.com>
6 * This file is part of Lustre, http://www.lustre.org.
8 * Lustre is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU General Public
10 * License as published by the Free Software Foundation.
12 * Lustre is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Lustre; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 /* this code liberated and modified from lnet/lnet/router_proc.c */
24 #define DEBUG_SUBSYSTEM S_LND
26 #include <linux/seq_file.h>
28 #define GNILND_PROC_STATS "stats"
29 #define GNILND_PROC_MDD "mdd"
30 #define GNILND_PROC_SMSG "smsg"
31 #define GNILND_PROC_CONN "conn"
32 #define GNILND_PROC_PEER "peer"
33 #define GNILND_PROC_CKSUM_TEST "cksum_test"
36 _kgnilnd_proc_run_cksum_test(int caseno, int nloops, int nob)
38 lnet_kiov_t *src, *dest;
39 struct timespec begin, end, diff;
45 LIBCFS_ALLOC(src, LNET_MAX_IOV * sizeof(lnet_kiov_t));
46 LIBCFS_ALLOC(dest, LNET_MAX_IOV * sizeof(lnet_kiov_t));
48 if (src == NULL || dest == NULL) {
49 CERROR("couldn't allocate iovs\n");
50 GOTO(unwind, -ENOMEM);
53 for (i = 0; i < LNET_MAX_IOV; i++) {
54 src[i].kiov_offset = 0;
55 src[i].kiov_len = CFS_PAGE_SIZE;
56 src[i].kiov_page = cfs_alloc_page(CFS_ALLOC_STD|CFS_ALLOC_ZERO);
58 if (src[i].kiov_page == NULL) {
59 CERROR("couldn't allocate page %d\n", i);
60 GOTO(unwind, -ENOMEM);
63 dest[i].kiov_offset = 0;
64 dest[i].kiov_len = CFS_PAGE_SIZE;
65 dest[i].kiov_page = cfs_alloc_page(CFS_ALLOC_STD|CFS_ALLOC_ZERO);
67 if (dest[i].kiov_page == NULL) {
68 CERROR("couldn't allocate page %d\n", i);
69 GOTO(unwind, -ENOMEM);
73 /* add extra 2 pages - one for offset of src, 2nd to allow dest offset */
74 niov = (nob / PAGE_SIZE) + 2;
75 if (niov > LNET_MAX_IOV) {
76 CERROR("bytes %d too large, requires niov %d > %d\n",
77 nob, niov, LNET_MAX_IOV);
82 src[0].kiov_offset = 317;
83 dest[0].kiov_offset = 592;
90 dest[0].kiov_offset -= 1;
94 src[0].kiov_offset += 1;
98 src[0].kiov_offset += 1;
99 dest[0].kiov_offset -= 1;
101 src[0].kiov_len = PAGE_SIZE - src[0].kiov_offset;
102 dest[0].kiov_len = PAGE_SIZE - dest[0].kiov_offset;
104 for (i = 0; i < niov; i++) {
105 memset(page_address(src[i].kiov_page) + src[i].kiov_offset,
106 0xf0 + i, src[i].kiov_len);
109 lnet_copy_kiov2kiov(niov, dest, 0, niov, src, 0, nob);
111 getnstimeofday(&begin);
113 for (n = 0; n < nloops; n++) {
114 CDEBUG(D_BUFFS, "case %d loop %d src %d dest %d nob %d niov %d\n",
115 caseno, n, src[0].kiov_offset, dest[0].kiov_offset, nob, niov);
116 cksum = kgnilnd_cksum_kiov(niov, src, 0, nob - n, 1);
117 cksum2 = kgnilnd_cksum_kiov(niov, dest, 0, nob - n, 1);
119 if (cksum != cksum2) {
120 CERROR("case %d loop %d different checksums %x expected %x\n",
121 j, n, cksum2, cksum);
122 GOTO(unwind, -ENOKEY);
126 getnstimeofday(&end);
128 mbytes = (nloops * nob * 2) / (1024*1024);
130 diff = kgnilnd_ts_sub(end, begin);
132 LCONSOLE_INFO("running "LPD64"MB took %ld.%ld seconds\n",
133 mbytes, diff.tv_sec, diff.tv_nsec);
136 CDEBUG(D_NET, "freeing %d pages\n", i);
137 for (i -= 1; i >= 0; i--) {
138 if (src[i].kiov_page != NULL) {
139 cfs_free_page(src[i].kiov_page);
141 if (dest[i].kiov_page != NULL) {
142 cfs_free_page(dest[i].kiov_page);
147 LIBCFS_FREE(src, LNET_MAX_IOV * sizeof(lnet_kiov_t));
149 LIBCFS_FREE(dest, LNET_MAX_IOV * sizeof(lnet_kiov_t));
154 kgnilnd_proc_cksum_test_write(struct file *file, const char *ubuffer,
155 unsigned long count, void *data)
157 char dummy[256 + 1] = { '\0' };
158 int testno, nloops, nbytes;
161 if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
162 CERROR("can't run cksum test, kgnilnd is not initialized yet\n");
166 if (count >= sizeof(dummy) || count == 0)
169 if (copy_from_user(dummy, ubuffer, count))
172 if (sscanf(dummy, "%d:%d:%d", &testno, &nloops, &nbytes) == 3) {
173 rc = _kgnilnd_proc_run_cksum_test(testno, nloops, nbytes);
177 /* spurious, but lets us know the parse was ok */
185 kgnilnd_proc_stats_read(char *page, char **start, off_t off,
186 int count, int *eof, void *data)
192 if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
194 "kgnilnd is not initialized yet\n");
198 /* only do the first device */
199 dev = &kgnilnd_data.kgn_devices[0];
201 /* sampling is racy, but so is reading this file! */
203 do_gettimeofday(&now);
205 rc = sprintf(page, "time: %lu.%lu\n"
214 "GART map bytes: %ld\n"
215 "TX queued maps: %d\n"
216 "TX phys nmaps: %d\n"
217 "TX phys bytes: %lu\n"
218 "TX virt nmaps: %d\n"
219 "TX virt bytes: "LPU64"\n"
220 "RDMAQ bytes_auth: %ld\n"
221 "RDMAQ bytes_left: %ld\n"
222 "RDMAQ nstalls: %d\n"
223 "dev mutex delay: %ld\n"
225 "dev n_schedule: %d\n"
226 "SMSG fast_try: %d\n"
228 "SMSG fast_block: %d\n"
230 "SMSG tx_bytes: %ld\n"
232 "SMSG rx_bytes: %ld\n"
234 "RDMA tx_bytes: %ld\n"
236 "RDMA rx_bytes: %ld\n"
240 now.tv_sec, now.tv_usec,
241 atomic_read(&kgnilnd_data.kgn_ntx),
242 atomic_read(&kgnilnd_data.kgn_npeers),
243 atomic_read(&kgnilnd_data.kgn_nconns),
244 atomic_read(&dev->gnd_neps),
245 atomic_read(&dev->gnd_ndgrams),
246 atomic_read(&dev->gnd_nfmablk),
247 atomic_read(&dev->gnd_n_mdd), atomic_read(&dev->gnd_n_mdd_held),
248 atomic64_read(&dev->gnd_nbytes_map),
249 atomic_read(&dev->gnd_nq_map),
250 dev->gnd_map_nphys, dev->gnd_map_physnop * PAGE_SIZE,
251 dev->gnd_map_nvirt, dev->gnd_map_virtnob,
252 atomic64_read(&dev->gnd_rdmaq_bytes_out),
253 atomic64_read(&dev->gnd_rdmaq_bytes_ok),
254 atomic_read(&dev->gnd_rdmaq_nstalls),
255 dev->gnd_mutex_delay,
256 atomic_read(&dev->gnd_n_yield), atomic_read(&dev->gnd_n_schedule),
257 atomic_read(&dev->gnd_fast_try), atomic_read(&dev->gnd_fast_ok),
258 atomic_read(&dev->gnd_fast_block),
259 atomic_read(&dev->gnd_short_ntx), atomic64_read(&dev->gnd_short_txbytes),
260 atomic_read(&dev->gnd_short_nrx), atomic64_read(&dev->gnd_short_rxbytes),
261 atomic_read(&dev->gnd_rdma_ntx), atomic64_read(&dev->gnd_rdma_txbytes),
262 atomic_read(&dev->gnd_rdma_nrx), atomic64_read(&dev->gnd_rdma_rxbytes),
263 atomic_read(&kgnilnd_data.kgn_nvmap_short),
264 atomic_read(&kgnilnd_data.kgn_nvmap_cksum),
265 atomic_read(&kgnilnd_data.kgn_nkmap_short));
271 kgnilnd_proc_stats_write(struct file *file, const char *ubuffer,
272 unsigned long count, void *data)
276 if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
277 CERROR("kgnilnd is not initialized for stats write\n");
281 /* only do the first device */
282 dev = &kgnilnd_data.kgn_devices[0];
284 atomic_set(&dev->gnd_short_ntx, 0);
285 atomic_set(&dev->gnd_short_nrx, 0);
286 atomic64_set(&dev->gnd_short_txbytes, 0);
287 atomic64_set(&dev->gnd_short_rxbytes, 0);
288 atomic_set(&dev->gnd_rdma_ntx, 0);
289 atomic_set(&dev->gnd_rdma_nrx, 0);
290 atomic_set(&dev->gnd_fast_ok, 0);
291 atomic_set(&dev->gnd_fast_try, 0);
292 atomic_set(&dev->gnd_fast_block, 0);
293 atomic64_set(&dev->gnd_rdma_txbytes, 0);
294 atomic64_set(&dev->gnd_rdma_rxbytes, 0);
295 atomic_set(&dev->gnd_rdmaq_nstalls, 0);
296 set_mb(dev->gnd_mutex_delay, 0);
297 atomic_set(&dev->gnd_n_yield, 0);
298 atomic_set(&dev->gnd_n_schedule, 0);
299 atomic_set(&kgnilnd_data.kgn_nvmap_short, 0);
300 atomic_set(&kgnilnd_data.kgn_nvmap_cksum, 0);
301 atomic_set(&kgnilnd_data.kgn_nkmap_short, 0);
302 /* sampling is racy, but so is writing this file! */
308 kgn_device_t *gmdd_dev;
311 } kgn_mdd_seq_iter_t;
314 kgnilnd_mdd_seq_seek(kgn_mdd_seq_iter_t *gseq, loff_t off)
322 gseq->gmdd_tx = NULL;
329 if (tx == NULL || gseq->gmdd_off > off) {
330 /* search from start */
331 r = gseq->gmdd_dev->gnd_map_list.next;
334 /* continue current search */
335 r = &tx->tx_map_list;
336 here = gseq->gmdd_off;
339 gseq->gmdd_off = off;
341 while (r != &gseq->gmdd_dev->gnd_map_list) {
344 t = list_entry(r, kgn_tx_t, tx_map_list);
355 gseq->gmdd_tx = NULL;
362 kgnilnd_mdd_seq_start(struct seq_file *s, loff_t *pos)
365 kgn_mdd_seq_iter_t *gseq;
368 if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
372 LIBCFS_ALLOC(gseq, sizeof(*gseq));
374 CERROR("could not allocate mdd sequence iterator\n");
378 /* only doing device 0 for now */
379 gseq->gmdd_dev = &kgnilnd_data.kgn_devices[0];
380 gseq->gmdd_tx = NULL;
382 /* need to lock map while we poke - huge disturbance
383 * but without it, no way to get the data printed */
384 spin_lock(&gseq->gmdd_dev->gnd_map_lock);
386 /* set private to gseq for stop */
389 rc = kgnilnd_mdd_seq_seek(gseq, *pos);
397 kgnilnd_mdd_seq_stop(struct seq_file *s, void *iter)
399 kgn_mdd_seq_iter_t *gseq = s->private;
402 spin_unlock(&gseq->gmdd_dev->gnd_map_lock);
403 LIBCFS_FREE(gseq, sizeof(*gseq));
408 kgnilnd_mdd_seq_next(struct seq_file *s, void *iter, loff_t *pos)
410 kgn_mdd_seq_iter_t *gseq = iter;
412 loff_t next = *pos + 1;
414 rc = kgnilnd_mdd_seq_seek(gseq, next);
423 kgnilnd_mdd_seq_show(struct seq_file *s, void *iter)
425 kgn_mdd_seq_iter_t *gseq = iter;
431 gni_mem_handle_t hndl;
433 if (gseq->gmdd_off == 0) {
434 seq_printf(s, "%s %22s %16s %8s %8s %37s\n",
435 "tx", "tx_id", "nob", "physnop",
436 "buftype", "mem handle");
443 id = tx->tx_id.txe_smsg_id;
445 physnop = tx->tx_phys_npages;
446 buftype = tx->tx_buftype;
447 hndl.qword1 = tx->tx_map_key.qword1;
448 hndl.qword2 = tx->tx_map_key.qword2;
450 seq_printf(s, "%p %x %16"LPF64"u %8d %#8x "LPX64"."LPX64"x\n",
451 tx, id, nob, physnop, buftype,
452 hndl.qword1, hndl.qword2);
457 static struct seq_operations kgn_mdd_sops = {
458 .start = kgnilnd_mdd_seq_start,
459 .stop = kgnilnd_mdd_seq_stop,
460 .next = kgnilnd_mdd_seq_next,
461 .show = kgnilnd_mdd_seq_show,
466 kgnilnd_mdd_seq_open(struct inode *inode, struct file *file)
471 rc = seq_open(file, &kgn_mdd_sops);
473 sf = file->private_data;
475 /* NULL means we've not yet open() */
481 static struct file_operations kgn_mdd_fops = {
482 .owner = THIS_MODULE,
483 .open = kgnilnd_mdd_seq_open,
486 .release = seq_release,
491 kgn_device_t *gsmsg_dev;
492 kgn_fma_memblock_t *gsmsg_fmablk;
494 } kgn_smsg_seq_iter_t;
497 kgnilnd_smsg_seq_seek(kgn_smsg_seq_iter_t *gseq, loff_t off)
499 kgn_fma_memblock_t *fmablk;
505 /* offset 0 is the header, so we start real entries at
506 * here == off == 1 */
508 gseq->gsmsg_fmablk = NULL;
513 fmablk = gseq->gsmsg_fmablk;
514 dev = gseq->gsmsg_dev;
516 spin_lock(&dev->gnd_fmablk_lock);
518 if (fmablk != NULL &&
519 gseq->gsmsg_version != atomic_read(&dev->gnd_fmablk_vers)) {
525 if (fmablk == NULL || gseq->gsmsg_off > off) {
526 /* search from start */
527 r = dev->gnd_fma_buffs.next;
530 /* continue current search */
531 r = &fmablk->gnm_bufflist;
532 here = gseq->gsmsg_off;
535 gseq->gsmsg_version = atomic_read(&dev->gnd_fmablk_vers);
536 gseq->gsmsg_off = off;
538 while (r != &dev->gnd_fma_buffs) {
539 kgn_fma_memblock_t *t;
541 t = list_entry(r, kgn_fma_memblock_t, gnm_bufflist);
544 gseq->gsmsg_fmablk = t;
552 gseq->gsmsg_fmablk = NULL;
555 spin_unlock(&dev->gnd_fmablk_lock);
560 kgnilnd_smsg_seq_start(struct seq_file *s, loff_t *pos)
563 kgn_smsg_seq_iter_t *gseq;
566 if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
570 LIBCFS_ALLOC(gseq, sizeof(*gseq));
572 CERROR("could not allocate smsg sequence iterator\n");
576 /* only doing device 0 for now */
577 gseq->gsmsg_dev = &kgnilnd_data.kgn_devices[0];
578 gseq->gsmsg_fmablk = NULL;
579 rc = kgnilnd_smsg_seq_seek(gseq, *pos);
583 LIBCFS_FREE(gseq, sizeof(*gseq));
588 kgnilnd_smsg_seq_stop(struct seq_file *s, void *iter)
590 kgn_smsg_seq_iter_t *gseq = iter;
593 LIBCFS_FREE(gseq, sizeof(*gseq));
597 kgnilnd_smsg_seq_next(struct seq_file *s, void *iter, loff_t *pos)
599 kgn_smsg_seq_iter_t *gseq = iter;
601 loff_t next = *pos + 1;
603 rc = kgnilnd_smsg_seq_seek(gseq, next);
605 LIBCFS_FREE(gseq, sizeof(*gseq));
613 kgnilnd_smsg_seq_show(struct seq_file *s, void *iter)
615 kgn_smsg_seq_iter_t *gseq = iter;
616 kgn_fma_memblock_t *fmablk;
618 int avail_mboxs, held_mboxs, num_mboxs;
619 unsigned int blk_size;
621 kgn_fmablk_state_t state;
622 gni_mem_handle_t hndl;
624 if (gseq->gsmsg_off == 0) {
625 seq_printf(s, "%5s %4s %6s/%5s/%5s %9s %18s %37s\n",
626 "blk#", "type", "avail", "held", "total", "size",
627 "fmablk", "mem handle");
631 fmablk = gseq->gsmsg_fmablk;
632 dev = gseq->gsmsg_dev;
633 LASSERT(fmablk != NULL);
635 spin_lock(&dev->gnd_fmablk_lock);
637 if (gseq->gsmsg_version != atomic_read(&dev->gnd_fmablk_vers)) {
639 spin_unlock(&dev->gnd_fmablk_lock);
643 live = fmablk->gnm_hold_timeout == 0;
644 /* none are available if it isn't live... */
645 avail_mboxs = live ? fmablk->gnm_avail_mboxs : 0;
646 held_mboxs = fmablk->gnm_held_mboxs;
647 num_mboxs = fmablk->gnm_num_mboxs;
648 blk_size = fmablk->gnm_blk_size;
649 state = fmablk->gnm_state;
650 hndl.qword1 = fmablk->gnm_hndl.qword1;
651 hndl.qword2 = fmablk->gnm_hndl.qword2;
653 spin_unlock(&dev->gnd_fmablk_lock);
656 seq_printf(s, "%5d %4s %6d/%5d/%5d %9d %18p "LPX64"."LPX64"\n",
657 (int) gseq->gsmsg_off, kgnilnd_fmablk_state2str(state),
658 avail_mboxs, held_mboxs, num_mboxs, blk_size,
659 fmablk, hndl.qword1, hndl.qword2);
661 seq_printf(s, "%5d %4s %6d/%5d/%5d %9d %18p %37s\n",
662 (int) gseq->gsmsg_off, kgnilnd_fmablk_state2str(state),
663 avail_mboxs, held_mboxs, num_mboxs, blk_size,
664 fmablk, "PURGATORY.HOLD");
670 static struct seq_operations kgn_smsg_sops = {
671 .start = kgnilnd_smsg_seq_start,
672 .stop = kgnilnd_smsg_seq_stop,
673 .next = kgnilnd_smsg_seq_next,
674 .show = kgnilnd_smsg_seq_show,
679 kgnilnd_smsg_seq_open(struct inode *inode, struct file *file)
681 struct proc_dir_entry *dp = PDE(inode);
685 rc = seq_open(file, &kgn_smsg_sops);
687 sf = file->private_data;
688 sf->private = dp->data;
694 static struct file_operations kgn_smsg_fops = {
695 .owner = THIS_MODULE,
696 .open = kgnilnd_smsg_seq_open,
699 .release = seq_release,
704 struct list_head *gconn_list;
705 kgn_conn_t *gconn_conn;
708 } kgn_conn_seq_iter_t;
711 kgnilnd_conn_seq_seek(kgn_conn_seq_iter_t *gseq, loff_t off)
713 struct list_head *list, *tmp;
718 gseq->gconn_hashidx = 0;
719 gseq->gconn_list = NULL;
722 if (off > atomic_read(&kgnilnd_data.kgn_nconns)) {
723 gseq->gconn_list = NULL;
727 read_lock(&kgnilnd_data.kgn_peer_conn_lock);
728 if (gseq->gconn_list != NULL &&
729 gseq->gconn_version != kgnilnd_data.kgn_conn_version) {
735 if ((gseq->gconn_list == NULL) ||
736 (gseq->gconn_off > off) ||
737 (gseq->gconn_hashidx >= *kgnilnd_tunables.kgn_peer_hash_size)) {
738 /* search from start */
739 gseq->gconn_hashidx = 0;
740 list = &kgnilnd_data.kgn_conns[gseq->gconn_hashidx];
743 /* continue current search */
744 list = gseq->gconn_list;
747 gseq->gconn_version = kgnilnd_data.kgn_conn_version;
748 gseq->gconn_off = off;
752 list_for_each(tmp, list) {
755 conn = list_entry(tmp, kgn_conn_t, gnc_hashlist);
756 gseq->gconn_conn = conn;
762 /* if we got through this hash bucket with 'off' still to go, try next*/
763 gseq->gconn_hashidx++;
765 (gseq->gconn_hashidx < *kgnilnd_tunables.kgn_peer_hash_size)) {
766 list = &kgnilnd_data.kgn_conns[gseq->gconn_hashidx];
770 gseq->gconn_list = NULL;
773 read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
778 kgnilnd_conn_seq_start(struct seq_file *s, loff_t *pos)
781 kgn_conn_seq_iter_t *gseq;
784 if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
788 LIBCFS_ALLOC(gseq, sizeof(*gseq));
790 CERROR("could not allocate conn sequence iterator\n");
794 /* only doing device 0 for now */
795 gseq->gconn_list = NULL;
796 rc = kgnilnd_conn_seq_seek(gseq, *pos);
800 LIBCFS_FREE(gseq, sizeof(*gseq));
805 kgnilnd_conn_seq_stop(struct seq_file *s, void *iter)
807 kgn_conn_seq_iter_t *gseq = iter;
810 LIBCFS_FREE(gseq, sizeof(*gseq));
814 kgnilnd_conn_seq_next(struct seq_file *s, void *iter, loff_t *pos)
816 kgn_conn_seq_iter_t *gseq = iter;
818 loff_t next = *pos + 1;
820 rc = kgnilnd_conn_seq_seek(gseq, next);
822 LIBCFS_FREE(gseq, sizeof(*gseq));
830 kgnilnd_conn_seq_show(struct seq_file *s, void *iter)
832 kgn_conn_seq_iter_t *gseq = iter;
833 kgn_peer_t *peer = NULL;
836 /* there is no header data for conns, so offset 0 is the first
839 conn = gseq->gconn_conn;
840 LASSERT(conn != NULL);
842 read_lock(&kgnilnd_data.kgn_peer_conn_lock);
843 if (gseq->gconn_list != NULL &&
844 gseq->gconn_version != kgnilnd_data.kgn_conn_version) {
846 read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
850 /* instead of saving off the data, just refcount */
851 kgnilnd_conn_addref(conn);
852 if (conn->gnc_peer) {
853 /* don't use link - after unlock it could get nuked */
854 peer = conn->gnc_peer;
855 kgnilnd_peer_addref(peer);
858 read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
860 seq_printf(s, "%p->%s [%d] q %d/%d/%d "
861 "tx sq %u %dms/%dms "
862 "rx sq %u %dms/%dms "
863 "noop r/s %d/%d w/s/cq %lds/%lds/%lds "
864 "sched a/d %lds/%lds "
865 "tx_re "LPD64" TO %ds %s\n",
866 conn, peer ? libcfs_nid2str(peer->gnp_nid) : "<?>",
867 atomic_read(&conn->gnc_refcount),
868 kgnilnd_count_list(&conn->gnc_fmaq),
869 atomic_read(&conn->gnc_nlive_fma),
870 atomic_read(&conn->gnc_nlive_rdma),
872 jiffies_to_msecs(jiffies - conn->gnc_last_tx),
873 jiffies_to_msecs(jiffies - conn->gnc_last_tx_cq),
875 jiffies_to_msecs(jiffies - conn->gnc_last_rx),
876 jiffies_to_msecs(jiffies - conn->gnc_last_rx_cq),
877 atomic_read(&conn->gnc_reaper_noop),
878 atomic_read(&conn->gnc_sched_noop),
879 cfs_duration_sec(jiffies - conn->gnc_last_noop_want),
880 cfs_duration_sec(jiffies - conn->gnc_last_noop_sent),
881 cfs_duration_sec(jiffies - conn->gnc_last_noop_cq),
882 cfs_duration_sec(jiffies - conn->gnc_last_sched_ask),
883 cfs_duration_sec(jiffies - conn->gnc_last_sched_do),
884 conn->gnc_tx_retrans, conn->gnc_timeout,
885 kgnilnd_conn_state2str(conn));
888 kgnilnd_peer_decref(peer);
889 kgnilnd_conn_decref(conn);
894 static struct seq_operations kgn_conn_sops = {
895 .start = kgnilnd_conn_seq_start,
896 .stop = kgnilnd_conn_seq_stop,
897 .next = kgnilnd_conn_seq_next,
898 .show = kgnilnd_conn_seq_show,
903 kgnilnd_conn_seq_open(struct inode *inode, struct file *file)
905 struct proc_dir_entry *dp = PDE(inode);
909 rc = seq_open(file, &kgn_conn_sops);
911 sf = file->private_data;
912 sf->private = dp->data;
918 static struct file_operations kgn_conn_fops = {
919 .owner = THIS_MODULE,
920 .open = kgnilnd_conn_seq_open,
923 .release = seq_release,
928 struct list_head *gpeer_list;
929 kgn_peer_t *gpeer_peer;
932 } kgn_peer_seq_iter_t;
935 kgnilnd_peer_seq_seek(kgn_peer_seq_iter_t *gseq, loff_t off)
937 struct list_head *list, *tmp;
942 gseq->gpeer_hashidx = 0;
943 gseq->gpeer_list = NULL;
946 if (off > atomic_read(&kgnilnd_data.kgn_npeers)) {
947 gseq->gpeer_list = NULL;
951 read_lock(&kgnilnd_data.kgn_peer_conn_lock);
952 if (gseq->gpeer_list != NULL &&
953 gseq->gpeer_version != kgnilnd_data.kgn_peer_version) {
959 if ((gseq->gpeer_list == NULL) ||
960 (gseq->gpeer_off > off) ||
961 (gseq->gpeer_hashidx >= *kgnilnd_tunables.kgn_peer_hash_size)) {
962 /* search from start */
963 gseq->gpeer_hashidx = 0;
964 list = &kgnilnd_data.kgn_peers[gseq->gpeer_hashidx];
967 /* continue current search */
968 list = gseq->gpeer_list;
971 gseq->gpeer_version = kgnilnd_data.kgn_peer_version;
972 gseq->gpeer_off = off;
976 list_for_each(tmp, list) {
979 peer = list_entry(tmp, kgn_peer_t, gnp_list);
980 gseq->gpeer_peer = peer;
986 /* if we got through this hash bucket with 'off' still to go, try next*/
987 gseq->gpeer_hashidx++;
989 (gseq->gpeer_hashidx < *kgnilnd_tunables.kgn_peer_hash_size)) {
990 list = &kgnilnd_data.kgn_peers[gseq->gpeer_hashidx];
994 gseq->gpeer_list = NULL;
997 read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
1002 kgnilnd_peer_seq_start(struct seq_file *s, loff_t *pos)
1005 kgn_peer_seq_iter_t *gseq;
1008 if (kgnilnd_data.kgn_init < GNILND_INIT_ALL) {
1012 LIBCFS_ALLOC(gseq, sizeof(*gseq));
1014 CERROR("could not allocate peer sequence iterator\n");
1018 /* only doing device 0 for now */
1019 gseq->gpeer_list = NULL;
1020 rc = kgnilnd_peer_seq_seek(gseq, *pos);
1024 LIBCFS_FREE(gseq, sizeof(*gseq));
1029 kgnilnd_peer_seq_stop(struct seq_file *s, void *iter)
1031 kgn_peer_seq_iter_t *gseq = iter;
1034 LIBCFS_FREE(gseq, sizeof(*gseq));
1038 kgnilnd_peer_seq_next(struct seq_file *s, void *iter, loff_t *pos)
1040 kgn_peer_seq_iter_t *gseq = iter;
1042 loff_t next = *pos + 1;
1044 rc = kgnilnd_peer_seq_seek(gseq, next);
1046 LIBCFS_FREE(gseq, sizeof(*gseq));
1054 kgnilnd_peer_seq_show(struct seq_file *s, void *iter)
1056 kgn_peer_seq_iter_t *gseq = iter;
1061 /* there is no header data for peers, so offset 0 is the first
1064 peer = gseq->gpeer_peer;
1065 LASSERT(peer != NULL);
1067 read_lock(&kgnilnd_data.kgn_peer_conn_lock);
1068 if (gseq->gpeer_list != NULL &&
1069 gseq->gpeer_version != kgnilnd_data.kgn_peer_version) {
1071 read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
1075 /* instead of saving off the data, just refcount */
1076 kgnilnd_peer_addref(peer);
1077 conn = kgnilnd_find_conn_locked(peer);
1079 if (peer->gnp_connecting) {
1081 } else if (conn != NULL) {
1087 list_for_each_entry(conn, &peer->gnp_conns, gnc_list) {
1088 if (conn->gnc_in_purgatory) {
1093 read_unlock(&kgnilnd_data.kgn_peer_conn_lock);
1095 seq_printf(s, "%p->%s [%d] NIC 0x%x q %d conn %c purg %d "
1096 "last %d@%dms dgram %d@%dms "
1097 "reconn %dms to %lus \n",
1098 peer, libcfs_nid2str(peer->gnp_nid),
1099 atomic_read(&peer->gnp_refcount),
1101 kgnilnd_count_list(&peer->gnp_tx_queue),
1104 peer->gnp_last_errno,
1105 jiffies_to_msecs(jiffies - peer->gnp_last_alive),
1106 peer->gnp_last_dgram_errno,
1107 jiffies_to_msecs(jiffies - peer->gnp_last_dgram_time),
1108 peer->gnp_reconnect_interval != 0
1109 ? jiffies_to_msecs(jiffies - peer->gnp_reconnect_time)
1111 peer->gnp_reconnect_interval);
1113 kgnilnd_peer_decref(peer);
1118 static struct seq_operations kgn_peer_sops = {
1119 .start = kgnilnd_peer_seq_start,
1120 .stop = kgnilnd_peer_seq_stop,
1121 .next = kgnilnd_peer_seq_next,
1122 .show = kgnilnd_peer_seq_show,
1126 kgnilnd_peer_seq_open(struct inode *inode, struct file *file)
1128 struct proc_dir_entry *dp = PDE(inode);
1129 struct seq_file *sf;
1132 rc = seq_open(file, &kgn_peer_sops);
1134 sf = file->private_data;
1135 sf->private = dp->data;
1141 static struct file_operations kgn_peer_fops = {
1142 .owner = THIS_MODULE,
1143 .open = kgnilnd_peer_seq_open,
1145 .llseek = seq_lseek,
1146 .release = seq_release,
1149 static struct proc_dir_entry *kgn_proc_root;
1152 kgnilnd_proc_init(void)
1154 struct proc_dir_entry *pde;
1159 kgn_proc_root = proc_mkdir(libcfs_lnd2modname(GNILND), NULL);
1160 if (kgn_proc_root == NULL) {
1161 CERROR("couldn't create proc dir %s\n",
1162 libcfs_lnd2modname(GNILND));
1166 /* Initialize CKSUM_TEST */
1167 pde = create_proc_entry(GNILND_PROC_CKSUM_TEST, 0200, kgn_proc_root);
1169 CERROR("couldn't create proc entry %s\n", GNILND_PROC_CKSUM_TEST);
1171 GOTO(remove_dir, rc);
1175 pde->write_proc = kgnilnd_proc_cksum_test_write;
1177 /* Initialize STATS */
1178 pde = create_proc_entry(GNILND_PROC_STATS, 0644, kgn_proc_root);
1180 CERROR("couldn't create proc entry %s\n", GNILND_PROC_STATS);
1182 GOTO(remove_test, rc);
1186 pde->read_proc = kgnilnd_proc_stats_read;
1187 pde->write_proc = kgnilnd_proc_stats_write;
1189 /* Initialize MDD */
1190 pde = create_proc_entry(GNILND_PROC_MDD, 0444, kgn_proc_root);
1192 CERROR("couldn't create proc entry %s\n", GNILND_PROC_MDD);
1194 GOTO(remove_stats, rc);
1198 pde->proc_fops = &kgn_mdd_fops;
1200 /* Initialize SMSG */
1201 pde = create_proc_entry(GNILND_PROC_SMSG, 0444, kgn_proc_root);
1203 CERROR("couldn't create proc entry %s\n", GNILND_PROC_SMSG);
1205 GOTO(remove_mdd, rc);
1209 pde->proc_fops = &kgn_smsg_fops;
1211 /* Initialize CONN */
1212 pde = create_proc_entry(GNILND_PROC_CONN, 0444, kgn_proc_root);
1214 CERROR("couldn't create proc entry %s\n", GNILND_PROC_CONN);
1216 GOTO(remove_smsg, rc);
1220 pde->proc_fops = &kgn_conn_fops;
1222 /* Initialize PEER */
1223 pde = create_proc_entry(GNILND_PROC_PEER, 0444, kgn_proc_root);
1225 CERROR("couldn't create proc entry %s\n", GNILND_PROC_PEER);
1227 GOTO(remove_conn, rc);
1231 pde->proc_fops = &kgn_peer_fops;
1235 remove_proc_entry(GNILND_PROC_CONN, kgn_proc_root);
1237 remove_proc_entry(GNILND_PROC_SMSG, kgn_proc_root);
1239 remove_proc_entry(GNILND_PROC_MDD, kgn_proc_root);
1241 remove_proc_entry(GNILND_PROC_STATS, kgn_proc_root);
1243 remove_proc_entry(GNILND_PROC_CKSUM_TEST, kgn_proc_root);
1245 remove_proc_entry(kgn_proc_root->name, NULL);
1251 kgnilnd_proc_fini(void)
1253 remove_proc_entry(GNILND_PROC_PEER, kgn_proc_root);
1254 remove_proc_entry(GNILND_PROC_CONN, kgn_proc_root);
1255 remove_proc_entry(GNILND_PROC_MDD, kgn_proc_root);
1256 remove_proc_entry(GNILND_PROC_SMSG, kgn_proc_root);
1257 remove_proc_entry(GNILND_PROC_STATS, kgn_proc_root);
1258 remove_proc_entry(GNILND_PROC_CKSUM_TEST, kgn_proc_root);
1259 remove_proc_entry(kgn_proc_root->name, NULL);