xref: /linux/fs/ocfs2/cluster/netdebug.c (revision a1c613ae4c322ddd58d5a8539dbfba2a0380a8c0)
1328970deSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2fa60ce2cSMasahiro Yamada /*
32309e9e0SSunil Mushran  * netdebug.c
42309e9e0SSunil Mushran  *
52309e9e0SSunil Mushran  * debug functionality for o2net
62309e9e0SSunil Mushran  *
72309e9e0SSunil Mushran  * Copyright (C) 2005, 2008 Oracle.  All rights reserved.
82309e9e0SSunil Mushran  */
92309e9e0SSunil Mushran 
102309e9e0SSunil Mushran #ifdef CONFIG_DEBUG_FS
112309e9e0SSunil Mushran 
122309e9e0SSunil Mushran #include <linux/module.h>
132309e9e0SSunil Mushran #include <linux/types.h>
142309e9e0SSunil Mushran #include <linux/slab.h>
152309e9e0SSunil Mushran #include <linux/idr.h>
162309e9e0SSunil Mushran #include <linux/kref.h>
172309e9e0SSunil Mushran #include <linux/seq_file.h>
182309e9e0SSunil Mushran #include <linux/debugfs.h>
192309e9e0SSunil Mushran 
202309e9e0SSunil Mushran #include <linux/uaccess.h>
212309e9e0SSunil Mushran 
222309e9e0SSunil Mushran #include "tcp.h"
232309e9e0SSunil Mushran #include "nodemanager.h"
242309e9e0SSunil Mushran #define MLOG_MASK_PREFIX ML_TCP
252309e9e0SSunil Mushran #include "masklog.h"
262309e9e0SSunil Mushran 
272309e9e0SSunil Mushran #include "tcp_internal.h"
282309e9e0SSunil Mushran 
292309e9e0SSunil Mushran #define O2NET_DEBUG_DIR		"o2net"
302309e9e0SSunil Mushran #define SC_DEBUG_NAME		"sock_containers"
312309e9e0SSunil Mushran #define NST_DEBUG_NAME		"send_tracking"
32db02754cSSunil Mushran #define STATS_DEBUG_NAME	"stats"
333ba169ccSSunil Mushran #define NODES_DEBUG_NAME	"connected_nodes"
34db02754cSSunil Mushran 
35db02754cSSunil Mushran #define SHOW_SOCK_CONTAINERS	0
36db02754cSSunil Mushran #define SHOW_SOCK_STATS		1
372309e9e0SSunil Mushran 
382309e9e0SSunil Mushran static struct dentry *o2net_dentry;
392309e9e0SSunil Mushran 
402309e9e0SSunil Mushran static DEFINE_SPINLOCK(o2net_debug_lock);
412309e9e0SSunil Mushran 
422309e9e0SSunil Mushran static LIST_HEAD(sock_containers);
432309e9e0SSunil Mushran static LIST_HEAD(send_tracking);
442309e9e0SSunil Mushran 
o2net_debug_add_nst(struct o2net_send_tracking * nst)452309e9e0SSunil Mushran void o2net_debug_add_nst(struct o2net_send_tracking *nst)
462309e9e0SSunil Mushran {
47*84c10951SChengfeng Ye 	spin_lock_bh(&o2net_debug_lock);
482309e9e0SSunil Mushran 	list_add(&nst->st_net_debug_item, &send_tracking);
49*84c10951SChengfeng Ye 	spin_unlock_bh(&o2net_debug_lock);
502309e9e0SSunil Mushran }
512309e9e0SSunil Mushran 
o2net_debug_del_nst(struct o2net_send_tracking * nst)522309e9e0SSunil Mushran void o2net_debug_del_nst(struct o2net_send_tracking *nst)
532309e9e0SSunil Mushran {
54*84c10951SChengfeng Ye 	spin_lock_bh(&o2net_debug_lock);
552309e9e0SSunil Mushran 	if (!list_empty(&nst->st_net_debug_item))
562309e9e0SSunil Mushran 		list_del_init(&nst->st_net_debug_item);
57*84c10951SChengfeng Ye 	spin_unlock_bh(&o2net_debug_lock);
582309e9e0SSunil Mushran }
592309e9e0SSunil Mushran 
602309e9e0SSunil Mushran static struct o2net_send_tracking
next_nst(struct o2net_send_tracking * nst_start)612309e9e0SSunil Mushran 			*next_nst(struct o2net_send_tracking *nst_start)
622309e9e0SSunil Mushran {
632309e9e0SSunil Mushran 	struct o2net_send_tracking *nst, *ret = NULL;
642309e9e0SSunil Mushran 
652309e9e0SSunil Mushran 	assert_spin_locked(&o2net_debug_lock);
662309e9e0SSunil Mushran 
672309e9e0SSunil Mushran 	list_for_each_entry(nst, &nst_start->st_net_debug_item,
682309e9e0SSunil Mushran 			    st_net_debug_item) {
692309e9e0SSunil Mushran 		/* discover the head of the list */
702309e9e0SSunil Mushran 		if (&nst->st_net_debug_item == &send_tracking)
712309e9e0SSunil Mushran 			break;
722309e9e0SSunil Mushran 
732309e9e0SSunil Mushran 		/* use st_task to detect real nsts in the list */
742309e9e0SSunil Mushran 		if (nst->st_task != NULL) {
752309e9e0SSunil Mushran 			ret = nst;
762309e9e0SSunil Mushran 			break;
772309e9e0SSunil Mushran 		}
782309e9e0SSunil Mushran 	}
792309e9e0SSunil Mushran 
802309e9e0SSunil Mushran 	return ret;
812309e9e0SSunil Mushran }
822309e9e0SSunil Mushran 
nst_seq_start(struct seq_file * seq,loff_t * pos)832309e9e0SSunil Mushran static void *nst_seq_start(struct seq_file *seq, loff_t *pos)
842309e9e0SSunil Mushran {
852309e9e0SSunil Mushran 	struct o2net_send_tracking *nst, *dummy_nst = seq->private;
862309e9e0SSunil Mushran 
87*84c10951SChengfeng Ye 	spin_lock_bh(&o2net_debug_lock);
882309e9e0SSunil Mushran 	nst = next_nst(dummy_nst);
89*84c10951SChengfeng Ye 	spin_unlock_bh(&o2net_debug_lock);
902309e9e0SSunil Mushran 
912309e9e0SSunil Mushran 	return nst;
922309e9e0SSunil Mushran }
932309e9e0SSunil Mushran 
nst_seq_next(struct seq_file * seq,void * v,loff_t * pos)942309e9e0SSunil Mushran static void *nst_seq_next(struct seq_file *seq, void *v, loff_t *pos)
952309e9e0SSunil Mushran {
962309e9e0SSunil Mushran 	struct o2net_send_tracking *nst, *dummy_nst = seq->private;
972309e9e0SSunil Mushran 
98*84c10951SChengfeng Ye 	spin_lock_bh(&o2net_debug_lock);
992309e9e0SSunil Mushran 	nst = next_nst(dummy_nst);
1002309e9e0SSunil Mushran 	list_del_init(&dummy_nst->st_net_debug_item);
1012309e9e0SSunil Mushran 	if (nst)
1022309e9e0SSunil Mushran 		list_add(&dummy_nst->st_net_debug_item,
1032309e9e0SSunil Mushran 			 &nst->st_net_debug_item);
104*84c10951SChengfeng Ye 	spin_unlock_bh(&o2net_debug_lock);
1052309e9e0SSunil Mushran 
1062309e9e0SSunil Mushran 	return nst; /* unused, just needs to be null when done */
1072309e9e0SSunil Mushran }
1082309e9e0SSunil Mushran 
nst_seq_show(struct seq_file * seq,void * v)1092309e9e0SSunil Mushran static int nst_seq_show(struct seq_file *seq, void *v)
1102309e9e0SSunil Mushran {
1112309e9e0SSunil Mushran 	struct o2net_send_tracking *nst, *dummy_nst = seq->private;
1123f9c14faSSunil Mushran 	ktime_t now;
1133f9c14faSSunil Mushran 	s64 sock, send, status;
1142309e9e0SSunil Mushran 
115*84c10951SChengfeng Ye 	spin_lock_bh(&o2net_debug_lock);
1162309e9e0SSunil Mushran 	nst = next_nst(dummy_nst);
117cc548166SDan Carpenter 	if (!nst)
118cc548166SDan Carpenter 		goto out;
1192309e9e0SSunil Mushran 
1203f9c14faSSunil Mushran 	now = ktime_get();
1213f9c14faSSunil Mushran 	sock = ktime_to_us(ktime_sub(now, nst->st_sock_time));
1223f9c14faSSunil Mushran 	send = ktime_to_us(ktime_sub(now, nst->st_send_time));
1233f9c14faSSunil Mushran 	status = ktime_to_us(ktime_sub(now, nst->st_status_time));
1243f9c14faSSunil Mushran 
1252309e9e0SSunil Mushran 	/* get_task_comm isn't exported.  oh well. */
1262309e9e0SSunil Mushran 	seq_printf(seq, "%p:\n"
1272309e9e0SSunil Mushran 		   "  pid:          %lu\n"
1282309e9e0SSunil Mushran 		   "  tgid:         %lu\n"
1292309e9e0SSunil Mushran 		   "  process name: %s\n"
1302309e9e0SSunil Mushran 		   "  node:         %u\n"
1312309e9e0SSunil Mushran 		   "  sc:           %p\n"
1322309e9e0SSunil Mushran 		   "  message id:   %d\n"
1332309e9e0SSunil Mushran 		   "  message type: %u\n"
1342309e9e0SSunil Mushran 		   "  message key:  0x%08x\n"
1353f9c14faSSunil Mushran 		   "  sock acquiry: %lld usecs ago\n"
1363f9c14faSSunil Mushran 		   "  send start:   %lld usecs ago\n"
1373f9c14faSSunil Mushran 		   "  wait start:   %lld usecs ago\n",
13837096a79SSunil Mushran 		   nst, (unsigned long)task_pid_nr(nst->st_task),
1392309e9e0SSunil Mushran 		   (unsigned long)nst->st_task->tgid,
1402309e9e0SSunil Mushran 		   nst->st_task->comm, nst->st_node,
1412309e9e0SSunil Mushran 		   nst->st_sc, nst->st_id, nst->st_msg_type,
1422309e9e0SSunil Mushran 		   nst->st_msg_key,
1433f9c14faSSunil Mushran 		   (long long)sock,
1443f9c14faSSunil Mushran 		   (long long)send,
1453f9c14faSSunil Mushran 		   (long long)status);
1462309e9e0SSunil Mushran 
147cc548166SDan Carpenter out:
148*84c10951SChengfeng Ye 	spin_unlock_bh(&o2net_debug_lock);
1492309e9e0SSunil Mushran 
1502309e9e0SSunil Mushran 	return 0;
1512309e9e0SSunil Mushran }
1522309e9e0SSunil Mushran 
nst_seq_stop(struct seq_file * seq,void * v)1532309e9e0SSunil Mushran static void nst_seq_stop(struct seq_file *seq, void *v)
1542309e9e0SSunil Mushran {
1552309e9e0SSunil Mushran }
1562309e9e0SSunil Mushran 
15788e9d34cSJames Morris static const struct seq_operations nst_seq_ops = {
1582309e9e0SSunil Mushran 	.start = nst_seq_start,
1592309e9e0SSunil Mushran 	.next = nst_seq_next,
1602309e9e0SSunil Mushran 	.stop = nst_seq_stop,
1612309e9e0SSunil Mushran 	.show = nst_seq_show,
1622309e9e0SSunil Mushran };
1632309e9e0SSunil Mushran 
nst_fop_open(struct inode * inode,struct file * file)1642309e9e0SSunil Mushran static int nst_fop_open(struct inode *inode, struct file *file)
1652309e9e0SSunil Mushran {
1662309e9e0SSunil Mushran 	struct o2net_send_tracking *dummy_nst;
1672309e9e0SSunil Mushran 
168f3288338SRob Jones 	dummy_nst = __seq_open_private(file, &nst_seq_ops, sizeof(*dummy_nst));
169f3288338SRob Jones 	if (!dummy_nst)
170f3288338SRob Jones 		return -ENOMEM;
1712309e9e0SSunil Mushran 	o2net_debug_add_nst(dummy_nst);
1722309e9e0SSunil Mushran 
173f3288338SRob Jones 	return 0;
1742309e9e0SSunil Mushran }
1752309e9e0SSunil Mushran 
nst_fop_release(struct inode * inode,struct file * file)1762309e9e0SSunil Mushran static int nst_fop_release(struct inode *inode, struct file *file)
1772309e9e0SSunil Mushran {
1782309e9e0SSunil Mushran 	struct seq_file *seq = file->private_data;
1792309e9e0SSunil Mushran 	struct o2net_send_tracking *dummy_nst = seq->private;
1802309e9e0SSunil Mushran 
1812309e9e0SSunil Mushran 	o2net_debug_del_nst(dummy_nst);
1822309e9e0SSunil Mushran 	return seq_release_private(inode, file);
1832309e9e0SSunil Mushran }
1842309e9e0SSunil Mushran 
185828c0950SAlexey Dobriyan static const struct file_operations nst_seq_fops = {
1862309e9e0SSunil Mushran 	.open = nst_fop_open,
1872309e9e0SSunil Mushran 	.read = seq_read,
1882309e9e0SSunil Mushran 	.llseek = seq_lseek,
1892309e9e0SSunil Mushran 	.release = nst_fop_release,
1902309e9e0SSunil Mushran };
1912309e9e0SSunil Mushran 
o2net_debug_add_sc(struct o2net_sock_container * sc)1922309e9e0SSunil Mushran void o2net_debug_add_sc(struct o2net_sock_container *sc)
1932309e9e0SSunil Mushran {
194*84c10951SChengfeng Ye 	spin_lock_bh(&o2net_debug_lock);
1952309e9e0SSunil Mushran 	list_add(&sc->sc_net_debug_item, &sock_containers);
196*84c10951SChengfeng Ye 	spin_unlock_bh(&o2net_debug_lock);
1972309e9e0SSunil Mushran }
1982309e9e0SSunil Mushran 
o2net_debug_del_sc(struct o2net_sock_container * sc)1992309e9e0SSunil Mushran void o2net_debug_del_sc(struct o2net_sock_container *sc)
2002309e9e0SSunil Mushran {
201*84c10951SChengfeng Ye 	spin_lock_bh(&o2net_debug_lock);
2022309e9e0SSunil Mushran 	list_del_init(&sc->sc_net_debug_item);
203*84c10951SChengfeng Ye 	spin_unlock_bh(&o2net_debug_lock);
2042309e9e0SSunil Mushran }
2052309e9e0SSunil Mushran 
206db02754cSSunil Mushran struct o2net_sock_debug {
207db02754cSSunil Mushran 	int dbg_ctxt;
208db02754cSSunil Mushran 	struct o2net_sock_container *dbg_sock;
209db02754cSSunil Mushran };
210db02754cSSunil Mushran 
2112309e9e0SSunil Mushran static struct o2net_sock_container
next_sc(struct o2net_sock_container * sc_start)2122309e9e0SSunil Mushran 			*next_sc(struct o2net_sock_container *sc_start)
2132309e9e0SSunil Mushran {
2142309e9e0SSunil Mushran 	struct o2net_sock_container *sc, *ret = NULL;
2152309e9e0SSunil Mushran 
2162309e9e0SSunil Mushran 	assert_spin_locked(&o2net_debug_lock);
2172309e9e0SSunil Mushran 
2182309e9e0SSunil Mushran 	list_for_each_entry(sc, &sc_start->sc_net_debug_item,
2192309e9e0SSunil Mushran 			    sc_net_debug_item) {
2202309e9e0SSunil Mushran 		/* discover the head of the list miscast as a sc */
2212309e9e0SSunil Mushran 		if (&sc->sc_net_debug_item == &sock_containers)
2222309e9e0SSunil Mushran 			break;
2232309e9e0SSunil Mushran 
2242309e9e0SSunil Mushran 		/* use sc_page to detect real scs in the list */
2252309e9e0SSunil Mushran 		if (sc->sc_page != NULL) {
2262309e9e0SSunil Mushran 			ret = sc;
2272309e9e0SSunil Mushran 			break;
2282309e9e0SSunil Mushran 		}
2292309e9e0SSunil Mushran 	}
2302309e9e0SSunil Mushran 
2312309e9e0SSunil Mushran 	return ret;
2322309e9e0SSunil Mushran }
2332309e9e0SSunil Mushran 
sc_seq_start(struct seq_file * seq,loff_t * pos)2342309e9e0SSunil Mushran static void *sc_seq_start(struct seq_file *seq, loff_t *pos)
2352309e9e0SSunil Mushran {
236db02754cSSunil Mushran 	struct o2net_sock_debug *sd = seq->private;
237db02754cSSunil Mushran 	struct o2net_sock_container *sc, *dummy_sc = sd->dbg_sock;
2382309e9e0SSunil Mushran 
239*84c10951SChengfeng Ye 	spin_lock_bh(&o2net_debug_lock);
2402309e9e0SSunil Mushran 	sc = next_sc(dummy_sc);
241*84c10951SChengfeng Ye 	spin_unlock_bh(&o2net_debug_lock);
2422309e9e0SSunil Mushran 
2432309e9e0SSunil Mushran 	return sc;
2442309e9e0SSunil Mushran }
2452309e9e0SSunil Mushran 
sc_seq_next(struct seq_file * seq,void * v,loff_t * pos)2462309e9e0SSunil Mushran static void *sc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2472309e9e0SSunil Mushran {
248db02754cSSunil Mushran 	struct o2net_sock_debug *sd = seq->private;
249db02754cSSunil Mushran 	struct o2net_sock_container *sc, *dummy_sc = sd->dbg_sock;
2502309e9e0SSunil Mushran 
251*84c10951SChengfeng Ye 	spin_lock_bh(&o2net_debug_lock);
2522309e9e0SSunil Mushran 	sc = next_sc(dummy_sc);
2532309e9e0SSunil Mushran 	list_del_init(&dummy_sc->sc_net_debug_item);
2542309e9e0SSunil Mushran 	if (sc)
2552309e9e0SSunil Mushran 		list_add(&dummy_sc->sc_net_debug_item, &sc->sc_net_debug_item);
256*84c10951SChengfeng Ye 	spin_unlock_bh(&o2net_debug_lock);
2572309e9e0SSunil Mushran 
2582309e9e0SSunil Mushran 	return sc; /* unused, just needs to be null when done */
2592309e9e0SSunil Mushran }
2602309e9e0SSunil Mushran 
261db02754cSSunil Mushran #ifdef CONFIG_OCFS2_FS_STATS
262db02754cSSunil Mushran # define sc_send_count(_s)		((_s)->sc_send_count)
263db02754cSSunil Mushran # define sc_recv_count(_s)		((_s)->sc_recv_count)
264db02754cSSunil Mushran # define sc_tv_acquiry_total_ns(_s)	(ktime_to_ns((_s)->sc_tv_acquiry_total))
265db02754cSSunil Mushran # define sc_tv_send_total_ns(_s)	(ktime_to_ns((_s)->sc_tv_send_total))
266db02754cSSunil Mushran # define sc_tv_status_total_ns(_s)	(ktime_to_ns((_s)->sc_tv_status_total))
267db02754cSSunil Mushran # define sc_tv_process_total_ns(_s)	(ktime_to_ns((_s)->sc_tv_process_total))
268db02754cSSunil Mushran #else
269db02754cSSunil Mushran # define sc_send_count(_s)		(0U)
270db02754cSSunil Mushran # define sc_recv_count(_s)		(0U)
271db02754cSSunil Mushran # define sc_tv_acquiry_total_ns(_s)	(0LL)
272db02754cSSunil Mushran # define sc_tv_send_total_ns(_s)	(0LL)
273db02754cSSunil Mushran # define sc_tv_status_total_ns(_s)	(0LL)
274db02754cSSunil Mushran # define sc_tv_process_total_ns(_s)	(0LL)
275db02754cSSunil Mushran #endif
276db02754cSSunil Mushran 
277db02754cSSunil Mushran /* So that debugfs.ocfs2 can determine which format is being used */
278db02754cSSunil Mushran #define O2NET_STATS_STR_VERSION		1
sc_show_sock_stats(struct seq_file * seq,struct o2net_sock_container * sc)279db02754cSSunil Mushran static void sc_show_sock_stats(struct seq_file *seq,
280db02754cSSunil Mushran 			       struct o2net_sock_container *sc)
2812309e9e0SSunil Mushran {
282db02754cSSunil Mushran 	if (!sc)
283db02754cSSunil Mushran 		return;
2842309e9e0SSunil Mushran 
285db02754cSSunil Mushran 	seq_printf(seq, "%d,%u,%lu,%lld,%lld,%lld,%lu,%lld\n", O2NET_STATS_STR_VERSION,
286db02754cSSunil Mushran 		   sc->sc_node->nd_num, (unsigned long)sc_send_count(sc),
287db02754cSSunil Mushran 		   (long long)sc_tv_acquiry_total_ns(sc),
288db02754cSSunil Mushran 		   (long long)sc_tv_send_total_ns(sc),
289db02754cSSunil Mushran 		   (long long)sc_tv_status_total_ns(sc),
290db02754cSSunil Mushran 		   (unsigned long)sc_recv_count(sc),
291db02754cSSunil Mushran 		   (long long)sc_tv_process_total_ns(sc));
292db02754cSSunil Mushran }
2932309e9e0SSunil Mushran 
sc_show_sock_container(struct seq_file * seq,struct o2net_sock_container * sc)294db02754cSSunil Mushran static void sc_show_sock_container(struct seq_file *seq,
295db02754cSSunil Mushran 				   struct o2net_sock_container *sc)
296db02754cSSunil Mushran {
2972309e9e0SSunil Mushran 	struct inet_sock *inet = NULL;
2982309e9e0SSunil Mushran 	__be32 saddr = 0, daddr = 0;
2992309e9e0SSunil Mushran 	__be16 sport = 0, dport = 0;
3002309e9e0SSunil Mushran 
301db02754cSSunil Mushran 	if (!sc)
302db02754cSSunil Mushran 		return;
303db02754cSSunil Mushran 
3042309e9e0SSunil Mushran 	if (sc->sc_sock) {
3052309e9e0SSunil Mushran 		inet = inet_sk(sc->sc_sock->sk);
3062309e9e0SSunil Mushran 		/* the stack's structs aren't sparse endian clean */
307c720c7e8SEric Dumazet 		saddr = (__force __be32)inet->inet_saddr;
308c720c7e8SEric Dumazet 		daddr = (__force __be32)inet->inet_daddr;
309c720c7e8SEric Dumazet 		sport = (__force __be16)inet->inet_sport;
310c720c7e8SEric Dumazet 		dport = (__force __be16)inet->inet_dport;
3112309e9e0SSunil Mushran 	}
3122309e9e0SSunil Mushran 
3132309e9e0SSunil Mushran 	/* XXX sigh, inet-> doesn't have sparse annotation so any
3142309e9e0SSunil Mushran 	 * use of it here generates a warning with -Wbitwise */
3152309e9e0SSunil Mushran 	seq_printf(seq, "%p:\n"
3162309e9e0SSunil Mushran 		   "  krefs:           %d\n"
317be859405SHarvey Harrison 		   "  sock:            %pI4:%u -> "
318be859405SHarvey Harrison 				      "%pI4:%u\n"
3192309e9e0SSunil Mushran 		   "  remote node:     %s\n"
3202309e9e0SSunil Mushran 		   "  page off:        %zu\n"
3212309e9e0SSunil Mushran 		   "  handshake ok:    %u\n"
322ff1becbfSSunil Mushran 		   "  timer:           %lld usecs\n"
323ff1becbfSSunil Mushran 		   "  data ready:      %lld usecs\n"
324ff1becbfSSunil Mushran 		   "  advance start:   %lld usecs\n"
325ff1becbfSSunil Mushran 		   "  advance stop:    %lld usecs\n"
326ff1becbfSSunil Mushran 		   "  func start:      %lld usecs\n"
327ff1becbfSSunil Mushran 		   "  func stop:       %lld usecs\n"
328ff1becbfSSunil Mushran 		   "  func key:        0x%08x\n"
3292309e9e0SSunil Mushran 		   "  func type:       %u\n",
3302309e9e0SSunil Mushran 		   sc,
3312c935bc5SPeter Zijlstra 		   kref_read(&sc->sc_kref),
332be859405SHarvey Harrison 		   &saddr, inet ? ntohs(sport) : 0,
333be859405SHarvey Harrison 		   &daddr, inet ? ntohs(dport) : 0,
3342309e9e0SSunil Mushran 		   sc->sc_node->nd_name,
3352309e9e0SSunil Mushran 		   sc->sc_page_off,
3362309e9e0SSunil Mushran 		   sc->sc_handshake_ok,
337ff1becbfSSunil Mushran 		   (long long)ktime_to_us(sc->sc_tv_timer),
338ff1becbfSSunil Mushran 		   (long long)ktime_to_us(sc->sc_tv_data_ready),
339ff1becbfSSunil Mushran 		   (long long)ktime_to_us(sc->sc_tv_advance_start),
340ff1becbfSSunil Mushran 		   (long long)ktime_to_us(sc->sc_tv_advance_stop),
341ff1becbfSSunil Mushran 		   (long long)ktime_to_us(sc->sc_tv_func_start),
342ff1becbfSSunil Mushran 		   (long long)ktime_to_us(sc->sc_tv_func_stop),
3432309e9e0SSunil Mushran 		   sc->sc_msg_key,
3442309e9e0SSunil Mushran 		   sc->sc_msg_type);
3452309e9e0SSunil Mushran }
3462309e9e0SSunil Mushran 
sc_seq_show(struct seq_file * seq,void * v)347db02754cSSunil Mushran static int sc_seq_show(struct seq_file *seq, void *v)
348db02754cSSunil Mushran {
349db02754cSSunil Mushran 	struct o2net_sock_debug *sd = seq->private;
350db02754cSSunil Mushran 	struct o2net_sock_container *sc, *dummy_sc = sd->dbg_sock;
351db02754cSSunil Mushran 
352*84c10951SChengfeng Ye 	spin_lock_bh(&o2net_debug_lock);
353db02754cSSunil Mushran 	sc = next_sc(dummy_sc);
354db02754cSSunil Mushran 
355db02754cSSunil Mushran 	if (sc) {
356db02754cSSunil Mushran 		if (sd->dbg_ctxt == SHOW_SOCK_CONTAINERS)
357db02754cSSunil Mushran 			sc_show_sock_container(seq, sc);
358db02754cSSunil Mushran 		else
359db02754cSSunil Mushran 			sc_show_sock_stats(seq, sc);
360db02754cSSunil Mushran 	}
3612309e9e0SSunil Mushran 
362*84c10951SChengfeng Ye 	spin_unlock_bh(&o2net_debug_lock);
3632309e9e0SSunil Mushran 
3642309e9e0SSunil Mushran 	return 0;
3652309e9e0SSunil Mushran }
3662309e9e0SSunil Mushran 
sc_seq_stop(struct seq_file * seq,void * v)3672309e9e0SSunil Mushran static void sc_seq_stop(struct seq_file *seq, void *v)
3682309e9e0SSunil Mushran {
3692309e9e0SSunil Mushran }
3702309e9e0SSunil Mushran 
37188e9d34cSJames Morris static const struct seq_operations sc_seq_ops = {
3722309e9e0SSunil Mushran 	.start = sc_seq_start,
3732309e9e0SSunil Mushran 	.next = sc_seq_next,
3742309e9e0SSunil Mushran 	.stop = sc_seq_stop,
3752309e9e0SSunil Mushran 	.show = sc_seq_show,
3762309e9e0SSunil Mushran };
3772309e9e0SSunil Mushran 
sc_common_open(struct file * file,int ctxt)378f3288338SRob Jones static int sc_common_open(struct file *file, int ctxt)
3792309e9e0SSunil Mushran {
380f3288338SRob Jones 	struct o2net_sock_debug *sd;
3812309e9e0SSunil Mushran 	struct o2net_sock_container *dummy_sc;
3822309e9e0SSunil Mushran 
383f3288338SRob Jones 	dummy_sc = kzalloc(sizeof(*dummy_sc), GFP_KERNEL);
384f3288338SRob Jones 	if (!dummy_sc)
385f3288338SRob Jones 		return -ENOMEM;
386f3288338SRob Jones 
387f3288338SRob Jones 	sd = __seq_open_private(file, &sc_seq_ops, sizeof(*sd));
388f3288338SRob Jones 	if (!sd) {
389f3288338SRob Jones 		kfree(dummy_sc);
390f3288338SRob Jones 		return -ENOMEM;
3912309e9e0SSunil Mushran 	}
3922309e9e0SSunil Mushran 
393f3288338SRob Jones 	sd->dbg_ctxt = ctxt;
394db02754cSSunil Mushran 	sd->dbg_sock = dummy_sc;
395f3288338SRob Jones 
3962309e9e0SSunil Mushran 	o2net_debug_add_sc(dummy_sc);
3972309e9e0SSunil Mushran 
398f3288338SRob Jones 	return 0;
3992309e9e0SSunil Mushran }
4002309e9e0SSunil Mushran 
sc_fop_release(struct inode * inode,struct file * file)4012309e9e0SSunil Mushran static int sc_fop_release(struct inode *inode, struct file *file)
4022309e9e0SSunil Mushran {
4032309e9e0SSunil Mushran 	struct seq_file *seq = file->private_data;
404db02754cSSunil Mushran 	struct o2net_sock_debug *sd = seq->private;
405db02754cSSunil Mushran 	struct o2net_sock_container *dummy_sc = sd->dbg_sock;
4062309e9e0SSunil Mushran 
4072309e9e0SSunil Mushran 	o2net_debug_del_sc(dummy_sc);
40825b1c72eSpiaojun 	kfree(dummy_sc);
4092309e9e0SSunil Mushran 	return seq_release_private(inode, file);
4102309e9e0SSunil Mushran }
4112309e9e0SSunil Mushran 
stats_fop_open(struct inode * inode,struct file * file)412db02754cSSunil Mushran static int stats_fop_open(struct inode *inode, struct file *file)
413db02754cSSunil Mushran {
414f3288338SRob Jones 	return sc_common_open(file, SHOW_SOCK_STATS);
415db02754cSSunil Mushran }
416db02754cSSunil Mushran 
417db02754cSSunil Mushran static const struct file_operations stats_seq_fops = {
418db02754cSSunil Mushran 	.open = stats_fop_open,
419db02754cSSunil Mushran 	.read = seq_read,
420db02754cSSunil Mushran 	.llseek = seq_lseek,
421db02754cSSunil Mushran 	.release = sc_fop_release,
422db02754cSSunil Mushran };
423db02754cSSunil Mushran 
sc_fop_open(struct inode * inode,struct file * file)424db02754cSSunil Mushran static int sc_fop_open(struct inode *inode, struct file *file)
425db02754cSSunil Mushran {
426f3288338SRob Jones 	return sc_common_open(file, SHOW_SOCK_CONTAINERS);
427db02754cSSunil Mushran }
428db02754cSSunil Mushran 
429828c0950SAlexey Dobriyan static const struct file_operations sc_seq_fops = {
4302309e9e0SSunil Mushran 	.open = sc_fop_open,
4312309e9e0SSunil Mushran 	.read = seq_read,
4322309e9e0SSunil Mushran 	.llseek = seq_lseek,
4332309e9e0SSunil Mushran 	.release = sc_fop_release,
4342309e9e0SSunil Mushran };
4352309e9e0SSunil Mushran 
o2net_fill_bitmap(char * buf,int len)4363ba169ccSSunil Mushran static int o2net_fill_bitmap(char *buf, int len)
4372309e9e0SSunil Mushran {
4383ba169ccSSunil Mushran 	unsigned long map[BITS_TO_LONGS(O2NM_MAX_NODES)];
4393ba169ccSSunil Mushran 	int i = -1, out = 0;
4403ba169ccSSunil Mushran 
4416d4a93b6SJoseph Qi 	o2net_fill_node_map(map, O2NM_MAX_NODES);
4423ba169ccSSunil Mushran 
4433ba169ccSSunil Mushran 	while ((i = find_next_bit(map, O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES)
444d293d3afSTakashi Iwai 		out += scnprintf(buf + out, PAGE_SIZE - out, "%d ", i);
445d293d3afSTakashi Iwai 	out += scnprintf(buf + out, PAGE_SIZE - out, "\n");
4463ba169ccSSunil Mushran 
4473ba169ccSSunil Mushran 	return out;
4482309e9e0SSunil Mushran }
4492309e9e0SSunil Mushran 
nodes_fop_open(struct inode * inode,struct file * file)4503ba169ccSSunil Mushran static int nodes_fop_open(struct inode *inode, struct file *file)
4513ba169ccSSunil Mushran {
4523ba169ccSSunil Mushran 	char *buf;
4532309e9e0SSunil Mushran 
4543ba169ccSSunil Mushran 	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
4553ba169ccSSunil Mushran 	if (!buf)
4563ba169ccSSunil Mushran 		return -ENOMEM;
4572309e9e0SSunil Mushran 
4583ba169ccSSunil Mushran 	i_size_write(inode, o2net_fill_bitmap(buf, PAGE_SIZE));
4593ba169ccSSunil Mushran 
4603ba169ccSSunil Mushran 	file->private_data = buf;
461db02754cSSunil Mushran 
4622309e9e0SSunil Mushran 	return 0;
4632309e9e0SSunil Mushran }
4642309e9e0SSunil Mushran 
o2net_debug_release(struct inode * inode,struct file * file)4653ba169ccSSunil Mushran static int o2net_debug_release(struct inode *inode, struct file *file)
4663ba169ccSSunil Mushran {
4673ba169ccSSunil Mushran 	kfree(file->private_data);
4683ba169ccSSunil Mushran 	return 0;
4693ba169ccSSunil Mushran }
4703ba169ccSSunil Mushran 
o2net_debug_read(struct file * file,char __user * buf,size_t nbytes,loff_t * ppos)4713ba169ccSSunil Mushran static ssize_t o2net_debug_read(struct file *file, char __user *buf,
4723ba169ccSSunil Mushran 				size_t nbytes, loff_t *ppos)
4733ba169ccSSunil Mushran {
4743ba169ccSSunil Mushran 	return simple_read_from_buffer(buf, nbytes, ppos, file->private_data,
4753ba169ccSSunil Mushran 				       i_size_read(file->f_mapping->host));
4763ba169ccSSunil Mushran }
4773ba169ccSSunil Mushran 
4783ba169ccSSunil Mushran static const struct file_operations nodes_fops = {
4793ba169ccSSunil Mushran 	.open		= nodes_fop_open,
4803ba169ccSSunil Mushran 	.release	= o2net_debug_release,
4813ba169ccSSunil Mushran 	.read		= o2net_debug_read,
4823ba169ccSSunil Mushran 	.llseek		= generic_file_llseek,
4833ba169ccSSunil Mushran };
4843ba169ccSSunil Mushran 
o2net_debugfs_exit(void)4852309e9e0SSunil Mushran void o2net_debugfs_exit(void)
4862309e9e0SSunil Mushran {
487e581595eSGreg Kroah-Hartman 	debugfs_remove_recursive(o2net_dentry);
4882309e9e0SSunil Mushran }
4892309e9e0SSunil Mushran 
o2net_debugfs_init(void)490e581595eSGreg Kroah-Hartman void o2net_debugfs_init(void)
4913ba169ccSSunil Mushran {
492f4ae40a6SAl Viro 	umode_t mode = S_IFREG|S_IRUSR;
4933ba169ccSSunil Mushran 
4943ba169ccSSunil Mushran 	o2net_dentry = debugfs_create_dir(O2NET_DEBUG_DIR, NULL);
4953ba169ccSSunil Mushran 
496e581595eSGreg Kroah-Hartman 	debugfs_create_file(NST_DEBUG_NAME, mode, o2net_dentry, NULL,
497e581595eSGreg Kroah-Hartman 			    &nst_seq_fops);
498e581595eSGreg Kroah-Hartman 	debugfs_create_file(SC_DEBUG_NAME, mode, o2net_dentry, NULL,
499e581595eSGreg Kroah-Hartman 			    &sc_seq_fops);
500e581595eSGreg Kroah-Hartman 	debugfs_create_file(STATS_DEBUG_NAME, mode, o2net_dentry, NULL,
501e581595eSGreg Kroah-Hartman 			    &stats_seq_fops);
502e581595eSGreg Kroah-Hartman 	debugfs_create_file(NODES_DEBUG_NAME, mode, o2net_dentry, NULL,
503e581595eSGreg Kroah-Hartman 			    &nodes_fops);
5043ba169ccSSunil Mushran }
5053ba169ccSSunil Mushran 
5062309e9e0SSunil Mushran #endif	/* CONFIG_DEBUG_FS */
507