0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/debugfs.h>
0009 #include <linux/sunrpc/sched.h>
0010 #include <linux/sunrpc/clnt.h>
0011
0012 #include "netns.h"
0013 #include "fail.h"
0014
0015 static struct dentry *topdir;
0016 static struct dentry *rpc_clnt_dir;
0017 static struct dentry *rpc_xprt_dir;
0018
0019 static int
0020 tasks_show(struct seq_file *f, void *v)
0021 {
0022 u32 xid = 0;
0023 struct rpc_task *task = v;
0024 struct rpc_clnt *clnt = task->tk_client;
0025 const char *rpc_waitq = "none";
0026
0027 if (RPC_IS_QUEUED(task))
0028 rpc_waitq = rpc_qname(task->tk_waitqueue);
0029
0030 if (task->tk_rqstp)
0031 xid = be32_to_cpu(task->tk_rqstp->rq_xid);
0032
0033 seq_printf(f, "%5u %04x %6d 0x%x 0x%x %8ld %ps %sv%u %s a:%ps q:%s\n",
0034 task->tk_pid, task->tk_flags, task->tk_status,
0035 clnt->cl_clid, xid, rpc_task_timeout(task), task->tk_ops,
0036 clnt->cl_program->name, clnt->cl_vers, rpc_proc_name(task),
0037 task->tk_action, rpc_waitq);
0038 return 0;
0039 }
0040
0041 static void *
0042 tasks_start(struct seq_file *f, loff_t *ppos)
0043 __acquires(&clnt->cl_lock)
0044 {
0045 struct rpc_clnt *clnt = f->private;
0046 loff_t pos = *ppos;
0047 struct rpc_task *task;
0048
0049 spin_lock(&clnt->cl_lock);
0050 list_for_each_entry(task, &clnt->cl_tasks, tk_task)
0051 if (pos-- == 0)
0052 return task;
0053 return NULL;
0054 }
0055
0056 static void *
0057 tasks_next(struct seq_file *f, void *v, loff_t *pos)
0058 {
0059 struct rpc_clnt *clnt = f->private;
0060 struct rpc_task *task = v;
0061 struct list_head *next = task->tk_task.next;
0062
0063 ++*pos;
0064
0065
0066 if (next == &clnt->cl_tasks)
0067 return NULL;
0068 return list_entry(next, struct rpc_task, tk_task);
0069 }
0070
0071 static void
0072 tasks_stop(struct seq_file *f, void *v)
0073 __releases(&clnt->cl_lock)
0074 {
0075 struct rpc_clnt *clnt = f->private;
0076 spin_unlock(&clnt->cl_lock);
0077 }
0078
0079 static const struct seq_operations tasks_seq_operations = {
0080 .start = tasks_start,
0081 .next = tasks_next,
0082 .stop = tasks_stop,
0083 .show = tasks_show,
0084 };
0085
0086 static int tasks_open(struct inode *inode, struct file *filp)
0087 {
0088 int ret = seq_open(filp, &tasks_seq_operations);
0089 if (!ret) {
0090 struct seq_file *seq = filp->private_data;
0091 struct rpc_clnt *clnt = seq->private = inode->i_private;
0092
0093 if (!refcount_inc_not_zero(&clnt->cl_count)) {
0094 seq_release(inode, filp);
0095 ret = -EINVAL;
0096 }
0097 }
0098
0099 return ret;
0100 }
0101
0102 static int
0103 tasks_release(struct inode *inode, struct file *filp)
0104 {
0105 struct seq_file *seq = filp->private_data;
0106 struct rpc_clnt *clnt = seq->private;
0107
0108 rpc_release_client(clnt);
0109 return seq_release(inode, filp);
0110 }
0111
0112 static const struct file_operations tasks_fops = {
0113 .owner = THIS_MODULE,
0114 .open = tasks_open,
0115 .read = seq_read,
0116 .llseek = seq_lseek,
0117 .release = tasks_release,
0118 };
0119
0120 static int do_xprt_debugfs(struct rpc_clnt *clnt, struct rpc_xprt *xprt, void *numv)
0121 {
0122 int len;
0123 char name[24];
0124 char link[9];
0125 int *nump = numv;
0126
0127 if (IS_ERR_OR_NULL(xprt->debugfs))
0128 return 0;
0129 len = snprintf(name, sizeof(name), "../../rpc_xprt/%s",
0130 xprt->debugfs->d_name.name);
0131 if (len >= sizeof(name))
0132 return -1;
0133 if (*nump == 0)
0134 strcpy(link, "xprt");
0135 else {
0136 len = snprintf(link, sizeof(link), "xprt%d", *nump);
0137 if (len >= sizeof(link))
0138 return -1;
0139 }
0140 debugfs_create_symlink(link, clnt->cl_debugfs, name);
0141 (*nump)++;
0142 return 0;
0143 }
0144
0145 void
0146 rpc_clnt_debugfs_register(struct rpc_clnt *clnt)
0147 {
0148 int len;
0149 char name[9];
0150 int xprtnum = 0;
0151
0152 len = snprintf(name, sizeof(name), "%x", clnt->cl_clid);
0153 if (len >= sizeof(name))
0154 return;
0155
0156
0157 clnt->cl_debugfs = debugfs_create_dir(name, rpc_clnt_dir);
0158
0159
0160 debugfs_create_file("tasks", S_IFREG | 0400, clnt->cl_debugfs, clnt,
0161 &tasks_fops);
0162
0163 rpc_clnt_iterate_for_each_xprt(clnt, do_xprt_debugfs, &xprtnum);
0164 }
0165
0166 void
0167 rpc_clnt_debugfs_unregister(struct rpc_clnt *clnt)
0168 {
0169 debugfs_remove_recursive(clnt->cl_debugfs);
0170 clnt->cl_debugfs = NULL;
0171 }
0172
0173 static int
0174 xprt_info_show(struct seq_file *f, void *v)
0175 {
0176 struct rpc_xprt *xprt = f->private;
0177
0178 seq_printf(f, "netid: %s\n", xprt->address_strings[RPC_DISPLAY_NETID]);
0179 seq_printf(f, "addr: %s\n", xprt->address_strings[RPC_DISPLAY_ADDR]);
0180 seq_printf(f, "port: %s\n", xprt->address_strings[RPC_DISPLAY_PORT]);
0181 seq_printf(f, "state: 0x%lx\n", xprt->state);
0182 return 0;
0183 }
0184
0185 static int
0186 xprt_info_open(struct inode *inode, struct file *filp)
0187 {
0188 int ret;
0189 struct rpc_xprt *xprt = inode->i_private;
0190
0191 ret = single_open(filp, xprt_info_show, xprt);
0192
0193 if (!ret) {
0194 if (!xprt_get(xprt)) {
0195 single_release(inode, filp);
0196 ret = -EINVAL;
0197 }
0198 }
0199 return ret;
0200 }
0201
0202 static int
0203 xprt_info_release(struct inode *inode, struct file *filp)
0204 {
0205 struct rpc_xprt *xprt = inode->i_private;
0206
0207 xprt_put(xprt);
0208 return single_release(inode, filp);
0209 }
0210
0211 static const struct file_operations xprt_info_fops = {
0212 .owner = THIS_MODULE,
0213 .open = xprt_info_open,
0214 .read = seq_read,
0215 .llseek = seq_lseek,
0216 .release = xprt_info_release,
0217 };
0218
0219 void
0220 rpc_xprt_debugfs_register(struct rpc_xprt *xprt)
0221 {
0222 int len, id;
0223 static atomic_t cur_id;
0224 char name[9];
0225
0226 id = (unsigned int)atomic_inc_return(&cur_id);
0227
0228 len = snprintf(name, sizeof(name), "%x", id);
0229 if (len >= sizeof(name))
0230 return;
0231
0232
0233 xprt->debugfs = debugfs_create_dir(name, rpc_xprt_dir);
0234
0235
0236 debugfs_create_file("info", S_IFREG | 0400, xprt->debugfs, xprt,
0237 &xprt_info_fops);
0238 }
0239
0240 void
0241 rpc_xprt_debugfs_unregister(struct rpc_xprt *xprt)
0242 {
0243 debugfs_remove_recursive(xprt->debugfs);
0244 xprt->debugfs = NULL;
0245 }
0246
0247 #if IS_ENABLED(CONFIG_FAIL_SUNRPC)
0248 struct fail_sunrpc_attr fail_sunrpc = {
0249 .attr = FAULT_ATTR_INITIALIZER,
0250 };
0251 EXPORT_SYMBOL_GPL(fail_sunrpc);
0252
0253 static void fail_sunrpc_init(void)
0254 {
0255 struct dentry *dir;
0256
0257 dir = fault_create_debugfs_attr("fail_sunrpc", NULL,
0258 &fail_sunrpc.attr);
0259
0260 debugfs_create_bool("ignore-client-disconnect", S_IFREG | 0600, dir,
0261 &fail_sunrpc.ignore_client_disconnect);
0262
0263 debugfs_create_bool("ignore-server-disconnect", S_IFREG | 0600, dir,
0264 &fail_sunrpc.ignore_server_disconnect);
0265
0266 debugfs_create_bool("ignore-cache-wait", S_IFREG | 0600, dir,
0267 &fail_sunrpc.ignore_cache_wait);
0268 }
0269 #else
0270 static void fail_sunrpc_init(void)
0271 {
0272 }
0273 #endif
0274
0275 void __exit
0276 sunrpc_debugfs_exit(void)
0277 {
0278 debugfs_remove_recursive(topdir);
0279 topdir = NULL;
0280 rpc_clnt_dir = NULL;
0281 rpc_xprt_dir = NULL;
0282 }
0283
0284 void __init
0285 sunrpc_debugfs_init(void)
0286 {
0287 topdir = debugfs_create_dir("sunrpc", NULL);
0288
0289 rpc_clnt_dir = debugfs_create_dir("rpc_clnt", topdir);
0290
0291 rpc_xprt_dir = debugfs_create_dir("rpc_xprt", topdir);
0292
0293 fail_sunrpc_init();
0294 }