Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 388f0c77 authored by Jeff Layton's avatar Jeff Layton Committed by Trond Myklebust
Browse files

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: default avatarJeff Layton <jlayton@primarydata.com>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent b4b9d2cc
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -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_ */
+3 −0
Original line number Diff line number Diff line
@@ -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)
+108 −7
Original line number Diff line number Diff line
@@ -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,10 +149,106 @@ 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)) {
				 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
rpc_clnt_debugfs_unregister(struct rpc_clnt *clnt)
{
	debugfs_remove_recursive(clnt->cl_debugfs);
	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;
	}

@@ -159,10 +256,10 @@ rpc_clnt_debugfs_register(struct rpc_clnt *clnt)
}

void
rpc_clnt_debugfs_unregister(struct rpc_clnt *clnt)
rpc_xprt_debugfs_unregister(struct rpc_xprt *xprt)
{
	debugfs_remove_recursive(clnt->cl_debugfs);
	clnt->cl_debugfs = NULL;
	debugfs_remove_recursive(xprt->debugfs);
	xprt->debugfs = NULL;
}

void __exit
@@ -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);
+8 −0
Original line number Diff line number Diff line
@@ -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 @@ struct rpc_xprt *xprt_create_transport(struct xprt_create *args)
		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);