sunrpc: add debugfs file for displaying client rpc_task queue
Subsystems (3)
PATCH 1/1 sunrpc: add debugfs file for displaying client rpc_task queue
It's possible to get a dump of the RPC task queue by writing a value to /proc/sys/sunrpc/rpc_debug. If you write any value to that file, you get a dump of the RPC client task list into the log buffer. This is a rather inconvenient interface however, and makes it hard to get immediate info about the task queue.
Add a new file under debugfs that shows similar info. There are some small differences -- we avoid printing raw kernel addresses in favor of symbolic names and the XID is also displayed.
--- include/linux/sunrpc/clnt.h | 1 + include/linux/sunrpc/debug.h | 13 ++++ net/sunrpc/Kconfig | 1 + net/sunrpc/Makefile | 1 + net/sunrpc/clnt.c | 3 +- net/sunrpc/debugfs.c | 153 +++++++++++++++++++++++++++++++++++++++++++ net/sunrpc/sunrpc_syms.c | 8 +++ 7 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 net/sunrpc/debugfs.c
include/linux/sunrpc/clnt.h +1 -0
@@ -176,5 +176,6 @@ size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);const char *rpc_peeraddr2str (struct rpc_clnt *,enum rpc_display_format_t );int rpc_localaddr (struct rpc_clnt *,struct sockaddr *,size_t ); +const char *rpc_proc_name (const struct rpc_task *task);#endif /* __KERNEL__ */ #endif /* _LINUX_SUNRPC_CLNT_H */
include/linux/sunrpc/debug.h +13 -0
@@ -68,6 +68,19 @@ extern unsigned int nlm_debug;#ifdef RPC_DEBUG void rpc_register_sysctl (void );void rpc_unregister_sysctl (void ); +int sunrpc_debugfs_init (void ); +void sunrpc_debugfs_exit (void ); +#else +static inline int +sunrpc_debugfs_init (void ) +{ +return 0 ; +} +static inline void +sunrpc_debugfs_exit (void ) +{ +return ; +}#endif #endif /* _LINUX_SUNRPC_DEBUG_H_ */
net/sunrpc/Kconfig +1 -0
@@ -35,6 +35,7 @@ config RPCSEC_GSS_KRB5 config SUNRPC_DEBUG bool "RPC: Enable dprintk debugging" depends on SUNRPC && SYSCTL + select DEBUG_FS help This option enables a sysctl-based debugging interface that is be used by the 'rpcdebug' utility to turn on or off
net/sunrpc/Makefile +1 -0
@@ -14,6 +14,7 @@ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ addr.o rpcb_clnt.o timer.o xdr.o \ sunrpc_syms.o cache.o rpc_pipe.o \ svc_xprt.o +sunrpc-$(CONFIG_SUNRPC_DEBUG) += debugfs.o sunrpc-$(CONFIG_SUNRPC_BACKCHANNEL) += backchannel_rqst.o bc_svc.o sunrpc-$(CONFIG_PROC_FS) += stats.o sunrpc-$(CONFIG_SYSCTL) += sysctl.o
net/sunrpc/clnt.c +2 -1
@@ -1397,7 +1397,8 @@ rpc_restart_call(struct rpc_task *task)EXPORT_SYMBOL_GPL (rpc_restart_call);#ifdef RPC_DEBUG -static const char *rpc_proc_name (const struct rpc_task *task) +const char +*rpc_proc_name (const struct rpc_task *task) {const struct rpc_procinfo *proc = task->tk_msg.rpc_proc;
net/sunrpc/debugfs.c new file +153 -0
153 lines not on this page · raw message
net/sunrpc/sunrpc_syms.c +8 -0
@@ -97,6 +97,11 @@ init_sunrpc(void) err =register_rpc_pipefs ();if (err) goto out4; + + err =sunrpc_debugfs_init (); +if (err) + goto out5; +#ifdef RPC_DEBUG rpc_register_sysctl ();#endif
@@ -104,6 +109,8 @@ init_sunrpc(void)init_socket_xprt ();/* clnt sock transport */ return 0 ; +out5: +unregister_rpc_pipefs (); out4:unregister_pernet_subsys (&sunrpc_net_ops); out3:
@@ -120,6 +127,7 @@ cleanup_sunrpc(void)rpcauth_remove_module ();cleanup_socket_xprt ();svc_cleanup_xprt_sock (); +sunrpc_debugfs_exit ();unregister_rpc_pipefs ();rpc_destroy_mempool ();unregister_pernet_subsys (&sunrpc_net_ops);
Signature · 1 line
1.9.3
Quoted 200 lines · On Tue, 28 Oct 2014 14:24:55 -0400 Jeff Layton <[email protected]> wrote:
It's possible to get a dump of the RPC task queue by writing a value to
/proc/sys/sunrpc/rpc_debug. If you write any value to that file, you get a dump of the RPC client task list into the log buffer. This is a rather inconvenient interface however, and makes it hard to get immediate info about the task queue.Add a new file under debugfs that shows similar info. There are some small differences -- we avoid printing raw kernel addresses in favor of symbolic names and the XID is also displayed.
Signed-off-by Jeff Layton <[email protected]>--- include/linux/sunrpc/clnt.h | 1 + include/linux/sunrpc/debug.h | 13 ++++ net/sunrpc/Kconfig | 1 + net/sunrpc/Makefile | 1 + net/sunrpc/clnt.c | 3 +- net/sunrpc/debugfs.c | 153 +++++++++++++++++++++++++++++++++++++++++++ net/sunrpc/sunrpc_syms.c | 8 +++ 7 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 net/sunrpc/debugfs.cinclude/linux/sunrpc/clnt.h +1
-0@@ -176,5 +176,6 @@ size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);const char *rpc_peeraddr2str (struct rpc_clnt *,enum rpc_display_format_t );int rpc_localaddr (struct rpc_clnt *,struct sockaddr *,size_t ); +const char *rpc_proc_name (const struct rpc_task *task);#endif /* __KERNEL__ */ #endif /* _LINUX_SUNRPC_CLNT_H */ include/linux/sunrpc/debug.h +13
-0@@ -68,6 +68,19 @@ extern unsigned int nlm_debug;#ifdef RPC_DEBUG void rpc_register_sysctl (void );void rpc_unregister_sysctl (void ); +int sunrpc_debugfs_init (void ); +void sunrpc_debugfs_exit (void ); +#else +static inline int +sunrpc_debugfs_init (void ) +{ +return 0 ; +} +static inline void +sunrpc_debugfs_exit (void ) +{ +return ; +}#endif #endif /* _LINUX_SUNRPC_DEBUG_H_ */ net/sunrpc/Kconfig +1
-0@@ -35,6 +35,7 @@ config RPCSEC_GSS_KRB5 config SUNRPC_DEBUG bool "RPC: Enable dprintk debugging" depends on SUNRPC && SYSCTL + select DEBUG_FS help This option enables a sysctl-based debugging interface that is be used by the 'rpcdebug' utility to turn on or offnet/sunrpc/Makefile +1
-0@@ -14,6 +14,7 @@ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ addr.o rpcb_clnt.o timer.o xdr.o \ sunrpc_syms.o cache.o rpc_pipe.o \ svc_xprt.o +sunrpc-$(CONFIG_SUNRPC_DEBUG) += debugfs.o sunrpc-$(CONFIG_SUNRPC_BACKCHANNEL) += backchannel_rqst.o bc_svc.o sunrpc-$(CONFIG_PROC_FS) += stats.o sunrpc-$(CONFIG_SYSCTL) += sysctl.onet/sunrpc/clnt.c +2
-1@@ -1397,7 +1397,8 @@ rpc_restart_call(struct rpc_task *task)EXPORT_SYMBOL_GPL (rpc_restart_call);#ifdef RPC_DEBUG -static const char *rpc_proc_name (const struct rpc_task *task) +const char +*rpc_proc_name (const struct rpc_task *task) {const struct rpc_procinfo *proc = task->tk_msg.rpc_proc;net/sunrpc/debugfs.c new file +99
-0@@ -0,0 +1,153 @@ +/** +* debugfs interface for sunrpc +* +* (c) 2014 Jeff Layton <[email protected]> +*/ + +#include <linux/debugfs.h> +#include <linux/sunrpc/sched.h> +#include <linux/sunrpc/clnt.h> +#include "netns.h" + +static struct dentry *topdir; + +static int +tasks_show (struct seq_file *f,void *v) +{ +u32 xid =0 ; +struct rpc_task *task = v; +struct rpc_clnt *clnt = task->tk_client; +const char *rpc_waitq ="none" ; + +if (RPC_IS_QUEUED (task)) + rpc_waitq =rpc_qname (task->tk_waitqueue); + +if (task->tk_rqstp) + xid =be32_to_cpu (task->tk_rqstp->rq_xid); + +seq_printf (f,"%5u %04x %6d 0x%x 0x%x %8ld %ps %sv%u %s a:%ps q:%s\n" , + task->tk_pid, task->tk_flags, task->tk_status, + clnt->cl_clid, xid, task->tk_timeout, task->tk_ops, + clnt->cl_program->name, clnt->cl_vers,rpc_proc_name (task), + task->tk_action, rpc_waitq); +return 0 ; +} + +static void * +tasks_start (struct seq_file *f,loff_t *ppos) + __acquires(&sn->rpc_client_lock) + __acquires(&clnt->cl_lock) +{ +loff_t *p = f->private, pos = *ppos; +struct rpc_clnt *clnt; +struct rpc_task *task; +struct sunrpc_net *sn =net_generic (current->nsproxy->net_ns, + sunrpc_net_id); + + *p = pos +1 ; +spin_lock (&sn->rpc_client_lock); +list_for_each_entry (clnt, &sn->all_clients, cl_clients) { +spin_lock (&clnt->cl_lock); +list_for_each_entry (task, &clnt->cl_tasks, tk_task) +if (pos-- ==0 ) +return task; +spin_unlock (&clnt->cl_lock); + } +return NULL ; +} + +static void * +tasks_next (struct seq_file *f,void *v,loff_t *pos) + __releases(&clnt->cl_lock) + __acquires(&clnt->cl_lock) +{ +loff_t *p = f->private; +struct rpc_task *task = v; +struct rpc_clnt *clnt = task->tk_client; +struct list_head *next = task->tk_task.next; +struct sunrpc_net *sn =net_generic (current->nsproxy->net_ns, + sunrpc_net_id); + + ++*p; + ++*pos; + +/* If there's another task on list, return it */ +if (next != &clnt->cl_tasks) + return list_entry(next, struct rpc_task, tk_task); + +/* We're finished with this client, move on */ +spin_unlock (&clnt->cl_lock); +next_client: + next = clnt->cl_clients.next; +if (next == &sn->all_clients) +return NULL ; + + clnt = list_entry(next, struct rpc_clnt, cl_clients); +if (list_empty (&clnt->cl_tasks)) + goto next_client; +spin_lock (&clnt->cl_lock); +if (list_empty (&clnt->cl_tasks)) { +spin_unlock (&clnt->cl_lock); + goto next_client; + } + return list_first_entry(&clnt->cl_tasks, struct rpc_task, tk_task); +} + +static void +tasks_stop(struct seq_file *f, void *v) + __releases(&sn->rpc_client_lock) + __releases(&clnt->cl_lock)
net/sunrpc/debugfs.c line 109
Quoted 10 lines
net/sunrpc/debugfs.c new file +10
-0+{ +struct rpc_task *task = v; +struct rpc_clnt *clnt; +struct sunrpc_net *sn =net_generic (current->nsproxy->net_ns, + sunrpc_net_id); + +if (v) { + clnt = task->tk_client; +spin_unlock (&clnt->cl_lock); + }
Full disclosure here...
sparse complains about this patch:
net/sunrpc/debugfs.c:36:13: warning: context imbalance in 'tasks_start' - different lock contexts for basic block net/sunrpc/debugfs.c:59:13: warning: context imbalance in 'tasks_next' - different lock contexts for basic block net/sunrpc/debugfs.c:110:20: warning: context imbalance in 'tasks_stop' - different lock contexts for basic block
The __acquires/__releases annotations don't help in this case since tasks_start and tasks_next can conditionally return with the cl_lock held or not.
If tasks_start/_next return a valid object, then the lock will be held. If it returns NULL then it won't be. There should be no actual lock imbalances however.
Quoted 77 lines
net/sunrpc/debugfs.c new file +44
-0+spin_unlock (&sn->rpc_client_lock); +} + +static const struct seq_operations tasks_seq_operations = { + .start = tasks_start, + .next = tasks_next, + .stop = tasks_stop, + .show = tasks_show, +}; + +static int tasks_open (struct inode *inode,struct file *filp) +{ +return seq_open_private (filp, &tasks_seq_operations, +sizeof (loff_t)); +} + +static const struct file_operations tasks_fops = { + .owner =THIS_MODULE , + .open = tasks_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + +void __exit +sunrpc_debugfs_exit (void ) +{ +debugfs_remove_recursive (topdir); +} + +int __init +sunrpc_debugfs_init (void ) +{ + topdir =debugfs_create_dir ("sunrpc" ,NULL ); +if (!topdir) +return -ENOMEM ; + +if (!debugfs_create_file ("client_tasks" ,S_IFREG |S_IRUSR , topdir, +NULL , &tasks_fops)) { +debugfs_remove_recursive (topdir); +return -ENOMEM ; + } +return 0 ; +}net/sunrpc/sunrpc_syms.c +8
-0@@ -97,6 +97,11 @@ init_sunrpc(void) err =register_rpc_pipefs ();if (err) goto out4; + + err =sunrpc_debugfs_init (); +if (err) + goto out5; +#ifdef RPC_DEBUG rpc_register_sysctl ();#endif @@ -104,6 +109,8 @@ init_sunrpc(void)init_socket_xprt ();/* clnt sock transport */ return 0 ; +out5: +unregister_rpc_pipefs (); out4:unregister_pernet_subsys (&sunrpc_net_ops); out3:@@ -120,6 +127,7 @@ cleanup_sunrpc(void)rpcauth_remove_module ();cleanup_socket_xprt ();svc_cleanup_xprt_sock (); +sunrpc_debugfs_exit ();unregister_rpc_pipefs ();rpc_destroy_mempool ();unregister_pernet_subsys (&sunrpc_net_ops);
Signature · 1 line
Jeff Layton <[email protected]>
Quoted 153 lines · Jeff Layton
Quoted 150 lines · On Tue, 28 Oct 2014 14:24:55 -0400 Jeff Layton <[email protected]> wrote:
It's possible to get a dump of the RPC task queue by writing a value to
/proc/sys/sunrpc/rpc_debug. If you write any value to that file, you get a dump of the RPC client task list into the log buffer. This is a rather inconvenient interface however, and makes it hard to get immediate info about the task queue.Add a new file under debugfs that shows similar info. There are some small differences -- we avoid printing raw kernel addresses in favor of symbolic names and the XID is also displayed.
Signed-off-by Jeff Layton <[email protected]>--- include/linux/sunrpc/clnt.h | 1 + include/linux/sunrpc/debug.h | 13 ++++ net/sunrpc/Kconfig | 1 + net/sunrpc/Makefile | 1 + net/sunrpc/clnt.c | 3 +- net/sunrpc/debugfs.c | 153 +++++++++++++++++++++++++++++++++++++++++++ net/sunrpc/sunrpc_syms.c | 8 +++ 7 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 net/sunrpc/debugfs.cinclude/linux/sunrpc/clnt.h +1
-0@@ -176,5 +176,6 @@ size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);const char *rpc_peeraddr2str (struct rpc_clnt *,enum rpc_display_format_t );int rpc_localaddr (struct rpc_clnt *,struct sockaddr *,size_t ); +const char *rpc_proc_name (const struct rpc_task *task);#endif /* __KERNEL__ */ #endif /* _LINUX_SUNRPC_CLNT_H */ include/linux/sunrpc/debug.h +13
-0@@ -68,6 +68,19 @@ extern unsigned int nlm_debug;#ifdef RPC_DEBUG void rpc_register_sysctl (void );void rpc_unregister_sysctl (void ); +int sunrpc_debugfs_init (void ); +void sunrpc_debugfs_exit (void ); +#else +static inline int +sunrpc_debugfs_init (void ) +{ +return 0 ; +} +static inline void +sunrpc_debugfs_exit (void ) +{ +return ; +}#endif #endif /* _LINUX_SUNRPC_DEBUG_H_ */ net/sunrpc/Kconfig +1
-0@@ -35,6 +35,7 @@ config RPCSEC_GSS_KRB5 config SUNRPC_DEBUG bool "RPC: Enable dprintk debugging" depends on SUNRPC && SYSCTL + select DEBUG_FS help This option enables a sysctl-based debugging interface that is be used by the 'rpcdebug' utility to turn on or offnet/sunrpc/Makefile +1
-0@@ -14,6 +14,7 @@ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ addr.o rpcb_clnt.o timer.o xdr.o \ sunrpc_syms.o cache.o rpc_pipe.o \ svc_xprt.o +sunrpc-$(CONFIG_SUNRPC_DEBUG) += debugfs.o sunrpc-$(CONFIG_SUNRPC_BACKCHANNEL) += backchannel_rqst.o bc_svc.o sunrpc-$(CONFIG_PROC_FS) += stats.o sunrpc-$(CONFIG_SYSCTL) += sysctl.onet/sunrpc/clnt.c +2
-1@@ -1397,7 +1397,8 @@ rpc_restart_call(struct rpc_task *task)EXPORT_SYMBOL_GPL (rpc_restart_call);#ifdef RPC_DEBUG -static const char *rpc_proc_name (const struct rpc_task *task) +const char +*rpc_proc_name (const struct rpc_task *task) {const struct rpc_procinfo *proc = task->tk_msg.rpc_proc;net/sunrpc/debugfs.c new file +49
-0@@ -0,0 +1,153 @@ +/** +* debugfs interface for sunrpc +* +* (c) 2014 Jeff Layton <[email protected]> +*/ + +#include <linux/debugfs.h> +#include <linux/sunrpc/sched.h> +#include <linux/sunrpc/clnt.h> +#include "netns.h" + +static struct dentry *topdir; + +static int +tasks_show (struct seq_file *f,void *v) +{ +u32 xid =0 ; +struct rpc_task *task = v; +struct rpc_clnt *clnt = task->tk_client; +const char *rpc_waitq ="none" ; + +if (RPC_IS_QUEUED (task)) + rpc_waitq =rpc_qname (task->tk_waitqueue); + +if (task->tk_rqstp) + xid =be32_to_cpu (task->tk_rqstp->rq_xid); + +seq_printf (f,"%5u %04x %6d 0x%x 0x%x %8ld %ps %sv%u %s a:%ps q:%s\n" , + task->tk_pid, task->tk_flags, task->tk_status, + clnt->cl_clid, xid, task->tk_timeout, task->tk_ops, + clnt->cl_program->name, clnt->cl_vers,rpc_proc_name (task), + task->tk_action, rpc_waitq); +return 0 ; +} + +static void * +tasks_start (struct seq_file *f,loff_t *ppos) + __acquires(&sn->rpc_client_lock) + __acquires(&clnt->cl_lock) +{ +loff_t *p = f->private, pos = *ppos; +struct rpc_clnt *clnt; +struct rpc_task *task; +struct sunrpc_net *sn =net_generic (current->nsproxy->net_ns, + sunrpc_net_id); + + *p = pos +1 ; +spin_lock (&sn->rpc_client_lock); +list_for_each_entry (clnt, &sn->all_clients, cl_clients) {
Quoted 8 lines
net/sunrpc/debugfs.c line 57
Quoted 8 lines
net/sunrpc/debugfs.c new file +8
-0+spin_lock (&clnt->cl_lock); +list_for_each_entry (task, &clnt->cl_tasks, tk_task) +if (pos-- ==0 ) +return task; +spin_unlock (&clnt->cl_lock); + } +return NULL ; +}
Instead of having a single pseudofile that iterates through all rpc_clients and all rpc_tasks, should we perhaps have a hierarchy of subdirectories?
I'm thinking we might want a directory per rpc_client, each containing a pseudo-file that iterates through all rpc_tasks for that rpc_client only. The reason for doing so would be so that we can add pseudofiles to display more per-rpc_client debugging info, such as cl_nodename, cl_program->name, cl_prog, cl_vers. Maybe also with a symlink to another subdirectory that displays per-xprt debugging information?
i.e. a hierarchy of the form
debugfs/
rpc_clients/
1/
cl_tasks
cl_xprt->../../rpc_xprt/1
.....
2/
cl_tasks
cl_xprt->../../rpc_xprt/1
.....
rpc_xprt/
1/
servername.....
Signature · 5 lines
Trond Myklebust Linux NFS client maintainer, PrimaryData [email protected]
Quoted 174 lines · On Mon, 24 Nov 2014 14:20:25 -0500 Trond Myklebust…
Quoted 153 lines · Jeff Layton
Quoted 150 lines · On Tue, 28 Oct 2014 14:24:55 -0400 Jeff Layton <[email protected]> wrote:
It's possible to get a dump of the RPC task queue by writing a value to
/proc/sys/sunrpc/rpc_debug. If you write any value to that file, you get a dump of the RPC client task list into the log buffer. This is a rather inconvenient interface however, and makes it hard to get immediate info about the task queue.Add a new file under debugfs that shows similar info. There are some small differences -- we avoid printing raw kernel addresses in favor of symbolic names and the XID is also displayed.
Signed-off-by Jeff Layton <[email protected]>--- include/linux/sunrpc/clnt.h | 1 + include/linux/sunrpc/debug.h | 13 ++++ net/sunrpc/Kconfig | 1 + net/sunrpc/Makefile | 1 + net/sunrpc/clnt.c | 3 +- net/sunrpc/debugfs.c | 153 +++++++++++++++++++++++++++++++++++++++++++ net/sunrpc/sunrpc_syms.c | 8 +++ 7 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 net/sunrpc/debugfs.cinclude/linux/sunrpc/clnt.h +1
-0@@ -176,5 +176,6 @@ size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);const char *rpc_peeraddr2str (struct rpc_clnt *,enum rpc_display_format_t );int rpc_localaddr (struct rpc_clnt *,struct sockaddr *,size_t ); +const char *rpc_proc_name (const struct rpc_task *task);#endif /* __KERNEL__ */ #endif /* _LINUX_SUNRPC_CLNT_H */ include/linux/sunrpc/debug.h +13
-0@@ -68,6 +68,19 @@ extern unsigned int nlm_debug;#ifdef RPC_DEBUG void rpc_register_sysctl (void );void rpc_unregister_sysctl (void ); +int sunrpc_debugfs_init (void ); +void sunrpc_debugfs_exit (void ); +#else +static inline int +sunrpc_debugfs_init (void ) +{ +return 0 ; +} +static inline void +sunrpc_debugfs_exit (void ) +{ +return ; +}#endif #endif /* _LINUX_SUNRPC_DEBUG_H_ */ net/sunrpc/Kconfig +1
-0@@ -35,6 +35,7 @@ config RPCSEC_GSS_KRB5 config SUNRPC_DEBUG bool "RPC: Enable dprintk debugging" depends on SUNRPC && SYSCTL + select DEBUG_FS help This option enables a sysctl-based debugging interface that is be used by the 'rpcdebug' utility to turn on or offnet/sunrpc/Makefile +1
-0@@ -14,6 +14,7 @@ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ addr.o rpcb_clnt.o timer.o xdr.o \ sunrpc_syms.o cache.o rpc_pipe.o \ svc_xprt.o +sunrpc-$(CONFIG_SUNRPC_DEBUG) += debugfs.o sunrpc-$(CONFIG_SUNRPC_BACKCHANNEL) += backchannel_rqst.o bc_svc.o sunrpc-$(CONFIG_PROC_FS) += stats.o sunrpc-$(CONFIG_SYSCTL) += sysctl.onet/sunrpc/clnt.c +2
-1@@ -1397,7 +1397,8 @@ rpc_restart_call(struct rpc_task *task)EXPORT_SYMBOL_GPL (rpc_restart_call);#ifdef RPC_DEBUG -static const char *rpc_proc_name (const struct rpc_task *task) +const char +*rpc_proc_name (const struct rpc_task *task) {const struct rpc_procinfo *proc = task->tk_msg.rpc_proc;net/sunrpc/debugfs.c new file +49
-0@@ -0,0 +1,153 @@ +/** +* debugfs interface for sunrpc +* +* (c) 2014 Jeff Layton <[email protected]> +*/ + +#include <linux/debugfs.h> +#include <linux/sunrpc/sched.h> +#include <linux/sunrpc/clnt.h> +#include "netns.h" + +static struct dentry *topdir; + +static int +tasks_show (struct seq_file *f,void *v) +{ +u32 xid =0 ; +struct rpc_task *task = v; +struct rpc_clnt *clnt = task->tk_client; +const char *rpc_waitq ="none" ; + +if (RPC_IS_QUEUED (task)) + rpc_waitq =rpc_qname (task->tk_waitqueue); + +if (task->tk_rqstp) + xid =be32_to_cpu (task->tk_rqstp->rq_xid); + +seq_printf (f,"%5u %04x %6d 0x%x 0x%x %8ld %ps %sv%u %s a:%ps q:%s\n" , + task->tk_pid, task->tk_flags, task->tk_status, + clnt->cl_clid, xid, task->tk_timeout, task->tk_ops, + clnt->cl_program->name, clnt->cl_vers,rpc_proc_name (task), + task->tk_action, rpc_waitq); +return 0 ; +} + +static void * +tasks_start (struct seq_file *f,loff_t *ppos) + __acquires(&sn->rpc_client_lock) + __acquires(&clnt->cl_lock) +{ +loff_t *p = f->private, pos = *ppos; +struct rpc_clnt *clnt; +struct rpc_task *task; +struct sunrpc_net *sn =net_generic (current->nsproxy->net_ns, + sunrpc_net_id); + + *p = pos +1 ; +spin_lock (&sn->rpc_client_lock); +list_for_each_entry (clnt, &sn->all_clients, cl_clients) {Quoted 8 lines
net/sunrpc/debugfs.c line 57
Quoted 8 lines
net/sunrpc/debugfs.c new file +8
-0+spin_lock (&clnt->cl_lock); +list_for_each_entry (task, &clnt->cl_tasks, tk_task) +if (pos-- ==0 ) +return task; +spin_unlock (&clnt->cl_lock); + } +return NULL ; +}Instead of having a single pseudofile that iterates through all
rpc_clientsand allrpc_tasks, should we perhaps have a hierarchy of subdirectories?
I'm thinking we might want a directory perrpc_client, each containing a pseudo-file that iterates through allrpc_tasksfor thatrpc_clientonly. The reason for doing so would be so that we can add pseudofiles to display more per-rpc_client debugging info, such ascl_nodename,cl_program->name,cl_prog,cl_vers. Maybe also with a symlink to another subdirectory that displays per-xprt debugging information?
Quoted 3 lines
i.e. a hierarchy of the form
debugfs/
I'd suggest that we have a top level "sunrpc/" directory here to keep things neat and tidy.
Quoted 12 lines
rpc_clients/
1/
cl_tasks
cl_xprt->../../rpc_xprt/1
.....
2/
cl_tasks
cl_xprt->../../rpc_xprt/1
.....
rpc_xprt/
1/
servernameQuoted 2 lines
.....
Hmm...that looks doable, but is a much larger piece of work than this patch. Let me see what I can come up with and I'll get back to you...
Signature · 1 line
Jeff Layton <[email protected]>
v2 cover sunrpc: add debugfs file for displaying client rpc_task queue
In reply to Jeff LaytonThis is a respin of this patch that I sent a few weeks ago:
sunrpc: add debugfs file for displaying client rpc_task queue
...to address Trond's concerns about how to lay out this directory.
I've also included a respin of the patches to eliminate the unneeded #define redirection in the sunrpc debugging code. I had originally based those patches on top of the debugfs patch, so if we drop that patch there are merge conflicts with these.
In this set, I've reversed the order so if there are any more respins needed on the debugfs work, I shouldn't need to resend the whole set.
Jeff Layton (4):
lockd: eliminate LOCKD_DEBUG
sunrpc: eliminate RPC_DEBUG
sunrpc: eliminate RPC_TRACEPOINTS
sunrpc: add debugfs file for displaying client rpc_task queue
fs/lockd/svclock.c | 2 +- include/linux/lockd/debug.h | 6 +- include/linux/sunrpc/auth.h | 2 +- include/linux/sunrpc/clnt.h | 4 + include/linux/sunrpc/debug.h | 49 ++++++--- include/linux/sunrpc/sched.h | 8 +- include/uapi/linux/nfsd/debug.h | 2 +- net/sunrpc/Kconfig | 1 + net/sunrpc/Makefile | 1 + net/sunrpc/auth.c | 4 +- net/sunrpc/auth_generic.c | 2 +- net/sunrpc/auth_gss/auth_gss.c | 2 +- net/sunrpc/auth_gss/gss_generic_token.c | 2 +- net/sunrpc/auth_gss/gss_krb5_crypto.c | 2 +- net/sunrpc/auth_gss/gss_krb5_keys.c | 2 +- net/sunrpc/auth_gss/gss_krb5_mech.c | 2 +- net/sunrpc/auth_gss/gss_krb5_seal.c | 2 +- net/sunrpc/auth_gss/gss_krb5_seqnum.c | 2 +- net/sunrpc/auth_gss/gss_krb5_unseal.c | 2 +- net/sunrpc/auth_gss/gss_krb5_wrap.c | 2 +- net/sunrpc/auth_gss/gss_mech_switch.c | 2 +- net/sunrpc/auth_gss/gss_rpc_xdr.h | 2 +- net/sunrpc/auth_gss/svcauth_gss.c | 2 +- net/sunrpc/auth_null.c | 4 +- net/sunrpc/auth_unix.c | 2 +- net/sunrpc/backchannel_rqst.c | 2 +- net/sunrpc/clnt.c | 15 ++- net/sunrpc/debugfs.c | 173 ++++++++++++++++++++++++++++++++ net/sunrpc/rpcb_clnt.c | 2 +- net/sunrpc/sched.c | 4 +- net/sunrpc/sunrpc_syms.c | 12 ++- net/sunrpc/svc.c | 2 +- net/sunrpc/sysctl.c | 2 +- net/sunrpc/xprt.c | 2 +- net/sunrpc/xprtrdma/rpc_rdma.c | 4 +- net/sunrpc/xprtrdma/transport.c | 8 +- net/sunrpc/xprtrdma/verbs.c | 8 +- net/sunrpc/xprtsock.c | 8 +- 38 files changed, 281 insertions(+), 72 deletions(-) create mode 100644 net/sunrpc/debugfs.c
Signature · 1 line
2.1.0
PATCH v2 1/4 lockd: eliminate LOCKD_DEBUG
LOCKD_DEBUG is always the same value as CONFIG_SUNRPC_DEBUG, so we can just use it instead.
--- fs/lockd/svclock.c | 2 +- include/linux/lockd/debug.h | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-)
fs/lockd/svclock.c +1 -1
@@ -53,7 +53,7 @@ static const struct rpc_call_ops nlmsvc_grant_ops;static LIST_HEAD (nlm_blocked);static DEFINE_SPINLOCK (nlm_blocked_lock); -#ifdef LOCKD_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )static const char *nlmdbg_cookie2a (const struct nlm_cookie *cookie) {/*
include/linux/lockd/debug.h +1 -5
@@ -17,12 +17,8 @@* Enable lockd debugging. * Requires RPC_DEBUG. */ -#ifdef RPC_DEBUG -# define LOCKD_DEBUG 1 -#endif -#undef ifdebug -#if defined(RPC_DEBUG ) && defined(LOCKD_DEBUG ) +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define ifdebug (flag) if (unlikely(nlm_debug & NLMDBG_##flag))#else # define ifdebug (flag) if (0)
Signature · 1 line
2.1.0
PATCH v2 2/4 sunrpc: eliminate RPC_DEBUG
In reply to Jeff LaytonIt's always set to whatever CONFIG_SUNRPC_DEBUG is, so just use that.
--- include/linux/sunrpc/auth.h | 2 +- include/linux/sunrpc/debug.h | 9 +++------ include/linux/sunrpc/sched.h | 8 ++++---- include/uapi/linux/nfsd/debug.h | 2 +- net/sunrpc/auth.c | 4 ++-- net/sunrpc/auth_generic.c | 2 +- net/sunrpc/auth_gss/auth_gss.c | 2 +- net/sunrpc/auth_gss/gss_generic_token.c | 2 +- net/sunrpc/auth_gss/gss_krb5_crypto.c | 2 +- net/sunrpc/auth_gss/gss_krb5_keys.c | 2 +- net/sunrpc/auth_gss/gss_krb5_mech.c | 2 +- net/sunrpc/auth_gss/gss_krb5_seal.c | 2 +- net/sunrpc/auth_gss/gss_krb5_seqnum.c | 2 +- net/sunrpc/auth_gss/gss_krb5_unseal.c | 2 +- net/sunrpc/auth_gss/gss_krb5_wrap.c | 2 +- net/sunrpc/auth_gss/gss_mech_switch.c | 2 +- net/sunrpc/auth_gss/gss_rpc_xdr.h | 2 +- net/sunrpc/auth_gss/svcauth_gss.c | 2 +- net/sunrpc/auth_null.c | 4 ++-- net/sunrpc/auth_unix.c | 2 +- net/sunrpc/backchannel_rqst.c | 2 +- net/sunrpc/clnt.c | 6 +++--- net/sunrpc/rpcb_clnt.c | 2 +- net/sunrpc/sched.c | 4 ++-- net/sunrpc/sunrpc_syms.c | 4 ++-- net/sunrpc/svc.c | 2 +- net/sunrpc/sysctl.c | 2 +- net/sunrpc/xprt.c | 2 +- net/sunrpc/xprtrdma/rpc_rdma.c | 4 ++-- net/sunrpc/xprtrdma/transport.c | 8 ++++---- net/sunrpc/xprtrdma/verbs.c | 8 ++++---- net/sunrpc/xprtsock.c | 8 ++++---- 32 files changed, 53 insertions(+), 56 deletions(-)
include/linux/sunrpc/auth.h +1 -1
@@ -53,7 +53,7 @@ struct rpc_cred {struct rcu_head cr_rcu;struct rpc_auth * cr_auth;const struct rpc_credops *cr_ops; -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )unsigned long cr_magic;/* 0x0f4aa4f0 */ #endif unsigned long cr_expire;/* when to gc */
include/linux/sunrpc/debug.h +3 -6
@@ -14,9 +14,6 @@/* * Enable RPC debugging/profiling. */ -#ifdef CONFIG_SUNRPC_DEBUG -#define RPC_DEBUG -#endif #ifdef CONFIG_TRACEPOINTS #define RPC_TRACEPOINTS #endif
@@ -25,7 +22,7 @@/* * Debugging macros etc */ -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )extern unsigned int rpc_debug;extern unsigned int nfs_debug;extern unsigned int nfsd_debug;
@@ -36,7 +33,7 @@ extern unsigned int nlm_debug; #define dprintk_rcu(args...) dfprintk_rcu(FACILITY, ## args)#undef ifdebug -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define ifdebug (fac) if (unlikely(rpc_debug & RPCDBG_##fac)) # define dfprintk(fac, args...) \
@@ -65,7 +62,7 @@ extern unsigned int nlm_debug;/* * Sysctl interface for RPC debugging */ -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )void rpc_register_sysctl (void );void rpc_unregister_sysctl (void );#endif
include/linux/sunrpc/sched.h +4 -4
@@ -79,7 +79,7 @@ struct rpc_task {unsigned short tk_flags;/* misc flags */ unsigned short tk_timeouts;/* maj timeouts */ -#if defined(RPC_DEBUG ) || defined(RPC_TRACEPOINTS ) +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) || defined(RPC_TRACEPOINTS )unsigned short tk_pid;/* debugging aid */ #endif unsigned char tk_priority : 2,/* Task priority */
@@ -187,7 +187,7 @@ struct rpc_wait_queue {unsigned char nr;/* # tasks remaining for cookie */ unsigned short qlen;/* total # tasks waiting in queue */ struct rpc_timer timer_list; -#if defined(RPC_DEBUG ) || defined(RPC_TRACEPOINTS ) +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) || defined(RPC_TRACEPOINTS )const char * name;#endif };
@@ -237,7 +237,7 @@ void rpc_free(void *);int rpciod_up (void );void rpciod_down (void );int __rpc_wait_for_completion_task (struct rpc_task *task,wait_bit_action_f *); -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )struct net ;void rpc_show_tasks (struct net *);#endif
@@ -251,7 +251,7 @@ static inline int rpc_wait_for_completion_task(struct rpc_task *task)return __rpc_wait_for_completion_task (task,NULL ); } -#if defined(RPC_DEBUG ) || defined (RPC_TRACEPOINTS ) +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) || defined (RPC_TRACEPOINTS )static inline const char *rpc_qname (const struct rpc_wait_queue *q) {return ((q && q->name) ? q->name :"unknown" );
include/uapi/linux/nfsd/debug.h +1 -1
@@ -15,7 +15,7 @@* Enable debugging for nfsd. * Requires RPC_DEBUG. */ -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define NFSD_DEBUG 1#endif
net/sunrpc/auth.c +2 -2
@@ -16,7 +16,7 @@#include <linux/sunrpc/gss_api.h> #include <linux/spinlock.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
@@ -646,7 +646,7 @@ rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred, cred->cr_auth = auth; cred->cr_ops = ops; cred->cr_expire = jiffies; -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) cred->cr_magic =RPCAUTH_CRED_MAGIC ;#endif cred->cr_uid = acred->uid;
net/sunrpc/auth_generic.c +1 -1
@@ -14,7 +14,7 @@#include <linux/sunrpc/debug.h> #include <linux/sunrpc/sched.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/auth_gss.c +1 -1
@@ -66,7 +66,7 @@ static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED;#define GSS_KEY_EXPIRE_TIMEO 240static unsigned int gss_key_expire_timeo =GSS_KEY_EXPIRE_TIMEO ; -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/gss_generic_token.c +1 -1
@@ -38,7 +38,7 @@#include <linux/sunrpc/gss_asn1.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/gss_krb5_crypto.c +1 -1
@@ -45,7 +45,7 @@#include <linux/sunrpc/gss_krb5.h> #include <linux/sunrpc/xdr.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/gss_krb5_keys.c +1 -1
@@ -61,7 +61,7 @@#include <linux/sunrpc/xdr.h> #include <linux/lcm.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/gss_krb5_mech.c +1 -1
@@ -45,7 +45,7 @@#include <linux/crypto.h> #include <linux/sunrpc/gss_krb5_enctypes.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/gss_krb5_seal.c +1 -1
@@ -64,7 +64,7 @@#include <linux/random.h> #include <linux/crypto.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/gss_krb5_seqnum.c +1 -1
@@ -35,7 +35,7 @@#include <linux/sunrpc/gss_krb5.h> #include <linux/crypto.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/gss_krb5_unseal.c +1 -1
@@ -62,7 +62,7 @@#include <linux/sunrpc/gss_krb5.h> #include <linux/crypto.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/gss_krb5_wrap.c +1 -1
@@ -35,7 +35,7 @@#include <linux/pagemap.h> #include <linux/crypto.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/gss_mech_switch.c +1 -1
@@ -46,7 +46,7 @@#include <linux/sunrpc/gss_api.h> #include <linux/sunrpc/clnt.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/gss_rpc_xdr.h +1 -1
@@ -25,7 +25,7 @@#include <linux/sunrpc/clnt.h> #include <linux/sunrpc/xprtsock.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/svcauth_gss.c +1 -1
@@ -51,7 +51,7 @@#include "gss_rpc_upcall.h" -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_null.c +2 -2
@@ -10,7 +10,7 @@#include <linux/module.h> #include <linux/sunrpc/clnt.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
@@ -138,7 +138,7 @@ struct rpc_cred null_cred = { .cr_ops = &null_credops, .cr_count = ATOMIC_INIT(1), .cr_flags = 1UL << RPCAUTH_CRED_UPTODATE, -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) .cr_magic = RPCAUTH_CRED_MAGIC,#endif };
net/sunrpc/auth_unix.c +1 -1
@@ -25,7 +25,7 @@ struct unx_cred {#define UNX_WRITESLACK (21 + (UNX_MAXNODENAME >> 2)) -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/backchannel_rqst.c +1 -1
@@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#include <linux/export.h> #include <linux/sunrpc/bc_xprt.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )#define RPCDBG_FACILITY RPCDBG_TRANS#endif
net/sunrpc/clnt.c +3 -3
@@ -42,7 +42,7 @@#include "sunrpc.h" #include "netns.h" -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_CALL#endif
@@ -1396,7 +1396,7 @@ rpc_restart_call(struct rpc_task *task) }EXPORT_SYMBOL_GPL (rpc_restart_call); -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )static const char *rpc_proc_name (const struct rpc_task *task) {const struct rpc_procinfo *proc = task->tk_msg.rpc_proc;
@@ -2421,7 +2421,7 @@ struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int }EXPORT_SYMBOL_GPL (rpc_call_null); -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )static void rpc_show_header (void ) { printk(KERN_INFO "-pid- flgs status -client- --rqstp- "
net/sunrpc/rpcb_clnt.c +1 -1
@@ -32,7 +32,7 @@#include "netns.h" -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_BIND#endif
net/sunrpc/sched.c +2 -2
@@ -24,7 +24,7 @@#include "sunrpc.h" -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )#define RPCDBG_FACILITY RPCDBG_SCHED#endif
@@ -258,7 +258,7 @@ static int rpc_wait_bit_killable(struct wait_bit_key *key)return 0 ; } -#if defined(RPC_DEBUG ) || defined(RPC_TRACEPOINTS ) +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) || defined(RPC_TRACEPOINTS )static void rpc_task_set_debuginfo (struct rpc_task *task) {static atomic_t rpc_pid;
net/sunrpc/sunrpc_syms.c +2 -2
@@ -97,7 +97,7 @@ init_sunrpc(void) err =register_rpc_pipefs ();if (err) goto out4; -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )rpc_register_sysctl ();#endif svc_init_xprt_sock ();/* svc sock transport */
@@ -123,7 +123,7 @@ cleanup_sunrpc(void)unregister_rpc_pipefs ();rpc_destroy_mempool ();unregister_pernet_subsys (&sunrpc_net_ops); -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )rpc_unregister_sysctl ();#endif rcu_barrier ();/* Wait for completion of call_rcu()'s */
net/sunrpc/svc.c +1 -1
@@ -1042,7 +1042,7 @@ static void svc_unregister(const struct svc_serv *serv, struct net *net)/* * dprintk the given error with the address of the client that caused it. */ -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) static __printf(2, 3) void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) {
net/sunrpc/sysctl.c +1 -1
@@ -37,7 +37,7 @@ EXPORT_SYMBOL_GPL(nfsd_debug);unsigned int nlm_debug;EXPORT_SYMBOL_GPL (nlm_debug); -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )static struct ctl_table_header *sunrpc_table_header;static struct ctl_table sunrpc_table[];
net/sunrpc/xprt.c +1 -1
@@ -57,7 +57,7 @@* Local variables */ -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_XPRT#endif
net/sunrpc/xprtrdma/rpc_rdma.c +2 -2
@@ -49,11 +49,11 @@#include <linux/highmem.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_TRANS#endif -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )static const char transfertypes[][12 ] = {"pure inline" ,/* no chunks */ " read chunk", /* some argument via rdma read */
net/sunrpc/xprtrdma/transport.c +4 -4
@@ -55,7 +55,7 @@#include "xprt_rdma.h" -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_TRANS#endif
@@ -75,7 +75,7 @@ static unsigned int xprt_rdma_inline_write_padding;static unsigned int xprt_rdma_memreg_strategy =RPCRDMA_FRMR ;int xprt_rdma_pad_optimize =0 ; -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )static unsigned int min_slot_table_size =RPCRDMA_MIN_SLOT_TABLE ;static unsigned int max_slot_table_size =RPCRDMA_MAX_SLOT_TABLE ;
@@ -705,7 +705,7 @@ static void __exit xprt_rdma_cleanup(void)int rc;dprintk ("RPCRDMA Module Removed, deregister RPC RDMA transport\n" ); -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )if (sunrpc_table_header) {unregister_sysctl_table (sunrpc_table_header); sunrpc_table_header =NULL ;
@@ -736,7 +736,7 @@ static int __init xprt_rdma_init(void)dprintk ("\tPadding %d\n\tMemreg %d\n" , xprt_rdma_inline_write_padding, xprt_rdma_memreg_strategy); -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )if (!sunrpc_table_header) sunrpc_table_header =register_sysctl_table (sunrpc_table);#endif
net/sunrpc/xprtrdma/verbs.c +4 -4
@@ -57,7 +57,7 @@* Globals/Macros */ -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_TRANS#endif
@@ -313,7 +313,7 @@ rpcrdma_flush_cqs(struct rpcrdma_ep *ep)rpcrdma_sendcq_upcall (ep->rep_attr.send_cq, ep); } -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )static const char *const conn[] = {"address resolved" , "address error",
@@ -344,7 +344,7 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event)struct rpcrdma_xprt *xprt = id->context;struct rpcrdma_ia *ia = &xprt->rx_ia;struct rpcrdma_ep *ep = &xprt->rx_ep; -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )struct sockaddr_in *addr = (struct sockaddr_in *) &ep->rep_remote_addr;#endif struct ib_qp_attr attr;
@@ -408,7 +408,7 @@ connected:break ; } -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )if (connstate ==1 ) {int ird = attr.max_dest_rd_atomic;int tird = ep->rep_remote_cma.responder_resources;
net/sunrpc/xprtsock.c +4 -4
@@ -75,7 +75,7 @@ static unsigned int xs_tcp_fin_timeout __read_mostly = XS_TCP_LINGER_TO;* someone else's file names! */ -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )static unsigned int min_slot_table_size =RPC_MIN_SLOT_TABLE ;static unsigned int max_slot_table_size =RPC_MAX_SLOT_TABLE ;
@@ -186,7 +186,7 @@ static struct ctl_table sunrpc_table[] = {*/ #define XS_IDLE_DISC_TO (5U * 60 * HZ) -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# undef RPC_DEBUG_DATA# define RPCDBG_FACILITY RPCDBG_TRANS#endif
@@ -2991,7 +2991,7 @@ static struct xprt_class xs_bc_tcp_transport = {*/ int init_socket_xprt (void ) { -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )if (!sunrpc_table_header) sunrpc_table_header =register_sysctl_table (sunrpc_table);#endif
@@ -3010,7 +3010,7 @@ int init_socket_xprt(void)*/ void cleanup_socket_xprt (void ) { -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )if (sunrpc_table_header) {unregister_sysctl_table (sunrpc_table_header); sunrpc_table_header =NULL ;
Signature · 1 line
2.1.0
PATCH v2 3/4 sunrpc: eliminate RPC_TRACEPOINTS
In reply to Jeff LaytonIt's always set to the same value as CONFIG_TRACEPOINTS, so we can just use that instead.
--- include/linux/sunrpc/debug.h | 9 --------- include/linux/sunrpc/sched.h | 6 +++--- net/sunrpc/sched.c | 2 +- 3 files changed, 4 insertions(+), 13 deletions(-)
include/linux/sunrpc/debug.h +0 -9
@@ -10,15 +10,6 @@#include <uapi/linux/sunrpc/debug.h> - -/* -* Enable RPC debugging/profiling. -*/ -#ifdef CONFIG_TRACEPOINTS -#define RPC_TRACEPOINTS -#endif -/* #define RPC_PROFILE */ -/* * Debugging macros etc */
include/linux/sunrpc/sched.h +3 -3
@@ -79,7 +79,7 @@ struct rpc_task {unsigned short tk_flags;/* misc flags */ unsigned short tk_timeouts;/* maj timeouts */ -#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) || defined(RPC_TRACEPOINTS ) +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) ||IS_ENABLED (CONFIG_TRACEPOINTS )unsigned short tk_pid;/* debugging aid */ #endif unsigned char tk_priority : 2,/* Task priority */
@@ -187,7 +187,7 @@ struct rpc_wait_queue {unsigned char nr;/* # tasks remaining for cookie */ unsigned short qlen;/* total # tasks waiting in queue */ struct rpc_timer timer_list; -#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) || defined(RPC_TRACEPOINTS ) +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) ||IS_ENABLED (CONFIG_TRACEPOINTS )const char * name;#endif };
@@ -251,7 +251,7 @@ static inline int rpc_wait_for_completion_task(struct rpc_task *task)return __rpc_wait_for_completion_task (task,NULL ); } -#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) || defined (RPC_TRACEPOINTS ) +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) ||IS_ENABLED (CONFIG_TRACEPOINTS )static inline const char *rpc_qname (const struct rpc_wait_queue *q) {return ((q && q->name) ? q->name :"unknown" );
net/sunrpc/sched.c +1 -1
@@ -258,7 +258,7 @@ static int rpc_wait_bit_killable(struct wait_bit_key *key)return 0 ; } -#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) || defined(RPC_TRACEPOINTS ) +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) ||IS_ENABLED (CONFIG_TRACEPOINTS )static void rpc_task_set_debuginfo (struct rpc_task *task) {static atomic_t rpc_pid;
Signature · 1 line
2.1.0
PATCH v2 4/4 sunrpc: add debugfs file for displaying client rpc_task queue
In reply to Jeff LaytonIt's possible to get a dump of the RPC task queue by writing a value to /proc/sys/sunrpc/rpc_debug. If you write any value to that file, you get a dump of the RPC client task list into the log buffer. This is a rather inconvenient interface however, and makes it hard to get immediate info about the task queue.
Add a new directory hierarchy under debugfs:
sunrpc/
rpc_clnt/
<clientid>/Within each clientid directory we create a new "tasks" file that will dump info similar to what shows up in the log buffer, but with a few small differences -- we avoid printing raw kernel addresses in favor of symbolic names and the XID is also displayed.
--- include/linux/sunrpc/clnt.h | 4 + include/linux/sunrpc/debug.h | 31 ++++++++ net/sunrpc/Kconfig | 1 + net/sunrpc/Makefile | 1 + net/sunrpc/clnt.c | 9 ++- net/sunrpc/debugfs.c | 173 +++++++++++++++++++++++++++++++++++++++++++ net/sunrpc/sunrpc_syms.c | 8 ++ 7 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 net/sunrpc/debugfs.c
include/linux/sunrpc/clnt.h +4 -0
@@ -63,6 +63,9 @@ struct rpc_clnt {struct rpc_rtt cl_rtt_default;struct rpc_timeout cl_timeout_default;const struct rpc_program *cl_program; +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) +struct dentry *cl_debugfs;/* debugfs directory */ +#endif };/*
@@ -176,5 +179,6 @@ size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);const char *rpc_peeraddr2str (struct rpc_clnt *,enum rpc_display_format_t );int rpc_localaddr (struct rpc_clnt *,struct sockaddr *,size_t ); +const char *rpc_proc_name (const struct rpc_task *task);#endif /* __KERNEL__ */ #endif /* _LINUX_SUNRPC_CLNT_H */
include/linux/sunrpc/debug.h +31 -0
@@ -53,9 +53,40 @@ extern unsigned int nlm_debug;/* * Sysctl interface for RPC debugging */ + +struct rpc_clnt ; +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )void rpc_register_sysctl (void );void rpc_unregister_sysctl (void ); +int sunrpc_debugfs_init (void ); +void sunrpc_debugfs_exit (void ); +int rpc_clnt_debugfs_register (struct rpc_clnt *); +void rpc_clnt_debugfs_unregister (struct rpc_clnt *); +#else +static inline int +sunrpc_debugfs_init (void ) +{ +return 0 ; +} + +static inline void +sunrpc_debugfs_exit (void ) +{ +return ; +} + +static inline int +rpc_clnt_debugfs_register (struct rpc_clnt *clnt) +{ +return 0 ; +} + +static inline void +rpc_clnt_debugfs_unregister (struct rpc_clnt *clnt) +{ +return ; +}#endif #endif /* _LINUX_SUNRPC_DEBUG_H_ */
net/sunrpc/Kconfig +1 -0
@@ -35,6 +35,7 @@ config RPCSEC_GSS_KRB5 config SUNRPC_DEBUG bool "RPC: Enable dprintk debugging" depends on SUNRPC && SYSCTL + select DEBUG_FS help This option enables a sysctl-based debugging interface that is be used by the 'rpcdebug' utility to turn on or off
net/sunrpc/Makefile +1 -0
@@ -14,6 +14,7 @@ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ addr.o rpcb_clnt.o timer.o xdr.o \ sunrpc_syms.o cache.o rpc_pipe.o \ svc_xprt.o +sunrpc-$(CONFIG_SUNRPC_DEBUG) += debugfs.o sunrpc-$(CONFIG_SUNRPC_BACKCHANNEL) += backchannel_rqst.o bc_svc.o sunrpc-$(CONFIG_PROC_FS) += stats.o sunrpc-$(CONFIG_SYSCTL) += sysctl.o
net/sunrpc/clnt.c +8 -1
@@ -305,6 +305,10 @@ static int rpc_client_register(struct rpc_clnt *clnt,struct super_block *pipefs_sb;int err; + err =rpc_clnt_debugfs_register (clnt); +if (err) +return err; + pipefs_sb =rpc_get_sb_net (net);if (pipefs_sb) { err =rpc_setup_pipedir (pipefs_sb, clnt);
@@ -331,6 +335,7 @@ err_auth: out:if (pipefs_sb)rpc_put_sb_net (net); +rpc_clnt_debugfs_unregister (clnt);return err; }
@@ -771,6 +776,7 @@ rpc_free_client(struct rpc_clnt *clnt) rcu_dereference(clnt->cl_xprt)->servername);if (clnt->cl_parent != clnt) parent = clnt->cl_parent; +rpc_clnt_debugfs_unregister (clnt);rpc_clnt_remove_pipedir (clnt);rpc_unregister_client (clnt);rpc_free_iostats (clnt->cl_metrics);
@@ -1397,7 +1403,8 @@ rpc_restart_call(struct rpc_task *task)EXPORT_SYMBOL_GPL (rpc_restart_call);#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) -static const char *rpc_proc_name (const struct rpc_task *task) +const char +*rpc_proc_name (const struct rpc_task *task) {const struct rpc_procinfo *proc = task->tk_msg.rpc_proc;
net/sunrpc/debugfs.c new file +173 -0
173 lines not on this page · raw message
net/sunrpc/sunrpc_syms.c +8 -0
@@ -97,6 +97,11 @@ init_sunrpc(void) err =register_rpc_pipefs ();if (err) goto out4; + + err =sunrpc_debugfs_init (); +if (err) + goto out5; +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )rpc_register_sysctl ();#endif
@@ -104,6 +109,8 @@ init_sunrpc(void)init_socket_xprt ();/* clnt sock transport */ return 0 ; +out5: +unregister_rpc_pipefs (); out4:unregister_pernet_subsys (&sunrpc_net_ops); out3:
@@ -120,6 +127,7 @@ cleanup_sunrpc(void)rpcauth_remove_module ();cleanup_socket_xprt ();svc_cleanup_xprt_sock (); +sunrpc_debugfs_exit ();unregister_rpc_pipefs ();rpc_destroy_mempool ();unregister_pernet_subsys (&sunrpc_net_ops);
Signature · 1 line
2.1.0
Quoted 263 lines · On Tue, 25 Nov 2014 14:01:00 -0500 Jeff Layton <[email protected]> wrote:
It's possible to get a dump of the RPC task queue by writing a value to
/proc/sys/sunrpc/rpc_debug. If you write any value to that file, you get a dump of the RPC client task list into the log buffer. This is a rather inconvenient interface however, and makes it hard to get immediate info about the task queue.Add a new directory hierarchy under debugfs:
sunrpc/ rpc_clnt/ <clientid>/Within each clientid directory we create a new "tasks" file that will dump info similar to what shows up in the log buffer, but with a few small differences -- we avoid printing raw kernel addresses in favor of symbolic names and the XID is also displayed.
Signed-off-by Jeff Layton <[email protected]>--- include/linux/sunrpc/clnt.h | 4 + include/linux/sunrpc/debug.h | 31 ++++++++ net/sunrpc/Kconfig | 1 + net/sunrpc/Makefile | 1 + net/sunrpc/clnt.c | 9 ++- net/sunrpc/debugfs.c | 173 +++++++++++++++++++++++++++++++++++++++++++ net/sunrpc/sunrpc_syms.c | 8 ++ 7 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 net/sunrpc/debugfs.cinclude/linux/sunrpc/clnt.h +4
-0@@ -63,6 +63,9 @@ struct rpc_clnt {struct rpc_rtt cl_rtt_default;struct rpc_timeout cl_timeout_default;const struct rpc_program *cl_program; +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) +struct dentry *cl_debugfs;/* debugfs directory */ +#endif };/* @@ -176,5 +179,6 @@ size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);const char *rpc_peeraddr2str (struct rpc_clnt *,enum rpc_display_format_t );int rpc_localaddr (struct rpc_clnt *,struct sockaddr *,size_t ); +const char *rpc_proc_name (const struct rpc_task *task);#endif /* __KERNEL__ */ #endif /* _LINUX_SUNRPC_CLNT_H */ include/linux/sunrpc/debug.h +31
-0@@ -53,9 +53,40 @@ extern unsigned int nlm_debug;/* * Sysctl interface for RPC debugging */ + +struct rpc_clnt ; +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )void rpc_register_sysctl (void );void rpc_unregister_sysctl (void ); +int sunrpc_debugfs_init (void ); +void sunrpc_debugfs_exit (void ); +int rpc_clnt_debugfs_register (struct rpc_clnt *); +void rpc_clnt_debugfs_unregister (struct rpc_clnt *); +#else +static inline int +sunrpc_debugfs_init (void ) +{ +return 0 ; +} + +static inline void +sunrpc_debugfs_exit (void ) +{ +return ; +} + +static inline int +rpc_clnt_debugfs_register (struct rpc_clnt *clnt) +{ +return 0 ; +} + +static inline void +rpc_clnt_debugfs_unregister (struct rpc_clnt *clnt) +{ +return ; +}#endif #endif /* _LINUX_SUNRPC_DEBUG_H_ */ net/sunrpc/Kconfig +1
-0@@ -35,6 +35,7 @@ config RPCSEC_GSS_KRB5 config SUNRPC_DEBUG bool "RPC: Enable dprintk debugging" depends on SUNRPC && SYSCTL + select DEBUG_FS help This option enables a sysctl-based debugging interface that is be used by the 'rpcdebug' utility to turn on or offnet/sunrpc/Makefile +1
-0@@ -14,6 +14,7 @@ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ addr.o rpcb_clnt.o timer.o xdr.o \ sunrpc_syms.o cache.o rpc_pipe.o \ svc_xprt.o +sunrpc-$(CONFIG_SUNRPC_DEBUG) += debugfs.o sunrpc-$(CONFIG_SUNRPC_BACKCHANNEL) += backchannel_rqst.o bc_svc.o sunrpc-$(CONFIG_PROC_FS) += stats.o sunrpc-$(CONFIG_SYSCTL) += sysctl.onet/sunrpc/clnt.c +8
-1@@ -305,6 +305,10 @@ static int rpc_client_register(struct rpc_clnt *clnt,struct super_block *pipefs_sb;int err; + err =rpc_clnt_debugfs_register (clnt); +if (err) +return err; + pipefs_sb =rpc_get_sb_net (net);if (pipefs_sb) { err =rpc_setup_pipedir (pipefs_sb, clnt);@@ -331,6 +335,7 @@ err_auth: out:if (pipefs_sb)rpc_put_sb_net (net); +rpc_clnt_debugfs_unregister (clnt);return err; }@@ -771,6 +776,7 @@ rpc_free_client(struct rpc_clnt *clnt) rcu_dereference(clnt->cl_xprt)->servername);if (clnt->cl_parent != clnt) parent = clnt->cl_parent; +rpc_clnt_debugfs_unregister (clnt);rpc_clnt_remove_pipedir (clnt);rpc_unregister_client (clnt);rpc_free_iostats (clnt->cl_metrics);@@ -1397,7 +1403,8 @@ rpc_restart_call(struct rpc_task *task)EXPORT_SYMBOL_GPL (rpc_restart_call);#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) -static const char *rpc_proc_name (const struct rpc_task *task) +const char +*rpc_proc_name (const struct rpc_task *task) {const struct rpc_procinfo *proc = task->tk_msg.rpc_proc;net/sunrpc/debugfs.c new file +97
-0@@ -0,0 +1,173 @@ +/** +* debugfs interface for sunrpc +* +* (c) 2014 Jeff Layton <[email protected]> +*/ + +#include <linux/debugfs.h> +#include <linux/sunrpc/sched.h> +#include <linux/sunrpc/clnt.h> +#include "netns.h" + +static struct dentry *topdir; +static struct dentry *rpc_clnt_dir; + +struct rpc_clnt_iter { +struct rpc_clnt *clnt; +loff_t pos; +}; + +static int +tasks_show (struct seq_file *f,void *v) +{ +u32 xid =0 ; +struct rpc_task *task = v; +struct rpc_clnt *clnt = task->tk_client; +const char *rpc_waitq ="none" ; + +if (RPC_IS_QUEUED (task)) + rpc_waitq =rpc_qname (task->tk_waitqueue); + +if (task->tk_rqstp) + xid =be32_to_cpu (task->tk_rqstp->rq_xid); + +seq_printf (f,"%5u %04x %6d 0x%x 0x%x %8ld %ps %sv%u %s a:%ps q:%s\n" , + task->tk_pid, task->tk_flags, task->tk_status, + clnt->cl_clid, xid, task->tk_timeout, task->tk_ops, + clnt->cl_program->name, clnt->cl_vers,rpc_proc_name (task), + task->tk_action, rpc_waitq); +return 0 ; +} + +static void * +tasks_start (struct seq_file *f,loff_t *ppos) + __acquires(&clnt->cl_lock) +{ +struct rpc_clnt_iter *iter = f->private; +loff_t pos = *ppos; +struct rpc_clnt *clnt = iter->clnt; +struct rpc_task *task; + + iter->pos = pos +1 ; +spin_lock (&clnt->cl_lock); +list_for_each_entry (task, &clnt->cl_tasks, tk_task) +if (pos-- ==0 ) +return task; +return NULL ; +} + +static void * +tasks_next (struct seq_file *f,void *v,loff_t *pos) +{ +struct rpc_clnt_iter *iter = f->private; +struct rpc_clnt *clnt = iter->clnt; +struct rpc_task *task = v; +struct list_head *next = task->tk_task.next; + + ++iter->pos; + ++*pos; + +/* If there's another task on list, return it */ +if (next == &clnt->cl_tasks) +return NULL ; + return list_entry(next, struct rpc_task, tk_task); +} + +static void +tasks_stop (struct seq_file *f,void *v) + __releases(&clnt->cl_lock) +{ +struct rpc_clnt_iter *iter = f->private; +struct rpc_clnt *clnt = iter->clnt; + +spin_unlock (&clnt->cl_lock); +} + +static const struct seq_operations tasks_seq_operations = { + .start = tasks_start, + .next = tasks_next, + .stop = tasks_stop, + .show = tasks_show, +}; + +static int tasks_open (struct inode *inode,struct file *filp) +{ +int ret =seq_open_private (filp, &tasks_seq_operations, +sizeof (struct rpc_clnt_iter )); +
net/sunrpc/debugfs.c line 107
Quoted 10 lines
net/sunrpc/debugfs.c new file +10
-0+if (ret ==0 ) { +struct seq_file *seq = filp->private_data; +struct rpc_clnt_iter *iter = seq->private; + + iter->clnt = inode->i_private; + } + +return ret; +} +
Hmm...it occurs to me that we probably need to take a reference to the clnt in the above function to ensure that it doesn't vanish until the file is closed.
Let me fix that and resend before you merge this...
Quoted 99 lines
net/sunrpc/debugfs.c new file +66
-0+static const struct file_operations tasks_fops = { + .owner =THIS_MODULE , + .open = tasks_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + +int +rpc_clnt_debugfs_register (struct rpc_clnt *clnt) +{ +char name[9 ];/* 8 for hex digits + NULL terminator */ + +/* Already registered? */ +if (clnt->cl_debugfs) +return 0 ; + +snprintf (name,sizeof (name),"%8.8x" , clnt->cl_clid); + +/* make the per-client dir */ + clnt->cl_debugfs =debugfs_create_dir (name, rpc_clnt_dir); +if (!clnt->cl_debugfs) +return -ENOMEM ; + +/* make tasks file */ +if (!debugfs_create_file ("tasks" ,S_IFREG |S_IRUSR , clnt->cl_debugfs, + clnt, &tasks_fops)) { +debugfs_remove_recursive (clnt->cl_debugfs); + clnt->cl_debugfs =NULL ; +return -ENOMEM ; + } + +return 0 ; +} + +void +rpc_clnt_debugfs_unregister (struct rpc_clnt *clnt) +{ +debugfs_remove_recursive (clnt->cl_debugfs); + clnt->cl_debugfs =NULL ; +} + +void __exit +sunrpc_debugfs_exit (void ) +{ +debugfs_remove_recursive (topdir); +} + +int __init +sunrpc_debugfs_init (void ) +{ + topdir =debugfs_create_dir ("sunrpc" ,NULL ); +if (!topdir) + goto out; + + rpc_clnt_dir =debugfs_create_dir ("rpc_clnt" , topdir); +if (!rpc_clnt_dir) + goto out_remove; + +return 0 ; +out_remove: +debugfs_remove_recursive (topdir); + topdir =NULL ; +out: +return -ENOMEM ; +}net/sunrpc/sunrpc_syms.c +8
-0@@ -97,6 +97,11 @@ init_sunrpc(void) err =register_rpc_pipefs ();if (err) goto out4; + + err =sunrpc_debugfs_init (); +if (err) + goto out5; +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )rpc_register_sysctl ();#endif @@ -104,6 +109,8 @@ init_sunrpc(void)init_socket_xprt ();/* clnt sock transport */ return 0 ; +out5: +unregister_rpc_pipefs (); out4:unregister_pernet_subsys (&sunrpc_net_ops); out3:@@ -120,6 +127,7 @@ cleanup_sunrpc(void)rpcauth_remove_module ();cleanup_socket_xprt ();svc_cleanup_xprt_sock (); +sunrpc_debugfs_exit ();unregister_rpc_pipefs ();rpc_destroy_mempool ();unregister_pernet_subsys (&sunrpc_net_ops);
Signature · 1 line
Jeff Layton <[email protected]>
v3 cover sunrpc: add some debugfs files for dumping task and xprt info
In reply to Jeff Laytonv3:
- add a patch that creates and populates a rpc_xprt directory
- take reference on rpc_clnt when "tasks" file is opened
- minor cleanups
v2:
- add a whole new directory hierarchy instead of a single client_tasks file
- respin patches to remove LOCKD_DEBUG/RPC_DEBUG/RPC_TRACEPOINTS defines
Ok, here is the latest (and hopefully last!) respin of the patches to add some debugfs files to dump info about rpc_clnt and rpc_xprt objects.
This set ensures that references are properly acquired so that the objects don't disappear while we're working on them. I've also included the patches to eliminate the RPC_DEBUG defines too as they should be merged first to prevent conflicts.
Trond, can you consider these for v3.19?
Thanks!
Jeff Layton (5):
lockd: eliminate LOCKD_DEBUG
sunrpc: eliminate RPC_DEBUG
sunrpc: eliminate RPC_TRACEPOINTS
sunrpc: add debugfs file for displaying client rpc_task queue
sunrpc: add a debugfs rpc_xprt directory with an info file in it
fs/lockd/svclock.c | 2 +- include/linux/lockd/debug.h | 6 +- include/linux/sunrpc/auth.h | 2 +- include/linux/sunrpc/clnt.h | 4 + include/linux/sunrpc/debug.h | 64 +++++-- include/linux/sunrpc/sched.h | 8 +- include/linux/sunrpc/xprt.h | 3 + include/uapi/linux/nfsd/debug.h | 2 +- net/sunrpc/Kconfig | 1 + net/sunrpc/Makefile | 1 + net/sunrpc/auth.c | 4 +- net/sunrpc/auth_generic.c | 2 +- net/sunrpc/auth_gss/auth_gss.c | 2 +- net/sunrpc/auth_gss/gss_generic_token.c | 2 +- net/sunrpc/auth_gss/gss_krb5_crypto.c | 2 +- net/sunrpc/auth_gss/gss_krb5_keys.c | 2 +- net/sunrpc/auth_gss/gss_krb5_mech.c | 2 +- net/sunrpc/auth_gss/gss_krb5_seal.c | 2 +- net/sunrpc/auth_gss/gss_krb5_seqnum.c | 2 +- net/sunrpc/auth_gss/gss_krb5_unseal.c | 2 +- net/sunrpc/auth_gss/gss_krb5_wrap.c | 2 +- net/sunrpc/auth_gss/gss_mech_switch.c | 2 +- net/sunrpc/auth_gss/gss_rpc_xdr.h | 2 +- net/sunrpc/auth_gss/svcauth_gss.c | 2 +- net/sunrpc/auth_null.c | 4 +- net/sunrpc/auth_unix.c | 2 +- net/sunrpc/backchannel_rqst.c | 2 +- net/sunrpc/clnt.c | 16 +- net/sunrpc/debugfs.c | 292 ++++++++++++++++++++++++++++++++ net/sunrpc/rpcb_clnt.c | 2 +- net/sunrpc/sched.c | 4 +- net/sunrpc/sunrpc_syms.c | 12 +- net/sunrpc/svc.c | 2 +- net/sunrpc/sysctl.c | 2 +- net/sunrpc/xprt.c | 10 +- net/sunrpc/xprtrdma/rpc_rdma.c | 4 +- net/sunrpc/xprtrdma/transport.c | 8 +- net/sunrpc/xprtrdma/verbs.c | 8 +- net/sunrpc/xprtsock.c | 8 +- 39 files changed, 427 insertions(+), 72 deletions(-) create mode 100644 net/sunrpc/debugfs.c
Signature · 1 line
2.1.0
PATCH v3 1/5 lockd: eliminate LOCKD_DEBUG
LOCKD_DEBUG is always the same value as CONFIG_SUNRPC_DEBUG, so we can just use it instead.
--- fs/lockd/svclock.c | 2 +- include/linux/lockd/debug.h | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-)
fs/lockd/svclock.c +1 -1
@@ -53,7 +53,7 @@ static const struct rpc_call_ops nlmsvc_grant_ops;static LIST_HEAD (nlm_blocked);static DEFINE_SPINLOCK (nlm_blocked_lock); -#ifdef LOCKD_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )static const char *nlmdbg_cookie2a (const struct nlm_cookie *cookie) {/*
include/linux/lockd/debug.h +1 -5
@@ -17,12 +17,8 @@* Enable lockd debugging. * Requires RPC_DEBUG. */ -#ifdef RPC_DEBUG -# define LOCKD_DEBUG 1 -#endif -#undef ifdebug -#if defined(RPC_DEBUG ) && defined(LOCKD_DEBUG ) +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define ifdebug (flag) if (unlikely(nlm_debug & NLMDBG_##flag))#else # define ifdebug (flag) if (0)
Signature · 1 line
2.1.0
PATCH v3 2/5 sunrpc: eliminate RPC_DEBUG
In reply to Jeff LaytonIt's always set to whatever CONFIG_SUNRPC_DEBUG is, so just use that.
--- include/linux/sunrpc/auth.h | 2 +- include/linux/sunrpc/debug.h | 9 +++------ include/linux/sunrpc/sched.h | 8 ++++---- include/uapi/linux/nfsd/debug.h | 2 +- net/sunrpc/auth.c | 4 ++-- net/sunrpc/auth_generic.c | 2 +- net/sunrpc/auth_gss/auth_gss.c | 2 +- net/sunrpc/auth_gss/gss_generic_token.c | 2 +- net/sunrpc/auth_gss/gss_krb5_crypto.c | 2 +- net/sunrpc/auth_gss/gss_krb5_keys.c | 2 +- net/sunrpc/auth_gss/gss_krb5_mech.c | 2 +- net/sunrpc/auth_gss/gss_krb5_seal.c | 2 +- net/sunrpc/auth_gss/gss_krb5_seqnum.c | 2 +- net/sunrpc/auth_gss/gss_krb5_unseal.c | 2 +- net/sunrpc/auth_gss/gss_krb5_wrap.c | 2 +- net/sunrpc/auth_gss/gss_mech_switch.c | 2 +- net/sunrpc/auth_gss/gss_rpc_xdr.h | 2 +- net/sunrpc/auth_gss/svcauth_gss.c | 2 +- net/sunrpc/auth_null.c | 4 ++-- net/sunrpc/auth_unix.c | 2 +- net/sunrpc/backchannel_rqst.c | 2 +- net/sunrpc/clnt.c | 6 +++--- net/sunrpc/rpcb_clnt.c | 2 +- net/sunrpc/sched.c | 4 ++-- net/sunrpc/sunrpc_syms.c | 4 ++-- net/sunrpc/svc.c | 2 +- net/sunrpc/sysctl.c | 2 +- net/sunrpc/xprt.c | 2 +- net/sunrpc/xprtrdma/rpc_rdma.c | 4 ++-- net/sunrpc/xprtrdma/transport.c | 8 ++++---- net/sunrpc/xprtrdma/verbs.c | 8 ++++---- net/sunrpc/xprtsock.c | 8 ++++---- 32 files changed, 53 insertions(+), 56 deletions(-)
include/linux/sunrpc/auth.h +1 -1
@@ -53,7 +53,7 @@ struct rpc_cred {struct rcu_head cr_rcu;struct rpc_auth * cr_auth;const struct rpc_credops *cr_ops; -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )unsigned long cr_magic;/* 0x0f4aa4f0 */ #endif unsigned long cr_expire;/* when to gc */
include/linux/sunrpc/debug.h +3 -6
@@ -14,9 +14,6 @@/* * Enable RPC debugging/profiling. */ -#ifdef CONFIG_SUNRPC_DEBUG -#define RPC_DEBUG -#endif #ifdef CONFIG_TRACEPOINTS #define RPC_TRACEPOINTS #endif
@@ -25,7 +22,7 @@/* * Debugging macros etc */ -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )extern unsigned int rpc_debug;extern unsigned int nfs_debug;extern unsigned int nfsd_debug;
@@ -36,7 +33,7 @@ extern unsigned int nlm_debug; #define dprintk_rcu(args...) dfprintk_rcu(FACILITY, ## args)#undef ifdebug -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define ifdebug (fac) if (unlikely(rpc_debug & RPCDBG_##fac)) # define dfprintk(fac, args...) \
@@ -65,7 +62,7 @@ extern unsigned int nlm_debug;/* * Sysctl interface for RPC debugging */ -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )void rpc_register_sysctl (void );void rpc_unregister_sysctl (void );#endif
include/linux/sunrpc/sched.h +4 -4
@@ -79,7 +79,7 @@ struct rpc_task {unsigned short tk_flags;/* misc flags */ unsigned short tk_timeouts;/* maj timeouts */ -#if defined(RPC_DEBUG ) || defined(RPC_TRACEPOINTS ) +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) || defined(RPC_TRACEPOINTS )unsigned short tk_pid;/* debugging aid */ #endif unsigned char tk_priority : 2,/* Task priority */
@@ -187,7 +187,7 @@ struct rpc_wait_queue {unsigned char nr;/* # tasks remaining for cookie */ unsigned short qlen;/* total # tasks waiting in queue */ struct rpc_timer timer_list; -#if defined(RPC_DEBUG ) || defined(RPC_TRACEPOINTS ) +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) || defined(RPC_TRACEPOINTS )const char * name;#endif };
@@ -237,7 +237,7 @@ void rpc_free(void *);int rpciod_up (void );void rpciod_down (void );int __rpc_wait_for_completion_task (struct rpc_task *task,wait_bit_action_f *); -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )struct net ;void rpc_show_tasks (struct net *);#endif
@@ -251,7 +251,7 @@ static inline int rpc_wait_for_completion_task(struct rpc_task *task)return __rpc_wait_for_completion_task (task,NULL ); } -#if defined(RPC_DEBUG ) || defined (RPC_TRACEPOINTS ) +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) || defined (RPC_TRACEPOINTS )static inline const char *rpc_qname (const struct rpc_wait_queue *q) {return ((q && q->name) ? q->name :"unknown" );
include/uapi/linux/nfsd/debug.h +1 -1
@@ -15,7 +15,7 @@* Enable debugging for nfsd. * Requires RPC_DEBUG. */ -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define NFSD_DEBUG 1#endif
net/sunrpc/auth.c +2 -2
@@ -16,7 +16,7 @@#include <linux/sunrpc/gss_api.h> #include <linux/spinlock.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
@@ -646,7 +646,7 @@ rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred, cred->cr_auth = auth; cred->cr_ops = ops; cred->cr_expire = jiffies; -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) cred->cr_magic =RPCAUTH_CRED_MAGIC ;#endif cred->cr_uid = acred->uid;
net/sunrpc/auth_generic.c +1 -1
@@ -14,7 +14,7 @@#include <linux/sunrpc/debug.h> #include <linux/sunrpc/sched.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/auth_gss.c +1 -1
@@ -66,7 +66,7 @@ static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED;#define GSS_KEY_EXPIRE_TIMEO 240static unsigned int gss_key_expire_timeo =GSS_KEY_EXPIRE_TIMEO ; -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/gss_generic_token.c +1 -1
@@ -38,7 +38,7 @@#include <linux/sunrpc/gss_asn1.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/gss_krb5_crypto.c +1 -1
@@ -45,7 +45,7 @@#include <linux/sunrpc/gss_krb5.h> #include <linux/sunrpc/xdr.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/gss_krb5_keys.c +1 -1
@@ -61,7 +61,7 @@#include <linux/sunrpc/xdr.h> #include <linux/lcm.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/gss_krb5_mech.c +1 -1
@@ -45,7 +45,7 @@#include <linux/crypto.h> #include <linux/sunrpc/gss_krb5_enctypes.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/gss_krb5_seal.c +1 -1
@@ -64,7 +64,7 @@#include <linux/random.h> #include <linux/crypto.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/gss_krb5_seqnum.c +1 -1
@@ -35,7 +35,7 @@#include <linux/sunrpc/gss_krb5.h> #include <linux/crypto.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/gss_krb5_unseal.c +1 -1
@@ -62,7 +62,7 @@#include <linux/sunrpc/gss_krb5.h> #include <linux/crypto.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/gss_krb5_wrap.c +1 -1
@@ -35,7 +35,7 @@#include <linux/pagemap.h> #include <linux/crypto.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/gss_mech_switch.c +1 -1
@@ -46,7 +46,7 @@#include <linux/sunrpc/gss_api.h> #include <linux/sunrpc/clnt.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/gss_rpc_xdr.h +1 -1
@@ -25,7 +25,7 @@#include <linux/sunrpc/clnt.h> #include <linux/sunrpc/xprtsock.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_gss/svcauth_gss.c +1 -1
@@ -51,7 +51,7 @@#include "gss_rpc_upcall.h" -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/auth_null.c +2 -2
@@ -10,7 +10,7 @@#include <linux/module.h> #include <linux/sunrpc/clnt.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
@@ -138,7 +138,7 @@ struct rpc_cred null_cred = { .cr_ops = &null_credops, .cr_count = ATOMIC_INIT(1), .cr_flags = 1UL << RPCAUTH_CRED_UPTODATE, -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) .cr_magic = RPCAUTH_CRED_MAGIC,#endif };
net/sunrpc/auth_unix.c +1 -1
@@ -25,7 +25,7 @@ struct unx_cred {#define UNX_WRITESLACK (21 + (UNX_MAXNODENAME >> 2)) -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_AUTH#endif
net/sunrpc/backchannel_rqst.c +1 -1
@@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#include <linux/export.h> #include <linux/sunrpc/bc_xprt.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )#define RPCDBG_FACILITY RPCDBG_TRANS#endif
net/sunrpc/clnt.c +3 -3
@@ -42,7 +42,7 @@#include "sunrpc.h" #include "netns.h" -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_CALL#endif
@@ -1396,7 +1396,7 @@ rpc_restart_call(struct rpc_task *task) }EXPORT_SYMBOL_GPL (rpc_restart_call); -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )static const char *rpc_proc_name (const struct rpc_task *task) {const struct rpc_procinfo *proc = task->tk_msg.rpc_proc;
@@ -2421,7 +2421,7 @@ struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int }EXPORT_SYMBOL_GPL (rpc_call_null); -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )static void rpc_show_header (void ) { printk(KERN_INFO "-pid- flgs status -client- --rqstp- "
net/sunrpc/rpcb_clnt.c +1 -1
@@ -32,7 +32,7 @@#include "netns.h" -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_BIND#endif
net/sunrpc/sched.c +2 -2
@@ -24,7 +24,7 @@#include "sunrpc.h" -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )#define RPCDBG_FACILITY RPCDBG_SCHED#endif
@@ -258,7 +258,7 @@ static int rpc_wait_bit_killable(struct wait_bit_key *key)return 0 ; } -#if defined(RPC_DEBUG ) || defined(RPC_TRACEPOINTS ) +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) || defined(RPC_TRACEPOINTS )static void rpc_task_set_debuginfo (struct rpc_task *task) {static atomic_t rpc_pid;
net/sunrpc/sunrpc_syms.c +2 -2
@@ -97,7 +97,7 @@ init_sunrpc(void) err =register_rpc_pipefs ();if (err) goto out4; -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )rpc_register_sysctl ();#endif svc_init_xprt_sock ();/* svc sock transport */
@@ -123,7 +123,7 @@ cleanup_sunrpc(void)unregister_rpc_pipefs ();rpc_destroy_mempool ();unregister_pernet_subsys (&sunrpc_net_ops); -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )rpc_unregister_sysctl ();#endif rcu_barrier ();/* Wait for completion of call_rcu()'s */
net/sunrpc/svc.c +1 -1
@@ -1042,7 +1042,7 @@ static void svc_unregister(const struct svc_serv *serv, struct net *net)/* * dprintk the given error with the address of the client that caused it. */ -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) static __printf(2, 3) void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) {
net/sunrpc/sysctl.c +1 -1
@@ -37,7 +37,7 @@ EXPORT_SYMBOL_GPL(nfsd_debug);unsigned int nlm_debug;EXPORT_SYMBOL_GPL (nlm_debug); -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )static struct ctl_table_header *sunrpc_table_header;static struct ctl_table sunrpc_table[];
net/sunrpc/xprt.c +1 -1
@@ -57,7 +57,7 @@* Local variables */ -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_XPRT#endif
net/sunrpc/xprtrdma/rpc_rdma.c +2 -2
@@ -49,11 +49,11 @@#include <linux/highmem.h> -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_TRANS#endif -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )static const char transfertypes[][12 ] = {"pure inline" ,/* no chunks */ " read chunk", /* some argument via rdma read */
net/sunrpc/xprtrdma/transport.c +4 -4
@@ -55,7 +55,7 @@#include "xprt_rdma.h" -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_TRANS#endif
@@ -75,7 +75,7 @@ static unsigned int xprt_rdma_inline_write_padding;static unsigned int xprt_rdma_memreg_strategy =RPCRDMA_FRMR ;int xprt_rdma_pad_optimize =0 ; -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )static unsigned int min_slot_table_size =RPCRDMA_MIN_SLOT_TABLE ;static unsigned int max_slot_table_size =RPCRDMA_MAX_SLOT_TABLE ;
@@ -705,7 +705,7 @@ static void __exit xprt_rdma_cleanup(void)int rc;dprintk ("RPCRDMA Module Removed, deregister RPC RDMA transport\n" ); -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )if (sunrpc_table_header) {unregister_sysctl_table (sunrpc_table_header); sunrpc_table_header =NULL ;
@@ -736,7 +736,7 @@ static int __init xprt_rdma_init(void)dprintk ("\tPadding %d\n\tMemreg %d\n" , xprt_rdma_inline_write_padding, xprt_rdma_memreg_strategy); -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )if (!sunrpc_table_header) sunrpc_table_header =register_sysctl_table (sunrpc_table);#endif
net/sunrpc/xprtrdma/verbs.c +4 -4
@@ -57,7 +57,7 @@* Globals/Macros */ -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# define RPCDBG_FACILITY RPCDBG_TRANS#endif
@@ -313,7 +313,7 @@ rpcrdma_flush_cqs(struct rpcrdma_ep *ep)rpcrdma_sendcq_upcall (ep->rep_attr.send_cq, ep); } -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )static const char *const conn[] = {"address resolved" , "address error",
@@ -344,7 +344,7 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event)struct rpcrdma_xprt *xprt = id->context;struct rpcrdma_ia *ia = &xprt->rx_ia;struct rpcrdma_ep *ep = &xprt->rx_ep; -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )struct sockaddr_in *addr = (struct sockaddr_in *) &ep->rep_remote_addr;#endif struct ib_qp_attr attr;
@@ -408,7 +408,7 @@ connected:break ; } -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )if (connstate ==1 ) {int ird = attr.max_dest_rd_atomic;int tird = ep->rep_remote_cma.responder_resources;
net/sunrpc/xprtsock.c +4 -4
@@ -75,7 +75,7 @@ static unsigned int xs_tcp_fin_timeout __read_mostly = XS_TCP_LINGER_TO;* someone else's file names! */ -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )static unsigned int min_slot_table_size =RPC_MIN_SLOT_TABLE ;static unsigned int max_slot_table_size =RPC_MAX_SLOT_TABLE ;
@@ -186,7 +186,7 @@ static struct ctl_table sunrpc_table[] = {*/ #define XS_IDLE_DISC_TO (5U * 60 * HZ) -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )# undef RPC_DEBUG_DATA# define RPCDBG_FACILITY RPCDBG_TRANS#endif
@@ -2991,7 +2991,7 @@ static struct xprt_class xs_bc_tcp_transport = {*/ int init_socket_xprt (void ) { -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )if (!sunrpc_table_header) sunrpc_table_header =register_sysctl_table (sunrpc_table);#endif
@@ -3010,7 +3010,7 @@ int init_socket_xprt(void)*/ void cleanup_socket_xprt (void ) { -#ifdef RPC_DEBUG +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )if (sunrpc_table_header) {unregister_sysctl_table (sunrpc_table_header); sunrpc_table_header =NULL ;
Signature · 1 line
2.1.0
PATCH v3 3/5 sunrpc: eliminate RPC_TRACEPOINTS
In reply to Jeff LaytonIt's always set to the same value as CONFIG_TRACEPOINTS, so we can just use that instead.
--- include/linux/sunrpc/debug.h | 9 --------- include/linux/sunrpc/sched.h | 6 +++--- net/sunrpc/sched.c | 2 +- 3 files changed, 4 insertions(+), 13 deletions(-)
include/linux/sunrpc/debug.h +0 -9
@@ -10,15 +10,6 @@#include <uapi/linux/sunrpc/debug.h> - -/* -* Enable RPC debugging/profiling. -*/ -#ifdef CONFIG_TRACEPOINTS -#define RPC_TRACEPOINTS -#endif -/* #define RPC_PROFILE */ -/* * Debugging macros etc */
include/linux/sunrpc/sched.h +3 -3
@@ -79,7 +79,7 @@ struct rpc_task {unsigned short tk_flags;/* misc flags */ unsigned short tk_timeouts;/* maj timeouts */ -#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) || defined(RPC_TRACEPOINTS ) +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) ||IS_ENABLED (CONFIG_TRACEPOINTS )unsigned short tk_pid;/* debugging aid */ #endif unsigned char tk_priority : 2,/* Task priority */
@@ -187,7 +187,7 @@ struct rpc_wait_queue {unsigned char nr;/* # tasks remaining for cookie */ unsigned short qlen;/* total # tasks waiting in queue */ struct rpc_timer timer_list; -#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) || defined(RPC_TRACEPOINTS ) +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) ||IS_ENABLED (CONFIG_TRACEPOINTS )const char * name;#endif };
@@ -251,7 +251,7 @@ static inline int rpc_wait_for_completion_task(struct rpc_task *task)return __rpc_wait_for_completion_task (task,NULL ); } -#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) || defined (RPC_TRACEPOINTS ) +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) ||IS_ENABLED (CONFIG_TRACEPOINTS )static inline const char *rpc_qname (const struct rpc_wait_queue *q) {return ((q && q->name) ? q->name :"unknown" );
net/sunrpc/sched.c +1 -1
@@ -258,7 +258,7 @@ static int rpc_wait_bit_killable(struct wait_bit_key *key)return 0 ; } -#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) || defined(RPC_TRACEPOINTS ) +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) ||IS_ENABLED (CONFIG_TRACEPOINTS )static void rpc_task_set_debuginfo (struct rpc_task *task) {static atomic_t rpc_pid;
Signature · 1 line
2.1.0
PATCH v3 4/5 sunrpc: add debugfs file for displaying client rpc_task queue
In reply to Jeff LaytonIt's possible to get a dump of the RPC task queue by writing a value to /proc/sys/sunrpc/rpc_debug. If you write any value to that file, you get a dump of the RPC client task list into the log buffer. This is a rather inconvenient interface however, and makes it hard to get immediate info about the task queue.
Add a new directory hierarchy under debugfs:
sunrpc/
rpc_clnt/
<clientid>/Within each clientid directory we create a new "tasks" file that will dump info similar to what shows up in the log buffer, but with a few small differences -- we avoid printing raw kernel addresses in favor of symbolic names and the XID is also displayed.
--- include/linux/sunrpc/clnt.h | 4 + include/linux/sunrpc/debug.h | 31 +++++++ net/sunrpc/Kconfig | 1 + net/sunrpc/Makefile | 1 + net/sunrpc/clnt.c | 10 ++- net/sunrpc/debugfs.c | 191 +++++++++++++++++++++++++++++++++++++++++++ net/sunrpc/sunrpc_syms.c | 8 ++ 7 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 net/sunrpc/debugfs.c
include/linux/sunrpc/clnt.h +4 -0
@@ -63,6 +63,9 @@ struct rpc_clnt {struct rpc_rtt cl_rtt_default;struct rpc_timeout cl_timeout_default;const struct rpc_program *cl_program; +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) +struct dentry *cl_debugfs;/* debugfs directory */ +#endif };/*
@@ -176,5 +179,6 @@ size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);const char *rpc_peeraddr2str (struct rpc_clnt *,enum rpc_display_format_t );int rpc_localaddr (struct rpc_clnt *,struct sockaddr *,size_t ); +const char *rpc_proc_name (const struct rpc_task *task);#endif /* __KERNEL__ */ #endif /* _LINUX_SUNRPC_CLNT_H */
include/linux/sunrpc/debug.h +31 -0
@@ -53,9 +53,40 @@ extern unsigned int nlm_debug;/* * Sysctl interface for RPC debugging */ + +struct rpc_clnt ; +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )void rpc_register_sysctl (void );void rpc_unregister_sysctl (void ); +int sunrpc_debugfs_init (void ); +void sunrpc_debugfs_exit (void ); +int rpc_clnt_debugfs_register (struct rpc_clnt *); +void rpc_clnt_debugfs_unregister (struct rpc_clnt *); +#else +static inline int +sunrpc_debugfs_init (void ) +{ +return 0 ; +} + +static inline void +sunrpc_debugfs_exit (void ) +{ +return ; +} + +static inline int +rpc_clnt_debugfs_register (struct rpc_clnt *clnt) +{ +return 0 ; +} + +static inline void +rpc_clnt_debugfs_unregister (struct rpc_clnt *clnt) +{ +return ; +}#endif #endif /* _LINUX_SUNRPC_DEBUG_H_ */
net/sunrpc/Kconfig +1 -0
@@ -35,6 +35,7 @@ config RPCSEC_GSS_KRB5 config SUNRPC_DEBUG bool "RPC: Enable dprintk debugging" depends on SUNRPC && SYSCTL + select DEBUG_FS help This option enables a sysctl-based debugging interface that is be used by the 'rpcdebug' utility to turn on or off
net/sunrpc/Makefile +1 -0
@@ -14,6 +14,7 @@ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ addr.o rpcb_clnt.o timer.o xdr.o \ sunrpc_syms.o cache.o rpc_pipe.o \ svc_xprt.o +sunrpc-$(CONFIG_SUNRPC_DEBUG) += debugfs.o sunrpc-$(CONFIG_SUNRPC_BACKCHANNEL) += backchannel_rqst.o bc_svc.o sunrpc-$(CONFIG_PROC_FS) += stats.o sunrpc-$(CONFIG_SYSCTL) += sysctl.o
net/sunrpc/clnt.c +9 -1
@@ -305,6 +305,10 @@ static int rpc_client_register(struct rpc_clnt *clnt,struct super_block *pipefs_sb;int err; + err =rpc_clnt_debugfs_register (clnt); +if (err) +return err; + pipefs_sb =rpc_get_sb_net (net);if (pipefs_sb) { err =rpc_setup_pipedir (pipefs_sb, clnt);
@@ -331,6 +335,7 @@ err_auth: out:if (pipefs_sb)rpc_put_sb_net (net); +rpc_clnt_debugfs_unregister (clnt);return err; }
@@ -670,6 +675,7 @@ int rpc_switch_client_transport(struct rpc_clnt *clnt,rpc_unregister_client (clnt);__rpc_clnt_remove_pipedir (clnt); +rpc_clnt_debugfs_unregister (clnt);/* * A new transport was created. "clnt" therefore
@@ -771,6 +777,7 @@ rpc_free_client(struct rpc_clnt *clnt) rcu_dereference(clnt->cl_xprt)->servername);if (clnt->cl_parent != clnt) parent = clnt->cl_parent; +rpc_clnt_debugfs_unregister (clnt);rpc_clnt_remove_pipedir (clnt);rpc_unregister_client (clnt);rpc_free_iostats (clnt->cl_metrics);
@@ -1397,7 +1404,8 @@ rpc_restart_call(struct rpc_task *task)EXPORT_SYMBOL_GPL (rpc_restart_call);#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) -static const char *rpc_proc_name (const struct rpc_task *task) +const char +*rpc_proc_name (const struct rpc_task *task) {const struct rpc_procinfo *proc = task->tk_msg.rpc_proc;
net/sunrpc/debugfs.c new file +191 -0
191 lines not on this page · raw message
net/sunrpc/sunrpc_syms.c +8 -0
@@ -97,6 +97,11 @@ init_sunrpc(void) err =register_rpc_pipefs ();if (err) goto out4; + + err =sunrpc_debugfs_init (); +if (err) + goto out5; +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )rpc_register_sysctl ();#endif
@@ -104,6 +109,8 @@ init_sunrpc(void)init_socket_xprt ();/* clnt sock transport */ return 0 ; +out5: +unregister_rpc_pipefs (); out4:unregister_pernet_subsys (&sunrpc_net_ops); out3:
@@ -120,6 +127,7 @@ cleanup_sunrpc(void)rpcauth_remove_module ();cleanup_socket_xprt ();svc_cleanup_xprt_sock (); +sunrpc_debugfs_exit ();unregister_rpc_pipefs ();rpc_destroy_mempool ();unregister_pernet_subsys (&sunrpc_net_ops);
Signature · 1 line
2.1.0
Hi Jeff,
Quoted 8 lines · Jeff Layton
It's possible to get a dump of the RPC task queue by writing a value to
/proc/sys/sunrpc/rpc_debug. If you write any value to that file, you get a dump of the RPC client task list into the log buffer. This is a rather inconvenient interface however, and makes it hard to get immediate info about the task queue.Add a new directory hierarchy under debugfs:
Quoted 8 lines
sunrpc/ rpc_clnt/ <clientid>/Within each clientid directory we create a new "tasks" file that will dump info similar to what shows up in the log buffer, but with a few small differences -- we avoid printing raw kernel addresses in favor of symbolic names and the XID is also displayed.
What do I have to do to get tasks to show up in the tasks file? I'm running xfstests and occasionally running "cat" on 0/tasks and 3/tasks, but both are empty.
Anna
Quoted 383 lines
Signed-off-by Jeff Layton <[email protected]>--- include/linux/sunrpc/clnt.h | 4 + include/linux/sunrpc/debug.h | 31 +++++++ net/sunrpc/Kconfig | 1 + net/sunrpc/Makefile | 1 + net/sunrpc/clnt.c | 10 ++- net/sunrpc/debugfs.c | 191 +++++++++++++++++++++++++++++++++++++++++++ net/sunrpc/sunrpc_syms.c | 8 ++ 7 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 net/sunrpc/debugfs.cinclude/linux/sunrpc/clnt.h +4
-0@@ -63,6 +63,9 @@ struct rpc_clnt {struct rpc_rtt cl_rtt_default;struct rpc_timeout cl_timeout_default;const struct rpc_program *cl_program; +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) +struct dentry *cl_debugfs;/* debugfs directory */ +#endif };/* @@ -176,5 +179,6 @@ size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);const char *rpc_peeraddr2str (struct rpc_clnt *,enum rpc_display_format_t );int rpc_localaddr (struct rpc_clnt *,struct sockaddr *,size_t ); +const char *rpc_proc_name (const struct rpc_task *task);#endif /* __KERNEL__ */ #endif /* _LINUX_SUNRPC_CLNT_H */ include/linux/sunrpc/debug.h +31
-0@@ -53,9 +53,40 @@ extern unsigned int nlm_debug;/* * Sysctl interface for RPC debugging */ + +struct rpc_clnt ; +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )void rpc_register_sysctl (void );void rpc_unregister_sysctl (void ); +int sunrpc_debugfs_init (void ); +void sunrpc_debugfs_exit (void ); +int rpc_clnt_debugfs_register (struct rpc_clnt *); +void rpc_clnt_debugfs_unregister (struct rpc_clnt *); +#else +static inline int +sunrpc_debugfs_init (void ) +{ +return 0 ; +} + +static inline void +sunrpc_debugfs_exit (void ) +{ +return ; +} + +static inline int +rpc_clnt_debugfs_register (struct rpc_clnt *clnt) +{ +return 0 ; +} + +static inline void +rpc_clnt_debugfs_unregister (struct rpc_clnt *clnt) +{ +return ; +}#endif #endif /* _LINUX_SUNRPC_DEBUG_H_ */ net/sunrpc/Kconfig +1
-0@@ -35,6 +35,7 @@ config RPCSEC_GSS_KRB5 config SUNRPC_DEBUG bool "RPC: Enable dprintk debugging" depends on SUNRPC && SYSCTL + select DEBUG_FS help This option enables a sysctl-based debugging interface that is be used by the 'rpcdebug' utility to turn on or offnet/sunrpc/Makefile +1
-0@@ -14,6 +14,7 @@ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ addr.o rpcb_clnt.o timer.o xdr.o \ sunrpc_syms.o cache.o rpc_pipe.o \ svc_xprt.o +sunrpc-$(CONFIG_SUNRPC_DEBUG) += debugfs.o sunrpc-$(CONFIG_SUNRPC_BACKCHANNEL) += backchannel_rqst.o bc_svc.o sunrpc-$(CONFIG_PROC_FS) += stats.o sunrpc-$(CONFIG_SYSCTL) += sysctl.onet/sunrpc/clnt.c +9
-1@@ -305,6 +305,10 @@ static int rpc_client_register(struct rpc_clnt *clnt,struct super_block *pipefs_sb;int err; + err =rpc_clnt_debugfs_register (clnt); +if (err) +return err; + pipefs_sb =rpc_get_sb_net (net);if (pipefs_sb) { err =rpc_setup_pipedir (pipefs_sb, clnt);@@ -331,6 +335,7 @@ err_auth: out:if (pipefs_sb)rpc_put_sb_net (net); +rpc_clnt_debugfs_unregister (clnt);return err; }@@ -670,6 +675,7 @@ int rpc_switch_client_transport(struct rpc_clnt *clnt,rpc_unregister_client (clnt);__rpc_clnt_remove_pipedir (clnt); +rpc_clnt_debugfs_unregister (clnt);/* * A new transport was created. "clnt" therefore @@ -771,6 +777,7 @@ rpc_free_client(struct rpc_clnt *clnt) rcu_dereference(clnt->cl_xprt)->servername);if (clnt->cl_parent != clnt) parent = clnt->cl_parent; +rpc_clnt_debugfs_unregister (clnt);rpc_clnt_remove_pipedir (clnt);rpc_unregister_client (clnt);rpc_free_iostats (clnt->cl_metrics);@@ -1397,7 +1404,8 @@ rpc_restart_call(struct rpc_task *task)EXPORT_SYMBOL_GPL (rpc_restart_call);#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) -static const char *rpc_proc_name (const struct rpc_task *task) +const char +*rpc_proc_name (const struct rpc_task *task) {const struct rpc_procinfo *proc = task->tk_msg.rpc_proc;net/sunrpc/debugfs.c new file +191
-0@@ -0,0 +1,191 @@ +/** +* debugfs interface for sunrpc +* +* (c) 2014 Jeff Layton <[email protected]> +*/ + +#include <linux/debugfs.h> +#include <linux/sunrpc/sched.h> +#include <linux/sunrpc/clnt.h> +#include "netns.h" + +static struct dentry *topdir; +static struct dentry *rpc_clnt_dir; + +struct rpc_clnt_iter { +struct rpc_clnt *clnt; +loff_t pos; +}; + +static int +tasks_show (struct seq_file *f,void *v) +{ +u32 xid =0 ; +struct rpc_task *task = v; +struct rpc_clnt *clnt = task->tk_client; +const char *rpc_waitq ="none" ; + +if (RPC_IS_QUEUED (task)) + rpc_waitq =rpc_qname (task->tk_waitqueue); + +if (task->tk_rqstp) + xid =be32_to_cpu (task->tk_rqstp->rq_xid); + +seq_printf (f,"%5u %04x %6d 0x%x 0x%x %8ld %ps %sv%u %s a:%ps q:%s\n" , + task->tk_pid, task->tk_flags, task->tk_status, + clnt->cl_clid, xid, task->tk_timeout, task->tk_ops, + clnt->cl_program->name, clnt->cl_vers,rpc_proc_name (task), + task->tk_action, rpc_waitq); +return 0 ; +} + +static void * +tasks_start (struct seq_file *f,loff_t *ppos) + __acquires(&clnt->cl_lock) +{ +struct rpc_clnt_iter *iter = f->private; +loff_t pos = *ppos; +struct rpc_clnt *clnt = iter->clnt; +struct rpc_task *task; + + iter->pos = pos +1 ; +spin_lock (&clnt->cl_lock); +list_for_each_entry (task, &clnt->cl_tasks, tk_task) +if (pos-- ==0 ) +return task; +return NULL ; +} + +static void * +tasks_next (struct seq_file *f,void *v,loff_t *pos) +{ +struct rpc_clnt_iter *iter = f->private; +struct rpc_clnt *clnt = iter->clnt; +struct rpc_task *task = v; +struct list_head *next = task->tk_task.next; + + ++iter->pos; + ++*pos; + +/* If there's another task on list, return it */ +if (next == &clnt->cl_tasks) +return NULL ; + return list_entry(next, struct rpc_task, tk_task); +} + +static void +tasks_stop (struct seq_file *f,void *v) + __releases(&clnt->cl_lock) +{ +struct rpc_clnt_iter *iter = f->private; +struct rpc_clnt *clnt = iter->clnt; + +spin_unlock (&clnt->cl_lock); +} + +static const struct seq_operations tasks_seq_operations = { + .start = tasks_start, + .next = tasks_next, + .stop = tasks_stop, + .show = tasks_show, +}; + +static int tasks_open (struct inode *inode,struct file *filp) +{ +int ret =seq_open_private (filp, &tasks_seq_operations, +sizeof (struct rpc_clnt_iter )); + +if (!ret) { +struct seq_file *seq = filp->private_data; +struct rpc_clnt_iter *iter = seq->private; + + iter->clnt = inode->i_private; + +if (!atomic_inc_not_zero (&iter->clnt->cl_count)) { +seq_release_private (inode, filp); + ret = -EINVAL ; + } + } + +return ret; +} + +static int +tasks_release (struct inode *inode,struct file *filp) +{ +struct seq_file *seq = filp->private_data; +struct rpc_clnt_iter *iter = seq->private; + +rpc_release_client (iter->clnt); +return seq_release_private (inode, filp); +} + +static const struct file_operations tasks_fops = { + .owner =THIS_MODULE , + .open = tasks_open, + .read = seq_read, + .llseek = seq_lseek, + .release = tasks_release, +}; + +int +rpc_clnt_debugfs_register (struct rpc_clnt *clnt) +{ +int len; +char name[9 ];/* 8 for hex digits + NULL terminator */ + +/* Already registered? */ +if (clnt->cl_debugfs) +return 0 ; + + len =snprintf (name,sizeof (name),"%x" , clnt->cl_clid); +if (len >=sizeof (name)) +return -EINVAL ; + +/* make the per-client dir */ + clnt->cl_debugfs =debugfs_create_dir (name, rpc_clnt_dir); +if (!clnt->cl_debugfs) +return -ENOMEM ; + +/* make tasks file */ +if (!debugfs_create_file ("tasks" ,S_IFREG |S_IRUSR , clnt->cl_debugfs, + clnt, &tasks_fops)) { +debugfs_remove_recursive (clnt->cl_debugfs); + clnt->cl_debugfs =NULL ; +return -ENOMEM ; + } + +return 0 ; +} + +void +rpc_clnt_debugfs_unregister (struct rpc_clnt *clnt) +{ +debugfs_remove_recursive (clnt->cl_debugfs); + clnt->cl_debugfs =NULL ; +} + +void __exit +sunrpc_debugfs_exit (void ) +{ +debugfs_remove_recursive (topdir); +} + +int __init +sunrpc_debugfs_init (void ) +{ + topdir =debugfs_create_dir ("sunrpc" ,NULL ); +if (!topdir) + goto out; + + rpc_clnt_dir =debugfs_create_dir ("rpc_clnt" , topdir); +if (!rpc_clnt_dir) + goto out_remove; + +return 0 ; +out_remove: +debugfs_remove_recursive (topdir); + topdir =NULL ; +out: +return -ENOMEM ; +}net/sunrpc/sunrpc_syms.c +8
-0@@ -97,6 +97,11 @@ init_sunrpc(void) err =register_rpc_pipefs ();if (err) goto out4; + + err =sunrpc_debugfs_init (); +if (err) + goto out5; +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )rpc_register_sysctl ();#endif @@ -104,6 +109,8 @@ init_sunrpc(void)init_socket_xprt ();/* clnt sock transport */ return 0 ; +out5: +unregister_rpc_pipefs (); out4:unregister_pernet_subsys (&sunrpc_net_ops); out3:@@ -120,6 +127,7 @@ cleanup_sunrpc(void)rpcauth_remove_module ();cleanup_socket_xprt ();svc_cleanup_xprt_sock (); +sunrpc_debugfs_exit ();unregister_rpc_pipefs ();rpc_destroy_mempool ();unregister_pernet_subsys (&sunrpc_net_ops);
Quoted 15 lines · Anna Schumaker
Hi Jeff,
Quoted 12 lines · Jeff Layton
It's possible to get a dump of the RPC task queue by writing a value to
/proc/sys/sunrpc/rpc_debug. If you write any value to that file, you get a dump of the RPC client task list into the log buffer. This is a rather inconvenient interface however, and makes it hard to get immediate info about the task queue.Add a new directory hierarchy under debugfs:
sunrpc/ rpc_clnt/ <clientid>/
Quoted 6 lines
Quoted 4 lines
Within each clientid directory we create a new "tasks" file that will dump info similar to what shows up in the log buffer, but with a few small differences -- we avoid printing raw kernel addresses in favor of symbolic names and the XID is also displayed.
What do I have to do to get tasks to show up in the tasks file? I'm running xfstests and occasionally running "cat" on 0/tasks and 3/tasks, but both are empty.
Ah, apparently I had to wait for generic/074 to run. Now things are showing up!
Anna
Quoted 387 lines
Anna
Quoted 383 lines
Signed-off-by Jeff Layton <[email protected]>--- include/linux/sunrpc/clnt.h | 4 + include/linux/sunrpc/debug.h | 31 +++++++ net/sunrpc/Kconfig | 1 + net/sunrpc/Makefile | 1 + net/sunrpc/clnt.c | 10 ++- net/sunrpc/debugfs.c | 191 +++++++++++++++++++++++++++++++++++++++++++ net/sunrpc/sunrpc_syms.c | 8 ++ 7 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 net/sunrpc/debugfs.cinclude/linux/sunrpc/clnt.h +4
-0@@ -63,6 +63,9 @@ struct rpc_clnt {struct rpc_rtt cl_rtt_default;struct rpc_timeout cl_timeout_default;const struct rpc_program *cl_program; +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) +struct dentry *cl_debugfs;/* debugfs directory */ +#endif };/* @@ -176,5 +179,6 @@ size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);const char *rpc_peeraddr2str (struct rpc_clnt *,enum rpc_display_format_t );int rpc_localaddr (struct rpc_clnt *,struct sockaddr *,size_t ); +const char *rpc_proc_name (const struct rpc_task *task);#endif /* __KERNEL__ */ #endif /* _LINUX_SUNRPC_CLNT_H */ include/linux/sunrpc/debug.h +31
-0@@ -53,9 +53,40 @@ extern unsigned int nlm_debug;/* * Sysctl interface for RPC debugging */ + +struct rpc_clnt ; +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )void rpc_register_sysctl (void );void rpc_unregister_sysctl (void ); +int sunrpc_debugfs_init (void ); +void sunrpc_debugfs_exit (void ); +int rpc_clnt_debugfs_register (struct rpc_clnt *); +void rpc_clnt_debugfs_unregister (struct rpc_clnt *); +#else +static inline int +sunrpc_debugfs_init (void ) +{ +return 0 ; +} + +static inline void +sunrpc_debugfs_exit (void ) +{ +return ; +} + +static inline int +rpc_clnt_debugfs_register (struct rpc_clnt *clnt) +{ +return 0 ; +} + +static inline void +rpc_clnt_debugfs_unregister (struct rpc_clnt *clnt) +{ +return ; +}#endif #endif /* _LINUX_SUNRPC_DEBUG_H_ */ net/sunrpc/Kconfig +1
-0@@ -35,6 +35,7 @@ config RPCSEC_GSS_KRB5 config SUNRPC_DEBUG bool "RPC: Enable dprintk debugging" depends on SUNRPC && SYSCTL + select DEBUG_FS help This option enables a sysctl-based debugging interface that is be used by the 'rpcdebug' utility to turn on or offnet/sunrpc/Makefile +1
-0@@ -14,6 +14,7 @@ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ addr.o rpcb_clnt.o timer.o xdr.o \ sunrpc_syms.o cache.o rpc_pipe.o \ svc_xprt.o +sunrpc-$(CONFIG_SUNRPC_DEBUG) += debugfs.o sunrpc-$(CONFIG_SUNRPC_BACKCHANNEL) += backchannel_rqst.o bc_svc.o sunrpc-$(CONFIG_PROC_FS) += stats.o sunrpc-$(CONFIG_SYSCTL) += sysctl.onet/sunrpc/clnt.c +9
-1@@ -305,6 +305,10 @@ static int rpc_client_register(struct rpc_clnt *clnt,struct super_block *pipefs_sb;int err; + err =rpc_clnt_debugfs_register (clnt); +if (err) +return err; + pipefs_sb =rpc_get_sb_net (net);if (pipefs_sb) { err =rpc_setup_pipedir (pipefs_sb, clnt);@@ -331,6 +335,7 @@ err_auth: out:if (pipefs_sb)rpc_put_sb_net (net); +rpc_clnt_debugfs_unregister (clnt);return err; }@@ -670,6 +675,7 @@ int rpc_switch_client_transport(struct rpc_clnt *clnt,rpc_unregister_client (clnt);__rpc_clnt_remove_pipedir (clnt); +rpc_clnt_debugfs_unregister (clnt);/* * A new transport was created. "clnt" therefore @@ -771,6 +777,7 @@ rpc_free_client(struct rpc_clnt *clnt) rcu_dereference(clnt->cl_xprt)->servername);if (clnt->cl_parent != clnt) parent = clnt->cl_parent; +rpc_clnt_debugfs_unregister (clnt);rpc_clnt_remove_pipedir (clnt);rpc_unregister_client (clnt);rpc_free_iostats (clnt->cl_metrics);@@ -1397,7 +1404,8 @@ rpc_restart_call(struct rpc_task *task)EXPORT_SYMBOL_GPL (rpc_restart_call);#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) -static const char *rpc_proc_name (const struct rpc_task *task) +const char +*rpc_proc_name (const struct rpc_task *task) {const struct rpc_procinfo *proc = task->tk_msg.rpc_proc;net/sunrpc/debugfs.c new file +191
-0@@ -0,0 +1,191 @@ +/** +* debugfs interface for sunrpc +* +* (c) 2014 Jeff Layton <[email protected]> +*/ + +#include <linux/debugfs.h> +#include <linux/sunrpc/sched.h> +#include <linux/sunrpc/clnt.h> +#include "netns.h" + +static struct dentry *topdir; +static struct dentry *rpc_clnt_dir; + +struct rpc_clnt_iter { +struct rpc_clnt *clnt; +loff_t pos; +}; + +static int +tasks_show (struct seq_file *f,void *v) +{ +u32 xid =0 ; +struct rpc_task *task = v; +struct rpc_clnt *clnt = task->tk_client; +const char *rpc_waitq ="none" ; + +if (RPC_IS_QUEUED (task)) + rpc_waitq =rpc_qname (task->tk_waitqueue); + +if (task->tk_rqstp) + xid =be32_to_cpu (task->tk_rqstp->rq_xid); + +seq_printf (f,"%5u %04x %6d 0x%x 0x%x %8ld %ps %sv%u %s a:%ps q:%s\n" , + task->tk_pid, task->tk_flags, task->tk_status, + clnt->cl_clid, xid, task->tk_timeout, task->tk_ops, + clnt->cl_program->name, clnt->cl_vers,rpc_proc_name (task), + task->tk_action, rpc_waitq); +return 0 ; +} + +static void * +tasks_start (struct seq_file *f,loff_t *ppos) + __acquires(&clnt->cl_lock) +{ +struct rpc_clnt_iter *iter = f->private; +loff_t pos = *ppos; +struct rpc_clnt *clnt = iter->clnt; +struct rpc_task *task; + + iter->pos = pos +1 ; +spin_lock (&clnt->cl_lock); +list_for_each_entry (task, &clnt->cl_tasks, tk_task) +if (pos-- ==0 ) +return task; +return NULL ; +} + +static void * +tasks_next (struct seq_file *f,void *v,loff_t *pos) +{ +struct rpc_clnt_iter *iter = f->private; +struct rpc_clnt *clnt = iter->clnt; +struct rpc_task *task = v; +struct list_head *next = task->tk_task.next; + + ++iter->pos; + ++*pos; + +/* If there's another task on list, return it */ +if (next == &clnt->cl_tasks) +return NULL ; + return list_entry(next, struct rpc_task, tk_task); +} + +static void +tasks_stop (struct seq_file *f,void *v) + __releases(&clnt->cl_lock) +{ +struct rpc_clnt_iter *iter = f->private; +struct rpc_clnt *clnt = iter->clnt; + +spin_unlock (&clnt->cl_lock); +} + +static const struct seq_operations tasks_seq_operations = { + .start = tasks_start, + .next = tasks_next, + .stop = tasks_stop, + .show = tasks_show, +}; + +static int tasks_open (struct inode *inode,struct file *filp) +{ +int ret =seq_open_private (filp, &tasks_seq_operations, +sizeof (struct rpc_clnt_iter )); + +if (!ret) { +struct seq_file *seq = filp->private_data; +struct rpc_clnt_iter *iter = seq->private; + + iter->clnt = inode->i_private; + +if (!atomic_inc_not_zero (&iter->clnt->cl_count)) { +seq_release_private (inode, filp); + ret = -EINVAL ; + } + } + +return ret; +} + +static int +tasks_release (struct inode *inode,struct file *filp) +{ +struct seq_file *seq = filp->private_data; +struct rpc_clnt_iter *iter = seq->private; + +rpc_release_client (iter->clnt); +return seq_release_private (inode, filp); +} + +static const struct file_operations tasks_fops = { + .owner =THIS_MODULE , + .open = tasks_open, + .read = seq_read, + .llseek = seq_lseek, + .release = tasks_release, +}; + +int +rpc_clnt_debugfs_register (struct rpc_clnt *clnt) +{ +int len; +char name[9 ];/* 8 for hex digits + NULL terminator */ + +/* Already registered? */ +if (clnt->cl_debugfs) +return 0 ; + + len =snprintf (name,sizeof (name),"%x" , clnt->cl_clid); +if (len >=sizeof (name)) +return -EINVAL ; + +/* make the per-client dir */ + clnt->cl_debugfs =debugfs_create_dir (name, rpc_clnt_dir); +if (!clnt->cl_debugfs) +return -ENOMEM ; + +/* make tasks file */ +if (!debugfs_create_file ("tasks" ,S_IFREG |S_IRUSR , clnt->cl_debugfs, + clnt, &tasks_fops)) { +debugfs_remove_recursive (clnt->cl_debugfs); + clnt->cl_debugfs =NULL ; +return -ENOMEM ; + } + +return 0 ; +} + +void +rpc_clnt_debugfs_unregister (struct rpc_clnt *clnt) +{ +debugfs_remove_recursive (clnt->cl_debugfs); + clnt->cl_debugfs =NULL ; +} + +void __exit +sunrpc_debugfs_exit (void ) +{ +debugfs_remove_recursive (topdir); +} + +int __init +sunrpc_debugfs_init (void ) +{ + topdir =debugfs_create_dir ("sunrpc" ,NULL ); +if (!topdir) + goto out; + + rpc_clnt_dir =debugfs_create_dir ("rpc_clnt" , topdir); +if (!rpc_clnt_dir) + goto out_remove; + +return 0 ; +out_remove: +debugfs_remove_recursive (topdir); + topdir =NULL ; +out: +return -ENOMEM ; +}net/sunrpc/sunrpc_syms.c +8
-0@@ -97,6 +97,11 @@ init_sunrpc(void) err =register_rpc_pipefs ();if (err) goto out4; + + err =sunrpc_debugfs_init (); +if (err) + goto out5; +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )rpc_register_sysctl ();#endif @@ -104,6 +109,8 @@ init_sunrpc(void)init_socket_xprt ();/* clnt sock transport */ return 0 ; +out5: +unregister_rpc_pipefs (); out4:unregister_pernet_subsys (&sunrpc_net_ops); out3:@@ -120,6 +127,7 @@ cleanup_sunrpc(void)rpcauth_remove_module ();cleanup_socket_xprt ();svc_cleanup_xprt_sock (); +sunrpc_debugfs_exit ();unregister_rpc_pipefs ();rpc_destroy_mempool ();unregister_pernet_subsys (&sunrpc_net_ops);
Quoted 21 lines · On Wed, 26 Nov 2014 15:15:42 -0500 Anna Schumaker <[email protected]>…
Quoted 20 lines · Anna Schumaker
Hi Jeff,
Quoted 16 lines · Jeff Layton
It's possible to get a dump of the RPC task queue by writing a value to
/proc/sys/sunrpc/rpc_debug. If you write any value to that file, you get a dump of the RPC client task list into the log buffer. This is a rather inconvenient interface however, and makes it hard to get immediate info about the task queue.Add a new directory hierarchy under debugfs:
sunrpc/ rpc_clnt/ <clientid>/Within each clientid directory we create a new "tasks" file that will dump info similar to what shows up in the log buffer, but with a few small differences -- we avoid printing raw kernel addresses in favor of symbolic names and the XID is also displayed.
Quoted 6 lines
Quoted 1 line
What do I have to do to get tasks to show up in the tasks file? I'm running xfstests and occasionally running "cat" on 0/tasks and 3/tasks, but both are empty.
Ah, apparently I had to wait for generic/074 to run. Now things are showing up!
Anna
Ok, cool!
Yes, if you have relatively quick clients and servers then it can be hard to catch them in the act. FWIW, I think this will primarily be of use when there are problems on the client and the queue ends up blocked for some reason.
Quoted 388 lines
Quoted 387 lines
Anna
Quoted 383 lines
Signed-off-by Jeff Layton <[email protected]>--- include/linux/sunrpc/clnt.h | 4 + include/linux/sunrpc/debug.h | 31 +++++++ net/sunrpc/Kconfig | 1 + net/sunrpc/Makefile | 1 + net/sunrpc/clnt.c | 10 ++- net/sunrpc/debugfs.c | 191 +++++++++++++++++++++++++++++++++++++++++++ net/sunrpc/sunrpc_syms.c | 8 ++ 7 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 net/sunrpc/debugfs.cinclude/linux/sunrpc/clnt.h +4
-0@@ -63,6 +63,9 @@ struct rpc_clnt {struct rpc_rtt cl_rtt_default;struct rpc_timeout cl_timeout_default;const struct rpc_program *cl_program; +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) +struct dentry *cl_debugfs;/* debugfs directory */ +#endif };/* @@ -176,5 +179,6 @@ size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);const char *rpc_peeraddr2str (struct rpc_clnt *,enum rpc_display_format_t );int rpc_localaddr (struct rpc_clnt *,struct sockaddr *,size_t ); +const char *rpc_proc_name (const struct rpc_task *task);#endif /* __KERNEL__ */ #endif /* _LINUX_SUNRPC_CLNT_H */ include/linux/sunrpc/debug.h +31
-0@@ -53,9 +53,40 @@ extern unsigned int nlm_debug;/* * Sysctl interface for RPC debugging */ + +struct rpc_clnt ; +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )void rpc_register_sysctl (void );void rpc_unregister_sysctl (void ); +int sunrpc_debugfs_init (void ); +void sunrpc_debugfs_exit (void ); +int rpc_clnt_debugfs_register (struct rpc_clnt *); +void rpc_clnt_debugfs_unregister (struct rpc_clnt *); +#else +static inline int +sunrpc_debugfs_init (void ) +{ +return 0 ; +} + +static inline void +sunrpc_debugfs_exit (void ) +{ +return ; +} + +static inline int +rpc_clnt_debugfs_register (struct rpc_clnt *clnt) +{ +return 0 ; +} + +static inline void +rpc_clnt_debugfs_unregister (struct rpc_clnt *clnt) +{ +return ; +}#endif #endif /* _LINUX_SUNRPC_DEBUG_H_ */ net/sunrpc/Kconfig +1
-0@@ -35,6 +35,7 @@ config RPCSEC_GSS_KRB5 config SUNRPC_DEBUG bool "RPC: Enable dprintk debugging" depends on SUNRPC && SYSCTL + select DEBUG_FS help This option enables a sysctl-based debugging interface that is be used by the 'rpcdebug' utility to turn on or offnet/sunrpc/Makefile +1
-0@@ -14,6 +14,7 @@ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ addr.o rpcb_clnt.o timer.o xdr.o \ sunrpc_syms.o cache.o rpc_pipe.o \ svc_xprt.o +sunrpc-$(CONFIG_SUNRPC_DEBUG) += debugfs.o sunrpc-$(CONFIG_SUNRPC_BACKCHANNEL) += backchannel_rqst.o bc_svc.o sunrpc-$(CONFIG_PROC_FS) += stats.o sunrpc-$(CONFIG_SYSCTL) += sysctl.onet/sunrpc/clnt.c +9
-1@@ -305,6 +305,10 @@ static int rpc_client_register(struct rpc_clnt *clnt,struct super_block *pipefs_sb;int err; + err =rpc_clnt_debugfs_register (clnt); +if (err) +return err; + pipefs_sb =rpc_get_sb_net (net);if (pipefs_sb) { err =rpc_setup_pipedir (pipefs_sb, clnt);@@ -331,6 +335,7 @@ err_auth: out:if (pipefs_sb)rpc_put_sb_net (net); +rpc_clnt_debugfs_unregister (clnt);return err; }@@ -670,6 +675,7 @@ int rpc_switch_client_transport(struct rpc_clnt *clnt,rpc_unregister_client (clnt);__rpc_clnt_remove_pipedir (clnt); +rpc_clnt_debugfs_unregister (clnt);/* * A new transport was created. "clnt" therefore @@ -771,6 +777,7 @@ rpc_free_client(struct rpc_clnt *clnt) rcu_dereference(clnt->cl_xprt)->servername);if (clnt->cl_parent != clnt) parent = clnt->cl_parent; +rpc_clnt_debugfs_unregister (clnt);rpc_clnt_remove_pipedir (clnt);rpc_unregister_client (clnt);rpc_free_iostats (clnt->cl_metrics);@@ -1397,7 +1404,8 @@ rpc_restart_call(struct rpc_task *task)EXPORT_SYMBOL_GPL (rpc_restart_call);#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) -static const char *rpc_proc_name (const struct rpc_task *task) +const char +*rpc_proc_name (const struct rpc_task *task) {const struct rpc_procinfo *proc = task->tk_msg.rpc_proc;net/sunrpc/debugfs.c new file +191
-0@@ -0,0 +1,191 @@ +/** +* debugfs interface for sunrpc +* +* (c) 2014 Jeff Layton <[email protected]> +*/ + +#include <linux/debugfs.h> +#include <linux/sunrpc/sched.h> +#include <linux/sunrpc/clnt.h> +#include "netns.h" + +static struct dentry *topdir; +static struct dentry *rpc_clnt_dir; + +struct rpc_clnt_iter { +struct rpc_clnt *clnt; +loff_t pos; +}; + +static int +tasks_show (struct seq_file *f,void *v) +{ +u32 xid =0 ; +struct rpc_task *task = v; +struct rpc_clnt *clnt = task->tk_client; +const char *rpc_waitq ="none" ; + +if (RPC_IS_QUEUED (task)) + rpc_waitq =rpc_qname (task->tk_waitqueue); + +if (task->tk_rqstp) + xid =be32_to_cpu (task->tk_rqstp->rq_xid); + +seq_printf (f,"%5u %04x %6d 0x%x 0x%x %8ld %ps %sv%u %s a:%ps q:%s\n" , + task->tk_pid, task->tk_flags, task->tk_status, + clnt->cl_clid, xid, task->tk_timeout, task->tk_ops, + clnt->cl_program->name, clnt->cl_vers,rpc_proc_name (task), + task->tk_action, rpc_waitq); +return 0 ; +} + +static void * +tasks_start (struct seq_file *f,loff_t *ppos) + __acquires(&clnt->cl_lock) +{ +struct rpc_clnt_iter *iter = f->private; +loff_t pos = *ppos; +struct rpc_clnt *clnt = iter->clnt; +struct rpc_task *task; + + iter->pos = pos +1 ; +spin_lock (&clnt->cl_lock); +list_for_each_entry (task, &clnt->cl_tasks, tk_task) +if (pos-- ==0 ) +return task; +return NULL ; +} + +static void * +tasks_next (struct seq_file *f,void *v,loff_t *pos) +{ +struct rpc_clnt_iter *iter = f->private; +struct rpc_clnt *clnt = iter->clnt; +struct rpc_task *task = v; +struct list_head *next = task->tk_task.next; + + ++iter->pos; + ++*pos; + +/* If there's another task on list, return it */ +if (next == &clnt->cl_tasks) +return NULL ; + return list_entry(next, struct rpc_task, tk_task); +} + +static void +tasks_stop (struct seq_file *f,void *v) + __releases(&clnt->cl_lock) +{ +struct rpc_clnt_iter *iter = f->private; +struct rpc_clnt *clnt = iter->clnt; + +spin_unlock (&clnt->cl_lock); +} + +static const struct seq_operations tasks_seq_operations = { + .start = tasks_start, + .next = tasks_next, + .stop = tasks_stop, + .show = tasks_show, +}; + +static int tasks_open (struct inode *inode,struct file *filp) +{ +int ret =seq_open_private (filp, &tasks_seq_operations, +sizeof (struct rpc_clnt_iter )); + +if (!ret) { +struct seq_file *seq = filp->private_data; +struct rpc_clnt_iter *iter = seq->private; + + iter->clnt = inode->i_private; + +if (!atomic_inc_not_zero (&iter->clnt->cl_count)) { +seq_release_private (inode, filp); + ret = -EINVAL ; + } + } + +return ret; +} + +static int +tasks_release (struct inode *inode,struct file *filp) +{ +struct seq_file *seq = filp->private_data; +struct rpc_clnt_iter *iter = seq->private; + +rpc_release_client (iter->clnt); +return seq_release_private (inode, filp); +} + +static const struct file_operations tasks_fops = { + .owner =THIS_MODULE , + .open = tasks_open, + .read = seq_read, + .llseek = seq_lseek, + .release = tasks_release, +}; + +int +rpc_clnt_debugfs_register (struct rpc_clnt *clnt) +{ +int len; +char name[9 ];/* 8 for hex digits + NULL terminator */ + +/* Already registered? */ +if (clnt->cl_debugfs) +return 0 ; + + len =snprintf (name,sizeof (name),"%x" , clnt->cl_clid); +if (len >=sizeof (name)) +return -EINVAL ; + +/* make the per-client dir */ + clnt->cl_debugfs =debugfs_create_dir (name, rpc_clnt_dir); +if (!clnt->cl_debugfs) +return -ENOMEM ; + +/* make tasks file */ +if (!debugfs_create_file ("tasks" ,S_IFREG |S_IRUSR , clnt->cl_debugfs, + clnt, &tasks_fops)) { +debugfs_remove_recursive (clnt->cl_debugfs); + clnt->cl_debugfs =NULL ; +return -ENOMEM ; + } + +return 0 ; +} + +void +rpc_clnt_debugfs_unregister (struct rpc_clnt *clnt) +{ +debugfs_remove_recursive (clnt->cl_debugfs); + clnt->cl_debugfs =NULL ; +} + +void __exit +sunrpc_debugfs_exit (void ) +{ +debugfs_remove_recursive (topdir); +} + +int __init +sunrpc_debugfs_init (void ) +{ + topdir =debugfs_create_dir ("sunrpc" ,NULL ); +if (!topdir) + goto out; + + rpc_clnt_dir =debugfs_create_dir ("rpc_clnt" , topdir); +if (!rpc_clnt_dir) + goto out_remove; + +return 0 ; +out_remove: +debugfs_remove_recursive (topdir); + topdir =NULL ; +out: +return -ENOMEM ; +}net/sunrpc/sunrpc_syms.c +8
-0@@ -97,6 +97,11 @@ init_sunrpc(void) err =register_rpc_pipefs ();if (err) goto out4; + + err =sunrpc_debugfs_init (); +if (err) + goto out5; +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )rpc_register_sysctl ();#endif @@ -104,6 +109,8 @@ init_sunrpc(void)init_socket_xprt ();/* clnt sock transport */ return 0 ; +out5: +unregister_rpc_pipefs (); out4:unregister_pernet_subsys (&sunrpc_net_ops); out3:@@ -120,6 +127,7 @@ cleanup_sunrpc(void)rpcauth_remove_module ();cleanup_socket_xprt ();svc_cleanup_xprt_sock (); +sunrpc_debugfs_exit ();unregister_rpc_pipefs ();rpc_destroy_mempool ();unregister_pernet_subsys (&sunrpc_net_ops);
Signature · 1 line
Jeff Layton <[email protected]>
PATCH v3 5/5 sunrpc: add a debugfs rpc_xprt directory with an info file in it
In reply to Jeff LaytonAdd a new directory heirarchy under the debugfs sunrpc/ directory:
sunrpc/
rpc_xprt/
<xprt id>/Within that directory, we can put files that give info about the xprts. We do have the (minor) problem that there is no succinct, unique identifier for rpc_xprts. So we generate them synthetically with a static atomic_t counter.
For now, this directory just holds an "info" file, but we may add other files to it in the future.
--- include/linux/sunrpc/debug.h | 15 ++++++ include/linux/sunrpc/xprt.h | 3 ++ net/sunrpc/debugfs.c | 115 ++++++++++++++++++++++++++++++++++++++++--- net/sunrpc/xprt.c | 8 +++ 4 files changed, 134 insertions(+), 7 deletions(-)
include/linux/sunrpc/debug.h +15 -0
@@ -55,6 +55,7 @@ extern unsigned int nlm_debug;*/ struct rpc_clnt ; +struct rpc_xprt ;#if IS_ENABLED (CONFIG_SUNRPC_DEBUG )void rpc_register_sysctl (void );
@@ -63,6 +64,8 @@ int sunrpc_debugfs_init(void);void sunrpc_debugfs_exit (void );int rpc_clnt_debugfs_register (struct rpc_clnt *);void rpc_clnt_debugfs_unregister (struct rpc_clnt *); +int rpc_xprt_debugfs_register (struct rpc_xprt *); +void rpc_xprt_debugfs_unregister (struct rpc_xprt *);#else static inline int sunrpc_debugfs_init (void )
@@ -87,6 +90,18 @@ rpc_clnt_debugfs_unregister(struct rpc_clnt *clnt) {return ; } + +static inline int +rpc_xprt_debugfs_register (struct rpc_xprt *xprt) +{ +return 0 ; +} + +static inline void +rpc_xprt_debugfs_unregister (struct rpc_xprt *xprt) +{ +return ; +}#endif #endif /* _LINUX_SUNRPC_DEBUG_H_ */
include/linux/sunrpc/xprt.h +3 -0
@@ -239,6 +239,9 @@ struct rpc_xprt {struct net *xprt_net;const char *servername;const char *address_strings[RPC_DISPLAY_MAX ]; +#if IS_ENABLED (CONFIG_SUNRPC_DEBUG ) +struct dentry *debugfs;/* debugfs directory */ +#endif };#if defined(CONFIG_SUNRPC_BACKCHANNEL )
net/sunrpc/debugfs.c +108 -7
148 lines not on this page · raw message
net/sunrpc/xprt.c +8 -0
@@ -1303,6 +1303,7 @@ static void xprt_init(struct rpc_xprt *xprt, struct net *net)*/ struct rpc_xprt *xprt_create_transport (struct xprt_create *args) { +int err;struct rpc_xprt *xprt;struct xprt_class *t;
@@ -1343,6 +1344,12 @@ found:return ERR_PTR (-ENOMEM ); } + err =rpc_xprt_debugfs_register (xprt); +if (err) { +xprt_destroy (xprt); +return ERR_PTR (err); + } +dprintk ("RPC: created transport %p with %u slots\n" , xprt, xprt->max_reqs); out:
@@ -1359,6 +1366,7 @@ static void xprt_destroy(struct rpc_xprt *xprt)dprintk ("RPC: destroying transport %p\n" , xprt);del_timer_sync (&xprt->timer); +rpc_xprt_debugfs_unregister (xprt);rpc_destroy_wait_queue (&xprt->binding);rpc_destroy_wait_queue (&xprt->pending);rpc_destroy_wait_queue (&xprt->sending);
Signature · 1 line
2.1.0