Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

sunrpc: make debugfs file creation failure non-fatal

v2: gracefully handle the case where some dentry pointers end up NULL
and be more dilligent about zeroing out dentry pointers

We currently have a problem that SELinux policy is being enforced when
creating debugfs files. If a debugfs file is created as a side effect of
doing some syscall, then that creation can fail if the SELinux policy
for that process prevents it.

This seems wrong. We don't do that for files under /proc, for instance,
so Bruce has proposed a patch to fix that.

While discussing that patch however, Greg K.H. stated:

"No kernel code should care / fail if a debugfs function fails, so
please fix up the sunrpc code first."

This patch converts all of the sunrpc debugfs setup code to be void
return functins, and the callers to not look for errors from those
functions.

This should allow rpc_clnt and rpc_xprt creation to work, even if the
kernel fails to create debugfs files for some reason.

Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: "J. Bruce Fields" <bfields@fieldses.org>
Signed-off-by: Jeff Layton <jeff.layton@primarydata.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>

authored by

Jeff Layton and committed by
Trond Myklebust
3f940098 5d05e54a

+41 -47
+9 -9
include/linux/sunrpc/debug.h
··· 60 60 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) 61 61 void rpc_register_sysctl(void); 62 62 void rpc_unregister_sysctl(void); 63 - int sunrpc_debugfs_init(void); 63 + void sunrpc_debugfs_init(void); 64 64 void sunrpc_debugfs_exit(void); 65 - int rpc_clnt_debugfs_register(struct rpc_clnt *); 65 + void rpc_clnt_debugfs_register(struct rpc_clnt *); 66 66 void rpc_clnt_debugfs_unregister(struct rpc_clnt *); 67 - int rpc_xprt_debugfs_register(struct rpc_xprt *); 67 + void rpc_xprt_debugfs_register(struct rpc_xprt *); 68 68 void rpc_xprt_debugfs_unregister(struct rpc_xprt *); 69 69 #else 70 - static inline int 70 + static inline void 71 71 sunrpc_debugfs_init(void) 72 72 { 73 - return 0; 73 + return; 74 74 } 75 75 76 76 static inline void ··· 79 79 return; 80 80 } 81 81 82 - static inline int 82 + static inline void 83 83 rpc_clnt_debugfs_register(struct rpc_clnt *clnt) 84 84 { 85 - return 0; 85 + return; 86 86 } 87 87 88 88 static inline void ··· 91 91 return; 92 92 } 93 93 94 - static inline int 94 + static inline void 95 95 rpc_xprt_debugfs_register(struct rpc_xprt *xprt) 96 96 { 97 - return 0; 97 + return; 98 98 } 99 99 100 100 static inline void
+1 -3
net/sunrpc/clnt.c
··· 303 303 struct super_block *pipefs_sb; 304 304 int err; 305 305 306 - err = rpc_clnt_debugfs_register(clnt); 307 - if (err) 308 - return err; 306 + rpc_clnt_debugfs_register(clnt); 309 307 310 308 pipefs_sb = rpc_get_sb_net(net); 311 309 if (pipefs_sb) {
+29 -23
net/sunrpc/debugfs.c
··· 129 129 .release = tasks_release, 130 130 }; 131 131 132 - int 132 + void 133 133 rpc_clnt_debugfs_register(struct rpc_clnt *clnt) 134 134 { 135 - int len, err; 135 + int len; 136 136 char name[24]; /* enough for "../../rpc_xprt/ + 8 hex digits + NULL */ 137 + struct rpc_xprt *xprt; 137 138 138 139 /* Already registered? */ 139 - if (clnt->cl_debugfs) 140 - return 0; 140 + if (clnt->cl_debugfs || !rpc_clnt_dir) 141 + return; 141 142 142 143 len = snprintf(name, sizeof(name), "%x", clnt->cl_clid); 143 144 if (len >= sizeof(name)) 144 - return -EINVAL; 145 + return; 145 146 146 147 /* make the per-client dir */ 147 148 clnt->cl_debugfs = debugfs_create_dir(name, rpc_clnt_dir); 148 149 if (!clnt->cl_debugfs) 149 - return -ENOMEM; 150 + return; 150 151 151 152 /* make tasks file */ 152 - err = -ENOMEM; 153 153 if (!debugfs_create_file("tasks", S_IFREG | S_IRUSR, clnt->cl_debugfs, 154 154 clnt, &tasks_fops)) 155 155 goto out_err; 156 156 157 - err = -EINVAL; 158 157 rcu_read_lock(); 158 + xprt = rcu_dereference(clnt->cl_xprt); 159 + /* no "debugfs" dentry? Don't bother with the symlink. */ 160 + if (!xprt->debugfs) { 161 + rcu_read_unlock(); 162 + return; 163 + } 159 164 len = snprintf(name, sizeof(name), "../../rpc_xprt/%s", 160 - rcu_dereference(clnt->cl_xprt)->debugfs->d_name.name); 165 + xprt->debugfs->d_name.name); 161 166 rcu_read_unlock(); 167 + 162 168 if (len >= sizeof(name)) 163 169 goto out_err; 164 170 165 - err = -ENOMEM; 166 171 if (!debugfs_create_symlink("xprt", clnt->cl_debugfs, name)) 167 172 goto out_err; 168 173 169 - return 0; 174 + return; 170 175 out_err: 171 176 debugfs_remove_recursive(clnt->cl_debugfs); 172 177 clnt->cl_debugfs = NULL; 173 - return err; 174 178 } 175 179 176 180 void ··· 230 226 .release = xprt_info_release, 231 227 }; 232 228 233 - int 229 + void 234 230 rpc_xprt_debugfs_register(struct rpc_xprt *xprt) 235 231 { 236 232 int len, id; 237 233 static atomic_t cur_id; 238 234 char name[9]; /* 8 hex digits + NULL term */ 239 235 236 + if (!rpc_xprt_dir) 237 + return; 238 + 240 239 id = (unsigned int)atomic_inc_return(&cur_id); 241 240 242 241 len = snprintf(name, sizeof(name), "%x", id); 243 242 if (len >= sizeof(name)) 244 - return -EINVAL; 243 + return; 245 244 246 245 /* make the per-client dir */ 247 246 xprt->debugfs = debugfs_create_dir(name, rpc_xprt_dir); 248 247 if (!xprt->debugfs) 249 - return -ENOMEM; 248 + return; 250 249 251 250 /* make tasks file */ 252 251 if (!debugfs_create_file("info", S_IFREG | S_IRUSR, xprt->debugfs, 253 252 xprt, &xprt_info_fops)) { 254 253 debugfs_remove_recursive(xprt->debugfs); 255 254 xprt->debugfs = NULL; 256 - return -ENOMEM; 257 255 } 258 - 259 - return 0; 260 256 } 261 257 262 258 void ··· 270 266 sunrpc_debugfs_exit(void) 271 267 { 272 268 debugfs_remove_recursive(topdir); 269 + topdir = NULL; 270 + rpc_clnt_dir = NULL; 271 + rpc_xprt_dir = NULL; 273 272 } 274 273 275 - int __init 274 + void __init 276 275 sunrpc_debugfs_init(void) 277 276 { 278 277 topdir = debugfs_create_dir("sunrpc", NULL); 279 278 if (!topdir) 280 - goto out; 279 + return; 281 280 282 281 rpc_clnt_dir = debugfs_create_dir("rpc_clnt", topdir); 283 282 if (!rpc_clnt_dir) ··· 290 283 if (!rpc_xprt_dir) 291 284 goto out_remove; 292 285 293 - return 0; 286 + return; 294 287 out_remove: 295 288 debugfs_remove_recursive(topdir); 296 289 topdir = NULL; 297 - out: 298 - return -ENOMEM; 290 + rpc_clnt_dir = NULL; 299 291 }
+1 -6
net/sunrpc/sunrpc_syms.c
··· 98 98 if (err) 99 99 goto out4; 100 100 101 - err = sunrpc_debugfs_init(); 102 - if (err) 103 - goto out5; 104 - 101 + sunrpc_debugfs_init(); 105 102 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) 106 103 rpc_register_sysctl(); 107 104 #endif ··· 106 109 init_socket_xprt(); /* clnt sock transport */ 107 110 return 0; 108 111 109 - out5: 110 - unregister_rpc_pipefs(); 111 112 out4: 112 113 unregister_pernet_subsys(&sunrpc_net_ops); 113 114 out3:
+1 -6
net/sunrpc/xprt.c
··· 1331 1331 */ 1332 1332 struct rpc_xprt *xprt_create_transport(struct xprt_create *args) 1333 1333 { 1334 - int err; 1335 1334 struct rpc_xprt *xprt; 1336 1335 struct xprt_class *t; 1337 1336 ··· 1371 1372 return ERR_PTR(-ENOMEM); 1372 1373 } 1373 1374 1374 - err = rpc_xprt_debugfs_register(xprt); 1375 - if (err) { 1376 - xprt_destroy(xprt); 1377 - return ERR_PTR(err); 1378 - } 1375 + rpc_xprt_debugfs_register(xprt); 1379 1376 1380 1377 dprintk("RPC: created transport %p with %u slots\n", xprt, 1381 1378 xprt->max_reqs);