.. | .. |
---|
1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
---|
2 | | -/** |
---|
| 2 | +/* |
---|
3 | 3 | * debugfs interface for sunrpc |
---|
4 | 4 | * |
---|
5 | 5 | * (c) 2014 Jeff Layton <jlayton@primarydata.com> |
---|
.. | .. |
---|
11 | 11 | #include "netns.h" |
---|
12 | 12 | |
---|
13 | 13 | static struct dentry *topdir; |
---|
14 | | -static struct dentry *rpc_fault_dir; |
---|
15 | 14 | static struct dentry *rpc_clnt_dir; |
---|
16 | 15 | static struct dentry *rpc_xprt_dir; |
---|
17 | 16 | |
---|
.. | .. |
---|
33 | 32 | |
---|
34 | 33 | seq_printf(f, "%5u %04x %6d 0x%x 0x%x %8ld %ps %sv%u %s a:%ps q:%s\n", |
---|
35 | 34 | task->tk_pid, task->tk_flags, task->tk_status, |
---|
36 | | - clnt->cl_clid, xid, task->tk_timeout, task->tk_ops, |
---|
| 35 | + clnt->cl_clid, xid, rpc_task_timeout(task), task->tk_ops, |
---|
37 | 36 | clnt->cl_program->name, clnt->cl_vers, rpc_proc_name(task), |
---|
38 | 37 | task->tk_action, rpc_waitq); |
---|
39 | 38 | return 0; |
---|
.. | .. |
---|
118 | 117 | .release = tasks_release, |
---|
119 | 118 | }; |
---|
120 | 119 | |
---|
| 120 | +static int do_xprt_debugfs(struct rpc_clnt *clnt, struct rpc_xprt *xprt, void *numv) |
---|
| 121 | +{ |
---|
| 122 | + int len; |
---|
| 123 | + char name[24]; /* enough for "../../rpc_xprt/ + 8 hex digits + NULL */ |
---|
| 124 | + char link[9]; /* enough for 8 hex digits + NULL */ |
---|
| 125 | + int *nump = numv; |
---|
| 126 | + |
---|
| 127 | + if (IS_ERR_OR_NULL(xprt->debugfs)) |
---|
| 128 | + return 0; |
---|
| 129 | + len = snprintf(name, sizeof(name), "../../rpc_xprt/%s", |
---|
| 130 | + xprt->debugfs->d_name.name); |
---|
| 131 | + if (len >= sizeof(name)) |
---|
| 132 | + return -1; |
---|
| 133 | + if (*nump == 0) |
---|
| 134 | + strcpy(link, "xprt"); |
---|
| 135 | + else { |
---|
| 136 | + len = snprintf(link, sizeof(link), "xprt%d", *nump); |
---|
| 137 | + if (len >= sizeof(link)) |
---|
| 138 | + return -1; |
---|
| 139 | + } |
---|
| 140 | + debugfs_create_symlink(link, clnt->cl_debugfs, name); |
---|
| 141 | + (*nump)++; |
---|
| 142 | + return 0; |
---|
| 143 | +} |
---|
| 144 | + |
---|
121 | 145 | void |
---|
122 | 146 | rpc_clnt_debugfs_register(struct rpc_clnt *clnt) |
---|
123 | 147 | { |
---|
124 | 148 | int len; |
---|
125 | | - char name[24]; /* enough for "../../rpc_xprt/ + 8 hex digits + NULL */ |
---|
126 | | - struct rpc_xprt *xprt; |
---|
127 | | - |
---|
128 | | - /* Already registered? */ |
---|
129 | | - if (clnt->cl_debugfs || !rpc_clnt_dir) |
---|
130 | | - return; |
---|
| 149 | + char name[9]; /* enough for 8 hex digits + NULL */ |
---|
| 150 | + int xprtnum = 0; |
---|
131 | 151 | |
---|
132 | 152 | len = snprintf(name, sizeof(name), "%x", clnt->cl_clid); |
---|
133 | 153 | if (len >= sizeof(name)) |
---|
.. | .. |
---|
135 | 155 | |
---|
136 | 156 | /* make the per-client dir */ |
---|
137 | 157 | clnt->cl_debugfs = debugfs_create_dir(name, rpc_clnt_dir); |
---|
138 | | - if (!clnt->cl_debugfs) |
---|
139 | | - return; |
---|
140 | 158 | |
---|
141 | 159 | /* make tasks file */ |
---|
142 | | - if (!debugfs_create_file("tasks", S_IFREG | 0400, clnt->cl_debugfs, |
---|
143 | | - clnt, &tasks_fops)) |
---|
144 | | - goto out_err; |
---|
| 160 | + debugfs_create_file("tasks", S_IFREG | 0400, clnt->cl_debugfs, clnt, |
---|
| 161 | + &tasks_fops); |
---|
145 | 162 | |
---|
146 | | - rcu_read_lock(); |
---|
147 | | - xprt = rcu_dereference(clnt->cl_xprt); |
---|
148 | | - /* no "debugfs" dentry? Don't bother with the symlink. */ |
---|
149 | | - if (!xprt->debugfs) { |
---|
150 | | - rcu_read_unlock(); |
---|
151 | | - return; |
---|
152 | | - } |
---|
153 | | - len = snprintf(name, sizeof(name), "../../rpc_xprt/%s", |
---|
154 | | - xprt->debugfs->d_name.name); |
---|
155 | | - rcu_read_unlock(); |
---|
156 | | - |
---|
157 | | - if (len >= sizeof(name)) |
---|
158 | | - goto out_err; |
---|
159 | | - |
---|
160 | | - if (!debugfs_create_symlink("xprt", clnt->cl_debugfs, name)) |
---|
161 | | - goto out_err; |
---|
162 | | - |
---|
163 | | - return; |
---|
164 | | -out_err: |
---|
165 | | - debugfs_remove_recursive(clnt->cl_debugfs); |
---|
166 | | - clnt->cl_debugfs = NULL; |
---|
| 163 | + rpc_clnt_iterate_for_each_xprt(clnt, do_xprt_debugfs, &xprtnum); |
---|
167 | 164 | } |
---|
168 | 165 | |
---|
169 | 166 | void |
---|
.. | .. |
---|
226 | 223 | static atomic_t cur_id; |
---|
227 | 224 | char name[9]; /* 8 hex digits + NULL term */ |
---|
228 | 225 | |
---|
229 | | - if (!rpc_xprt_dir) |
---|
230 | | - return; |
---|
231 | | - |
---|
232 | 226 | id = (unsigned int)atomic_inc_return(&cur_id); |
---|
233 | 227 | |
---|
234 | 228 | len = snprintf(name, sizeof(name), "%x", id); |
---|
.. | .. |
---|
237 | 231 | |
---|
238 | 232 | /* make the per-client dir */ |
---|
239 | 233 | xprt->debugfs = debugfs_create_dir(name, rpc_xprt_dir); |
---|
240 | | - if (!xprt->debugfs) |
---|
241 | | - return; |
---|
242 | 234 | |
---|
243 | 235 | /* make tasks file */ |
---|
244 | | - if (!debugfs_create_file("info", S_IFREG | 0400, xprt->debugfs, |
---|
245 | | - xprt, &xprt_info_fops)) { |
---|
246 | | - debugfs_remove_recursive(xprt->debugfs); |
---|
247 | | - xprt->debugfs = NULL; |
---|
248 | | - } |
---|
| 236 | + debugfs_create_file("info", S_IFREG | 0400, xprt->debugfs, xprt, |
---|
| 237 | + &xprt_info_fops); |
---|
249 | 238 | |
---|
250 | 239 | atomic_set(&xprt->inject_disconnect, rpc_inject_disconnect); |
---|
251 | 240 | } |
---|
.. | .. |
---|
308 | 297 | .release = fault_release, |
---|
309 | 298 | }; |
---|
310 | 299 | |
---|
311 | | -static struct dentry * |
---|
312 | | -inject_fault_dir(struct dentry *topdir) |
---|
313 | | -{ |
---|
314 | | - struct dentry *faultdir; |
---|
315 | | - |
---|
316 | | - faultdir = debugfs_create_dir("inject_fault", topdir); |
---|
317 | | - if (!faultdir) |
---|
318 | | - return NULL; |
---|
319 | | - |
---|
320 | | - if (!debugfs_create_file("disconnect", S_IFREG | 0400, faultdir, |
---|
321 | | - NULL, &fault_disconnect_fops)) |
---|
322 | | - return NULL; |
---|
323 | | - |
---|
324 | | - return faultdir; |
---|
325 | | -} |
---|
326 | | - |
---|
327 | 300 | void __exit |
---|
328 | 301 | sunrpc_debugfs_exit(void) |
---|
329 | 302 | { |
---|
330 | 303 | debugfs_remove_recursive(topdir); |
---|
331 | 304 | topdir = NULL; |
---|
332 | | - rpc_fault_dir = NULL; |
---|
333 | 305 | rpc_clnt_dir = NULL; |
---|
334 | 306 | rpc_xprt_dir = NULL; |
---|
335 | 307 | } |
---|
.. | .. |
---|
337 | 309 | void __init |
---|
338 | 310 | sunrpc_debugfs_init(void) |
---|
339 | 311 | { |
---|
340 | | - topdir = debugfs_create_dir("sunrpc", NULL); |
---|
341 | | - if (!topdir) |
---|
342 | | - return; |
---|
| 312 | + struct dentry *rpc_fault_dir; |
---|
343 | 313 | |
---|
344 | | - rpc_fault_dir = inject_fault_dir(topdir); |
---|
345 | | - if (!rpc_fault_dir) |
---|
346 | | - goto out_remove; |
---|
| 314 | + topdir = debugfs_create_dir("sunrpc", NULL); |
---|
347 | 315 | |
---|
348 | 316 | rpc_clnt_dir = debugfs_create_dir("rpc_clnt", topdir); |
---|
349 | | - if (!rpc_clnt_dir) |
---|
350 | | - goto out_remove; |
---|
351 | 317 | |
---|
352 | 318 | rpc_xprt_dir = debugfs_create_dir("rpc_xprt", topdir); |
---|
353 | | - if (!rpc_xprt_dir) |
---|
354 | | - goto out_remove; |
---|
355 | 319 | |
---|
356 | | - return; |
---|
357 | | -out_remove: |
---|
358 | | - debugfs_remove_recursive(topdir); |
---|
359 | | - topdir = NULL; |
---|
360 | | - rpc_fault_dir = NULL; |
---|
361 | | - rpc_clnt_dir = NULL; |
---|
| 320 | + rpc_fault_dir = debugfs_create_dir("inject_fault", topdir); |
---|
| 321 | + |
---|
| 322 | + debugfs_create_file("disconnect", S_IFREG | 0400, rpc_fault_dir, NULL, |
---|
| 323 | + &fault_disconnect_fops); |
---|
362 | 324 | } |
---|