2014-10-28 18:25:01

by Jeff Layton

[permalink] [raw]
Subject: [PATCH] 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.

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.c

diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 70736b98c721..265d40bd3109 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -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 */
diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
index 9385bd74c860..7c1ef9530087 100644
--- a/include/linux/sunrpc/debug.h
+++ b/include/linux/sunrpc/debug.h
@@ -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_ */
diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
index 0754d0f466d2..fb78117b896c 100644
--- a/net/sunrpc/Kconfig
+++ b/net/sunrpc/Kconfig
@@ -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
diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
index e5a7a1cac8f3..15e6f6c23c5d 100644
--- a/net/sunrpc/Makefile
+++ b/net/sunrpc/Makefile
@@ -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
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 9acd6ce88db7..5b2e2d3d37c1 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -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;

diff --git a/net/sunrpc/debugfs.c b/net/sunrpc/debugfs.c
new file mode 100644
index 000000000000..48769338172e
--- /dev/null
+++ b/net/sunrpc/debugfs.c
@@ -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)
+{
+ 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);
+ }
+ 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;
+}
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index cd30120de9e4..32583adf3477 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -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);
--
1.9.3



2014-10-28 18:30:50

by Jeff Layton

[permalink] [raw]
Subject: Re: [PATCH] sunrpc: add debugfs file for displaying client rpc_task queue

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.c
>
> diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
> index 70736b98c721..265d40bd3109 100644
> --- a/include/linux/sunrpc/clnt.h
> +++ b/include/linux/sunrpc/clnt.h
> @@ -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 */
> diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
> index 9385bd74c860..7c1ef9530087 100644
> --- a/include/linux/sunrpc/debug.h
> +++ b/include/linux/sunrpc/debug.h
> @@ -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_ */
> diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
> index 0754d0f466d2..fb78117b896c 100644
> --- a/net/sunrpc/Kconfig
> +++ b/net/sunrpc/Kconfig
> @@ -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
> diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
> index e5a7a1cac8f3..15e6f6c23c5d 100644
> --- a/net/sunrpc/Makefile
> +++ b/net/sunrpc/Makefile
> @@ -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
> diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
> index 9acd6ce88db7..5b2e2d3d37c1 100644
> --- a/net/sunrpc/clnt.c
> +++ b/net/sunrpc/clnt.c
> @@ -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;
>
> diff --git a/net/sunrpc/debugfs.c b/net/sunrpc/debugfs.c
> new file mode 100644
> index 000000000000..48769338172e
> --- /dev/null
> +++ b/net/sunrpc/debugfs.c
> @@ -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)
> +{
> + 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.

> + 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;
> +}
> diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
> index cd30120de9e4..32583adf3477 100644
> --- a/net/sunrpc/sunrpc_syms.c
> +++ b/net/sunrpc/sunrpc_syms.c
> @@ -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);


--
Jeff Layton <[email protected]>

2014-11-24 19:20:27

by Trond Myklebust

[permalink] [raw]
Subject: Re: [PATCH] sunrpc: add debugfs file for displaying client rpc_task queue

On Tue, Oct 28, 2014 at 2:30 PM, Jeff Layton
<[email protected]> wrote:
> 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.c
>>
>> diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
>> index 70736b98c721..265d40bd3109 100644
>> --- a/include/linux/sunrpc/clnt.h
>> +++ b/include/linux/sunrpc/clnt.h
>> @@ -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 */
>> diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
>> index 9385bd74c860..7c1ef9530087 100644
>> --- a/include/linux/sunrpc/debug.h
>> +++ b/include/linux/sunrpc/debug.h
>> @@ -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_ */
>> diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
>> index 0754d0f466d2..fb78117b896c 100644
>> --- a/net/sunrpc/Kconfig
>> +++ b/net/sunrpc/Kconfig
>> @@ -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
>> diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
>> index e5a7a1cac8f3..15e6f6c23c5d 100644
>> --- a/net/sunrpc/Makefile
>> +++ b/net/sunrpc/Makefile
>> @@ -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
>> diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
>> index 9acd6ce88db7..5b2e2d3d37c1 100644
>> --- a/net/sunrpc/clnt.c
>> +++ b/net/sunrpc/clnt.c
>> @@ -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;
>>
>> diff --git a/net/sunrpc/debugfs.c b/net/sunrpc/debugfs.c
>> new file mode 100644
>> index 000000000000..48769338172e
>> --- /dev/null
>> +++ b/net/sunrpc/debugfs.c
>> @@ -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;
>> +}

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
.....

--
Trond Myklebust

Linux NFS client maintainer, PrimaryData

[email protected]

2014-11-24 21:35:19

by Jeff Layton

[permalink] [raw]
Subject: Re: [PATCH] sunrpc: add debugfs file for displaying client rpc_task queue

On Mon, 24 Nov 2014 14:20:25 -0500
Trond Myklebust <[email protected]> wrote:

> On Tue, Oct 28, 2014 at 2:30 PM, Jeff Layton
> <[email protected]> wrote:
> > 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.c
> >>
> >> diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
> >> index 70736b98c721..265d40bd3109 100644
> >> --- a/include/linux/sunrpc/clnt.h
> >> +++ b/include/linux/sunrpc/clnt.h
> >> @@ -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 */
> >> diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
> >> index 9385bd74c860..7c1ef9530087 100644
> >> --- a/include/linux/sunrpc/debug.h
> >> +++ b/include/linux/sunrpc/debug.h
> >> @@ -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_ */
> >> diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
> >> index 0754d0f466d2..fb78117b896c 100644
> >> --- a/net/sunrpc/Kconfig
> >> +++ b/net/sunrpc/Kconfig
> >> @@ -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
> >> diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
> >> index e5a7a1cac8f3..15e6f6c23c5d 100644
> >> --- a/net/sunrpc/Makefile
> >> +++ b/net/sunrpc/Makefile
> >> @@ -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
> >> diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
> >> index 9acd6ce88db7..5b2e2d3d37c1 100644
> >> --- a/net/sunrpc/clnt.c
> >> +++ b/net/sunrpc/clnt.c
> >> @@ -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;
> >>
> >> diff --git a/net/sunrpc/debugfs.c b/net/sunrpc/debugfs.c
> >> new file mode 100644
> >> index 000000000000..48769338172e
> >> --- /dev/null
> >> +++ b/net/sunrpc/debugfs.c
> >> @@ -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;
> >> +}
>
> 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/

I'd suggest that we have a top level "sunrpc/" directory here to keep
things neat and tidy.

> rpc_clients/
> 1/
> cl_tasks
> cl_xprt->../../rpc_xprt/1
> .....
> 2/
> cl_tasks
> cl_xprt->../../rpc_xprt/1
> .....
> rpc_xprt/
> 1/
> servername
> .....
>

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...

--
Jeff Layton <[email protected]>

2014-11-25 19:01:09

by Jeff Layton

[permalink] [raw]
Subject: [PATCH v2 0/4] sunrpc: add debugfs file for displaying client rpc_task queue

This 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

--
2.1.0


2014-11-25 19:01:11

by Jeff Layton

[permalink] [raw]
Subject: [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.

Signed-off-by: Jeff Layton <[email protected]>
---
fs/lockd/svclock.c | 2 +-
include/linux/lockd/debug.h | 6 +-----
2 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 13db95f54176..56598742dde4 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -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)
{
/*
diff --git a/include/linux/lockd/debug.h b/include/linux/lockd/debug.h
index 257d3779f2ab..0ca8109934e4 100644
--- a/include/linux/lockd/debug.h
+++ b/include/linux/lockd/debug.h
@@ -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)
--
2.1.0


2014-11-25 19:01:13

by Jeff Layton

[permalink] [raw]
Subject: [PATCH v2 2/4] sunrpc: eliminate RPC_DEBUG

It's always set to whatever CONFIG_SUNRPC_DEBUG is, so just use that.

Signed-off-by: Jeff Layton <[email protected]>
---
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(-)

diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index 8e030075fe79..a7cbb570cc5c 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -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 */
diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
index 9385bd74c860..51143757b8f7 100644
--- a/include/linux/sunrpc/debug.h
+++ b/include/linux/sunrpc/debug.h
@@ -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
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 1a8959944c5f..fecdbf1b4797 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -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");
diff --git a/include/uapi/linux/nfsd/debug.h b/include/uapi/linux/nfsd/debug.h
index a6f453c740b8..1fdc95bb2375 100644
--- a/include/uapi/linux/nfsd/debug.h
+++ b/include/uapi/linux/nfsd/debug.h
@@ -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

diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 383eb919ac0b..47f38be4155f 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -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;
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c
index 6f6b829c9e8e..41248b1820c7 100644
--- a/net/sunrpc/auth_generic.c
+++ b/net/sunrpc/auth_generic.c
@@ -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

diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 53ed8d3f8897..dace13d7638e 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -66,7 +66,7 @@ static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED;
#define GSS_KEY_EXPIRE_TIMEO 240
static 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

diff --git a/net/sunrpc/auth_gss/gss_generic_token.c b/net/sunrpc/auth_gss/gss_generic_token.c
index c586e92bcf76..254defe446a7 100644
--- a/net/sunrpc/auth_gss/gss_generic_token.c
+++ b/net/sunrpc/auth_gss/gss_generic_token.c
@@ -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

diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index f5ed9f6ece06..b5408e8a37f2 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -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

diff --git a/net/sunrpc/auth_gss/gss_krb5_keys.c b/net/sunrpc/auth_gss/gss_krb5_keys.c
index 24589bd2a4b6..234fa8d0fd9b 100644
--- a/net/sunrpc/auth_gss/gss_krb5_keys.c
+++ b/net/sunrpc/auth_gss/gss_krb5_keys.c
@@ -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

diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 0d3c158ef8fa..28db442a0034 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -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

diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index 42768e5c3994..1d74d653e6c0 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -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

diff --git a/net/sunrpc/auth_gss/gss_krb5_seqnum.c b/net/sunrpc/auth_gss/gss_krb5_seqnum.c
index 62ac90c62cb1..20d55c793eb6 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seqnum.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seqnum.c
@@ -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

diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
index 6c981ddc19f8..dcf9515d9aef 100644
--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
@@ -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

diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index 4b614c604fe0..ca7e92a32f84 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -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

diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index 92d5ab99fbf3..7063d856a598 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -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

diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.h b/net/sunrpc/auth_gss/gss_rpc_xdr.h
index 685a688f3d8a..9d88c6239f01 100644
--- a/net/sunrpc/auth_gss/gss_rpc_xdr.h
+++ b/net/sunrpc/auth_gss/gss_rpc_xdr.h
@@ -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

diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index c548ab213f76..de856ddf5fed 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -51,7 +51,7 @@
#include "gss_rpc_upcall.h"


-#ifdef RPC_DEBUG
+#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
# define RPCDBG_FACILITY RPCDBG_AUTH
#endif

diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c
index 712c123e04e9..c2a2b584a056 100644
--- a/net/sunrpc/auth_null.c
+++ b/net/sunrpc/auth_null.c
@@ -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
};
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
index d5d692366294..4feda2d0a833 100644
--- a/net/sunrpc/auth_unix.c
+++ b/net/sunrpc/auth_unix.c
@@ -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

diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c
index 9761a0da964d..651f49ab601f 100644
--- a/net/sunrpc/backchannel_rqst.c
+++ b/net/sunrpc/backchannel_rqst.c
@@ -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

diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 9acd6ce88db7..36c64ef460cf 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -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- "
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 1891a1022c17..05202012bcfc 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -32,7 +32,7 @@

#include "netns.h"

-#ifdef RPC_DEBUG
+#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
# define RPCDBG_FACILITY RPCDBG_BIND
#endif

diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index fe3441abdbe5..574b2977fc4b 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -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;
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index cd30120de9e4..f632e476ab6c 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -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 */
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 371a8bbb43d6..2783fd80c229 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -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, ...)
{
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c
index c99c58e2ee66..887f0183b4c6 100644
--- a/net/sunrpc/sysctl.c
+++ b/net/sunrpc/sysctl.c
@@ -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[];
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 1b2e5e616cae..894d071426b2 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -57,7 +57,7 @@
* Local variables
*/

-#ifdef RPC_DEBUG
+#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
# define RPCDBG_FACILITY RPCDBG_XPRT
#endif

diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c
index 6166c985fe24..df01d124936c 100644
--- a/net/sunrpc/xprtrdma/rpc_rdma.c
+++ b/net/sunrpc/xprtrdma/rpc_rdma.c
@@ -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 */
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c
index 6a4615dd0261..ef58ebadb3ae 100644
--- a/net/sunrpc/xprtrdma/transport.c
+++ b/net/sunrpc/xprtrdma/transport.c
@@ -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
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
index 61c41298b4ea..b92b04083e40 100644
--- a/net/sunrpc/xprtrdma/verbs.c
+++ b/net/sunrpc/xprtrdma/verbs.c
@@ -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;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 31c015196a29..87ce7e8bb8dc 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -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;
--
2.1.0


2014-11-25 19:01:14

by Jeff Layton

[permalink] [raw]
Subject: [PATCH v2 3/4] sunrpc: eliminate RPC_TRACEPOINTS

It's always set to the same value as CONFIG_TRACEPOINTS, so we can just
use that instead.

Signed-off-by: Jeff Layton <[email protected]>
---
include/linux/sunrpc/debug.h | 9 ---------
include/linux/sunrpc/sched.h | 6 +++---
net/sunrpc/sched.c | 2 +-
3 files changed, 4 insertions(+), 13 deletions(-)

diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
index 51143757b8f7..43f38ee9668c 100644
--- a/include/linux/sunrpc/debug.h
+++ b/include/linux/sunrpc/debug.h
@@ -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
*/
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index fecdbf1b4797..5f1e6bd4c316 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -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");
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 574b2977fc4b..d20f2329eea3 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -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;
--
2.1.0


2014-11-25 19:01:16

by Jeff Layton

[permalink] [raw]
Subject: [PATCH v2 4/4] 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 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.c

diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 70736b98c721..d86acc63b25f 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -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 */
diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
index 43f38ee9668c..835339707094 100644
--- a/include/linux/sunrpc/debug.h
+++ b/include/linux/sunrpc/debug.h
@@ -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_ */
diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
index 0754d0f466d2..fb78117b896c 100644
--- a/net/sunrpc/Kconfig
+++ b/net/sunrpc/Kconfig
@@ -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
diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
index e5a7a1cac8f3..15e6f6c23c5d 100644
--- a/net/sunrpc/Makefile
+++ b/net/sunrpc/Makefile
@@ -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
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 36c64ef460cf..602259baebcc 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -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;

diff --git a/net/sunrpc/debugfs.c b/net/sunrpc/debugfs.c
new file mode 100644
index 000000000000..4062e8ca7363
--- /dev/null
+++ b/net/sunrpc/debugfs.c
@@ -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));
+
+ if (ret == 0) {
+ struct seq_file *seq = filp->private_data;
+ struct rpc_clnt_iter *iter = seq->private;
+
+ iter->clnt = inode->i_private;
+ }
+
+ return ret;
+}
+
+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;
+}
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index f632e476ab6c..e37fbed87956 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -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);
--
2.1.0


2014-11-25 21:00:18

by Jeff Layton

[permalink] [raw]
Subject: Re: [PATCH v2 4/4] sunrpc: add debugfs file for displaying client rpc_task queue

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.c
>
> diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
> index 70736b98c721..d86acc63b25f 100644
> --- a/include/linux/sunrpc/clnt.h
> +++ b/include/linux/sunrpc/clnt.h
> @@ -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 */
> diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
> index 43f38ee9668c..835339707094 100644
> --- a/include/linux/sunrpc/debug.h
> +++ b/include/linux/sunrpc/debug.h
> @@ -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_ */
> diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
> index 0754d0f466d2..fb78117b896c 100644
> --- a/net/sunrpc/Kconfig
> +++ b/net/sunrpc/Kconfig
> @@ -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
> diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
> index e5a7a1cac8f3..15e6f6c23c5d 100644
> --- a/net/sunrpc/Makefile
> +++ b/net/sunrpc/Makefile
> @@ -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
> diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
> index 36c64ef460cf..602259baebcc 100644
> --- a/net/sunrpc/clnt.c
> +++ b/net/sunrpc/clnt.c
> @@ -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;
>
> diff --git a/net/sunrpc/debugfs.c b/net/sunrpc/debugfs.c
> new file mode 100644
> index 000000000000..4062e8ca7363
> --- /dev/null
> +++ b/net/sunrpc/debugfs.c
> @@ -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));
> +
> + 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...


> +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;
> +}
> diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
> index f632e476ab6c..e37fbed87956 100644
> --- a/net/sunrpc/sunrpc_syms.c
> +++ b/net/sunrpc/sunrpc_syms.c
> @@ -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);


--
Jeff Layton <[email protected]>

2014-11-26 19:44:52

by Jeff Layton

[permalink] [raw]
Subject: [PATCH v3 0/5] sunrpc: add some debugfs files for dumping task and xprt info

v3:
- 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

--
2.1.0


2014-11-26 19:44:54

by Jeff Layton

[permalink] [raw]
Subject: [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.

Signed-off-by: Jeff Layton <[email protected]>
---
fs/lockd/svclock.c | 2 +-
include/linux/lockd/debug.h | 6 +-----
2 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 13db95f54176..56598742dde4 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -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)
{
/*
diff --git a/include/linux/lockd/debug.h b/include/linux/lockd/debug.h
index 257d3779f2ab..0ca8109934e4 100644
--- a/include/linux/lockd/debug.h
+++ b/include/linux/lockd/debug.h
@@ -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)
--
2.1.0


2014-11-26 19:44:56

by Jeff Layton

[permalink] [raw]
Subject: [PATCH v3 2/5] sunrpc: eliminate RPC_DEBUG

It's always set to whatever CONFIG_SUNRPC_DEBUG is, so just use that.

Signed-off-by: Jeff Layton <[email protected]>
---
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(-)

diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index 8e030075fe79..a7cbb570cc5c 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -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 */
diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
index 9385bd74c860..51143757b8f7 100644
--- a/include/linux/sunrpc/debug.h
+++ b/include/linux/sunrpc/debug.h
@@ -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
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 1a8959944c5f..fecdbf1b4797 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -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");
diff --git a/include/uapi/linux/nfsd/debug.h b/include/uapi/linux/nfsd/debug.h
index a6f453c740b8..1fdc95bb2375 100644
--- a/include/uapi/linux/nfsd/debug.h
+++ b/include/uapi/linux/nfsd/debug.h
@@ -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

diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 383eb919ac0b..47f38be4155f 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -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;
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c
index 6f6b829c9e8e..41248b1820c7 100644
--- a/net/sunrpc/auth_generic.c
+++ b/net/sunrpc/auth_generic.c
@@ -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

diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 53ed8d3f8897..dace13d7638e 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -66,7 +66,7 @@ static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED;
#define GSS_KEY_EXPIRE_TIMEO 240
static 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

diff --git a/net/sunrpc/auth_gss/gss_generic_token.c b/net/sunrpc/auth_gss/gss_generic_token.c
index c586e92bcf76..254defe446a7 100644
--- a/net/sunrpc/auth_gss/gss_generic_token.c
+++ b/net/sunrpc/auth_gss/gss_generic_token.c
@@ -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

diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index f5ed9f6ece06..b5408e8a37f2 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -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

diff --git a/net/sunrpc/auth_gss/gss_krb5_keys.c b/net/sunrpc/auth_gss/gss_krb5_keys.c
index 24589bd2a4b6..234fa8d0fd9b 100644
--- a/net/sunrpc/auth_gss/gss_krb5_keys.c
+++ b/net/sunrpc/auth_gss/gss_krb5_keys.c
@@ -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

diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 0d3c158ef8fa..28db442a0034 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -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

diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index 42768e5c3994..1d74d653e6c0 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -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

diff --git a/net/sunrpc/auth_gss/gss_krb5_seqnum.c b/net/sunrpc/auth_gss/gss_krb5_seqnum.c
index 62ac90c62cb1..20d55c793eb6 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seqnum.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seqnum.c
@@ -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

diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
index 6c981ddc19f8..dcf9515d9aef 100644
--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
@@ -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

diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index 4b614c604fe0..ca7e92a32f84 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -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

diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index 92d5ab99fbf3..7063d856a598 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -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

diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.h b/net/sunrpc/auth_gss/gss_rpc_xdr.h
index 685a688f3d8a..9d88c6239f01 100644
--- a/net/sunrpc/auth_gss/gss_rpc_xdr.h
+++ b/net/sunrpc/auth_gss/gss_rpc_xdr.h
@@ -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

diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index c548ab213f76..de856ddf5fed 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -51,7 +51,7 @@
#include "gss_rpc_upcall.h"


-#ifdef RPC_DEBUG
+#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
# define RPCDBG_FACILITY RPCDBG_AUTH
#endif

diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c
index 712c123e04e9..c2a2b584a056 100644
--- a/net/sunrpc/auth_null.c
+++ b/net/sunrpc/auth_null.c
@@ -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
};
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
index d5d692366294..4feda2d0a833 100644
--- a/net/sunrpc/auth_unix.c
+++ b/net/sunrpc/auth_unix.c
@@ -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

diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c
index 9761a0da964d..651f49ab601f 100644
--- a/net/sunrpc/backchannel_rqst.c
+++ b/net/sunrpc/backchannel_rqst.c
@@ -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

diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 9acd6ce88db7..36c64ef460cf 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -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- "
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 1891a1022c17..05202012bcfc 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -32,7 +32,7 @@

#include "netns.h"

-#ifdef RPC_DEBUG
+#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
# define RPCDBG_FACILITY RPCDBG_BIND
#endif

diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index fe3441abdbe5..574b2977fc4b 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -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;
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index cd30120de9e4..f632e476ab6c 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -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 */
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 371a8bbb43d6..2783fd80c229 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -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, ...)
{
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c
index c99c58e2ee66..887f0183b4c6 100644
--- a/net/sunrpc/sysctl.c
+++ b/net/sunrpc/sysctl.c
@@ -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[];
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 1b2e5e616cae..894d071426b2 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -57,7 +57,7 @@
* Local variables
*/

-#ifdef RPC_DEBUG
+#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
# define RPCDBG_FACILITY RPCDBG_XPRT
#endif

diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c
index 6166c985fe24..df01d124936c 100644
--- a/net/sunrpc/xprtrdma/rpc_rdma.c
+++ b/net/sunrpc/xprtrdma/rpc_rdma.c
@@ -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 */
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c
index 6a4615dd0261..ef58ebadb3ae 100644
--- a/net/sunrpc/xprtrdma/transport.c
+++ b/net/sunrpc/xprtrdma/transport.c
@@ -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
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
index 61c41298b4ea..b92b04083e40 100644
--- a/net/sunrpc/xprtrdma/verbs.c
+++ b/net/sunrpc/xprtrdma/verbs.c
@@ -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;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 31c015196a29..87ce7e8bb8dc 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -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;
--
2.1.0


2014-11-26 19:44:57

by Jeff Layton

[permalink] [raw]
Subject: [PATCH v3 3/5] sunrpc: eliminate RPC_TRACEPOINTS

It's always set to the same value as CONFIG_TRACEPOINTS, so we can just
use that instead.

Signed-off-by: Jeff Layton <[email protected]>
---
include/linux/sunrpc/debug.h | 9 ---------
include/linux/sunrpc/sched.h | 6 +++---
net/sunrpc/sched.c | 2 +-
3 files changed, 4 insertions(+), 13 deletions(-)

diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
index 51143757b8f7..43f38ee9668c 100644
--- a/include/linux/sunrpc/debug.h
+++ b/include/linux/sunrpc/debug.h
@@ -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
*/
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index fecdbf1b4797..5f1e6bd4c316 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -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");
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 574b2977fc4b..d20f2329eea3 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -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;
--
2.1.0


2014-11-26 19:44:58

by Jeff Layton

[permalink] [raw]
Subject: [PATCH v3 4/5] 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 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 | 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

diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 70736b98c721..d86acc63b25f 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -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 */
diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
index 43f38ee9668c..835339707094 100644
--- a/include/linux/sunrpc/debug.h
+++ b/include/linux/sunrpc/debug.h
@@ -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_ */
diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
index 0754d0f466d2..fb78117b896c 100644
--- a/net/sunrpc/Kconfig
+++ b/net/sunrpc/Kconfig
@@ -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
diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
index e5a7a1cac8f3..15e6f6c23c5d 100644
--- a/net/sunrpc/Makefile
+++ b/net/sunrpc/Makefile
@@ -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
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 36c64ef460cf..05da12a33945 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -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;

diff --git a/net/sunrpc/debugfs.c b/net/sunrpc/debugfs.c
new file mode 100644
index 000000000000..3d7745683ca3
--- /dev/null
+++ b/net/sunrpc/debugfs.c
@@ -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;
+}
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index f632e476ab6c..e37fbed87956 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -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);
--
2.1.0


2014-11-26 20:14:00

by Anna Schumaker

[permalink] [raw]
Subject: Re: [PATCH v3 4/5] sunrpc: add debugfs file for displaying client rpc_task queue

Hi Jeff,

On 11/26/2014 02:44 PM, Jeff Layton 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.

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

>
> 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.c
>
> diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
> index 70736b98c721..d86acc63b25f 100644
> --- a/include/linux/sunrpc/clnt.h
> +++ b/include/linux/sunrpc/clnt.h
> @@ -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 */
> diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
> index 43f38ee9668c..835339707094 100644
> --- a/include/linux/sunrpc/debug.h
> +++ b/include/linux/sunrpc/debug.h
> @@ -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_ */
> diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
> index 0754d0f466d2..fb78117b896c 100644
> --- a/net/sunrpc/Kconfig
> +++ b/net/sunrpc/Kconfig
> @@ -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
> diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
> index e5a7a1cac8f3..15e6f6c23c5d 100644
> --- a/net/sunrpc/Makefile
> +++ b/net/sunrpc/Makefile
> @@ -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
> diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
> index 36c64ef460cf..05da12a33945 100644
> --- a/net/sunrpc/clnt.c
> +++ b/net/sunrpc/clnt.c
> @@ -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;
>
> diff --git a/net/sunrpc/debugfs.c b/net/sunrpc/debugfs.c
> new file mode 100644
> index 000000000000..3d7745683ca3
> --- /dev/null
> +++ b/net/sunrpc/debugfs.c
> @@ -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;
> +}
> diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
> index f632e476ab6c..e37fbed87956 100644
> --- a/net/sunrpc/sunrpc_syms.c
> +++ b/net/sunrpc/sunrpc_syms.c
> @@ -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);
>


2014-11-26 20:15:45

by Anna Schumaker

[permalink] [raw]
Subject: Re: [PATCH v3 4/5] sunrpc: add debugfs file for displaying client rpc_task queue

On 11/26/2014 03:13 PM, Anna Schumaker wrote:
> Hi Jeff,
>
> On 11/26/2014 02:44 PM, Jeff Layton 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.
>
> 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

>
> Anna
>
>>
>> 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.c
>>
>> diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
>> index 70736b98c721..d86acc63b25f 100644
>> --- a/include/linux/sunrpc/clnt.h
>> +++ b/include/linux/sunrpc/clnt.h
>> @@ -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 */
>> diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
>> index 43f38ee9668c..835339707094 100644
>> --- a/include/linux/sunrpc/debug.h
>> +++ b/include/linux/sunrpc/debug.h
>> @@ -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_ */
>> diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
>> index 0754d0f466d2..fb78117b896c 100644
>> --- a/net/sunrpc/Kconfig
>> +++ b/net/sunrpc/Kconfig
>> @@ -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
>> diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
>> index e5a7a1cac8f3..15e6f6c23c5d 100644
>> --- a/net/sunrpc/Makefile
>> +++ b/net/sunrpc/Makefile
>> @@ -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
>> diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
>> index 36c64ef460cf..05da12a33945 100644
>> --- a/net/sunrpc/clnt.c
>> +++ b/net/sunrpc/clnt.c
>> @@ -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;
>>
>> diff --git a/net/sunrpc/debugfs.c b/net/sunrpc/debugfs.c
>> new file mode 100644
>> index 000000000000..3d7745683ca3
>> --- /dev/null
>> +++ b/net/sunrpc/debugfs.c
>> @@ -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;
>> +}
>> diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
>> index f632e476ab6c..e37fbed87956 100644
>> --- a/net/sunrpc/sunrpc_syms.c
>> +++ b/net/sunrpc/sunrpc_syms.c
>> @@ -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);
>>
>


2014-11-26 20:52:19

by Jeff Layton

[permalink] [raw]
Subject: Re: [PATCH v3 4/5] sunrpc: add debugfs file for displaying client rpc_task queue

On Wed, 26 Nov 2014 15:15:42 -0500
Anna Schumaker <[email protected]> wrote:

> On 11/26/2014 03:13 PM, Anna Schumaker wrote:
> > Hi Jeff,
> >
> > On 11/26/2014 02:44 PM, Jeff Layton 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.
> >
> > 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.

> >
> > Anna
> >
> >>
> >> 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.c
> >>
> >> diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
> >> index 70736b98c721..d86acc63b25f 100644
> >> --- a/include/linux/sunrpc/clnt.h
> >> +++ b/include/linux/sunrpc/clnt.h
> >> @@ -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 */
> >> diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
> >> index 43f38ee9668c..835339707094 100644
> >> --- a/include/linux/sunrpc/debug.h
> >> +++ b/include/linux/sunrpc/debug.h
> >> @@ -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_ */
> >> diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
> >> index 0754d0f466d2..fb78117b896c 100644
> >> --- a/net/sunrpc/Kconfig
> >> +++ b/net/sunrpc/Kconfig
> >> @@ -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
> >> diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
> >> index e5a7a1cac8f3..15e6f6c23c5d 100644
> >> --- a/net/sunrpc/Makefile
> >> +++ b/net/sunrpc/Makefile
> >> @@ -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
> >> diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
> >> index 36c64ef460cf..05da12a33945 100644
> >> --- a/net/sunrpc/clnt.c
> >> +++ b/net/sunrpc/clnt.c
> >> @@ -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;
> >>
> >> diff --git a/net/sunrpc/debugfs.c b/net/sunrpc/debugfs.c
> >> new file mode 100644
> >> index 000000000000..3d7745683ca3
> >> --- /dev/null
> >> +++ b/net/sunrpc/debugfs.c
> >> @@ -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;
> >> +}
> >> diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
> >> index f632e476ab6c..e37fbed87956 100644
> >> --- a/net/sunrpc/sunrpc_syms.c
> >> +++ b/net/sunrpc/sunrpc_syms.c
> >> @@ -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);
> >>
> >
>


--
Jeff Layton <[email protected]>

2014-11-26 19:45:00

by Jeff Layton

[permalink] [raw]
Subject: [PATCH v3 5/5] sunrpc: add a debugfs rpc_xprt directory with an info file in it

Add 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.

Signed-off-by: Jeff Layton <[email protected]>
---
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(-)

diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
index 835339707094..c57d8ea0716c 100644
--- a/include/linux/sunrpc/debug.h
+++ b/include/linux/sunrpc/debug.h
@@ -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_ */
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index cf391eef2e6d..9d27ac45b909 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -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)
diff --git a/net/sunrpc/debugfs.c b/net/sunrpc/debugfs.c
index 3d7745683ca3..e811f390f9f6 100644
--- a/net/sunrpc/debugfs.c
+++ b/net/sunrpc/debugfs.c
@@ -11,6 +11,7 @@

static struct dentry *topdir;
static struct dentry *rpc_clnt_dir;
+static struct dentry *rpc_xprt_dir;

struct rpc_clnt_iter {
struct rpc_clnt *clnt;
@@ -131,8 +132,8 @@ static const struct file_operations tasks_fops = {
int
rpc_clnt_debugfs_register(struct rpc_clnt *clnt)
{
- int len;
- char name[9]; /* 8 for hex digits + NULL terminator */
+ int len, err;
+ char name[24]; /* enough for "../../rpc_xprt/ + 8 hex digits + NULL */

/* Already registered? */
if (clnt->cl_debugfs)
@@ -148,14 +149,28 @@ rpc_clnt_debugfs_register(struct rpc_clnt *clnt)
return -ENOMEM;

/* make tasks file */
+ err = -ENOMEM;
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;
- }
+ clnt, &tasks_fops))
+ goto out_err;
+
+ err = -EINVAL;
+ rcu_read_lock();
+ len = snprintf(name, sizeof(name), "../../rpc_xprt/%s",
+ rcu_dereference(clnt->cl_xprt)->debugfs->d_name.name);
+ rcu_read_unlock();
+ if (len >= sizeof(name))
+ goto out_err;
+
+ err = -ENOMEM;
+ if (!debugfs_create_symlink("xprt", clnt->cl_debugfs, name))
+ goto out_err;

return 0;
+out_err:
+ debugfs_remove_recursive(clnt->cl_debugfs);
+ clnt->cl_debugfs = NULL;
+ return err;
}

void
@@ -165,6 +180,88 @@ rpc_clnt_debugfs_unregister(struct rpc_clnt *clnt)
clnt->cl_debugfs = NULL;
}

+static int
+xprt_info_show(struct seq_file *f, void *v)
+{
+ struct rpc_xprt *xprt = f->private;
+
+ seq_printf(f, "netid: %s\n", xprt->address_strings[RPC_DISPLAY_NETID]);
+ seq_printf(f, "addr: %s\n", xprt->address_strings[RPC_DISPLAY_ADDR]);
+ seq_printf(f, "port: %s\n", xprt->address_strings[RPC_DISPLAY_PORT]);
+ seq_printf(f, "state: 0x%lx\n", xprt->state);
+ return 0;
+}
+
+static int
+xprt_info_open(struct inode *inode, struct file *filp)
+{
+ int ret;
+ struct rpc_xprt *xprt = inode->i_private;
+
+ ret = single_open(filp, xprt_info_show, xprt);
+
+ if (!ret) {
+ if (!xprt_get(xprt)) {
+ single_release(inode, filp);
+ ret = -EINVAL;
+ }
+ }
+ return ret;
+}
+
+static int
+xprt_info_release(struct inode *inode, struct file *filp)
+{
+ struct rpc_xprt *xprt = inode->i_private;
+
+ xprt_put(xprt);
+ return single_release(inode, filp);
+}
+
+static const struct file_operations xprt_info_fops = {
+ .owner = THIS_MODULE,
+ .open = xprt_info_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = xprt_info_release,
+};
+
+int
+rpc_xprt_debugfs_register(struct rpc_xprt *xprt)
+{
+ int len, id;
+ static atomic_t cur_id;
+ char name[9]; /* 8 hex digits + NULL term */
+
+ id = (unsigned int)atomic_inc_return(&cur_id);
+
+ len = snprintf(name, sizeof(name), "%x", id);
+ if (len >= sizeof(name))
+ return -EINVAL;
+
+ /* make the per-client dir */
+ xprt->debugfs = debugfs_create_dir(name, rpc_xprt_dir);
+ if (!xprt->debugfs)
+ return -ENOMEM;
+
+ /* make tasks file */
+ if (!debugfs_create_file("info", S_IFREG | S_IRUSR, xprt->debugfs,
+ xprt, &xprt_info_fops)) {
+ debugfs_remove_recursive(xprt->debugfs);
+ xprt->debugfs = NULL;
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void
+rpc_xprt_debugfs_unregister(struct rpc_xprt *xprt)
+{
+ debugfs_remove_recursive(xprt->debugfs);
+ xprt->debugfs = NULL;
+}
+
void __exit
sunrpc_debugfs_exit(void)
{
@@ -182,6 +279,10 @@ sunrpc_debugfs_init(void)
if (!rpc_clnt_dir)
goto out_remove;

+ rpc_xprt_dir = debugfs_create_dir("rpc_xprt", topdir);
+ if (!rpc_xprt_dir)
+ goto out_remove;
+
return 0;
out_remove:
debugfs_remove_recursive(topdir);
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 894d071426b2..ebbefad21a37 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -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);
--
2.1.0