diff options
Diffstat (limited to 'net/sunrpc/clnt.c')
-rw-r--r-- | net/sunrpc/clnt.c | 71 |
1 files changed, 44 insertions, 27 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 5a750b9c3640..f0339ae9bf37 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -157,20 +157,15 @@ static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb, | |||
157 | } | 157 | } |
158 | 158 | ||
159 | static int | 159 | static int |
160 | rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name) | 160 | rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name, |
161 | struct super_block *pipefs_sb) | ||
161 | { | 162 | { |
162 | struct net *net = rpc_net_ns(clnt); | ||
163 | struct super_block *pipefs_sb; | ||
164 | struct dentry *dentry; | 163 | struct dentry *dentry; |
165 | 164 | ||
166 | clnt->cl_dentry = NULL; | 165 | clnt->cl_dentry = NULL; |
167 | if (dir_name == NULL) | 166 | if (dir_name == NULL) |
168 | return 0; | 167 | return 0; |
169 | pipefs_sb = rpc_get_sb_net(net); | ||
170 | if (!pipefs_sb) | ||
171 | return 0; | ||
172 | dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name); | 168 | dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name); |
173 | rpc_put_sb_net(net); | ||
174 | if (IS_ERR(dentry)) | 169 | if (IS_ERR(dentry)) |
175 | return PTR_ERR(dentry); | 170 | return PTR_ERR(dentry); |
176 | clnt->cl_dentry = dentry; | 171 | clnt->cl_dentry = dentry; |
@@ -182,6 +177,8 @@ static inline int rpc_clnt_skip_event(struct rpc_clnt *clnt, unsigned long event | |||
182 | if (((event == RPC_PIPEFS_MOUNT) && clnt->cl_dentry) || | 177 | if (((event == RPC_PIPEFS_MOUNT) && clnt->cl_dentry) || |
183 | ((event == RPC_PIPEFS_UMOUNT) && !clnt->cl_dentry)) | 178 | ((event == RPC_PIPEFS_UMOUNT) && !clnt->cl_dentry)) |
184 | return 1; | 179 | return 1; |
180 | if ((event == RPC_PIPEFS_MOUNT) && atomic_read(&clnt->cl_count) == 0) | ||
181 | return 1; | ||
185 | return 0; | 182 | return 0; |
186 | } | 183 | } |
187 | 184 | ||
@@ -241,8 +238,6 @@ static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event) | |||
241 | continue; | 238 | continue; |
242 | if (rpc_clnt_skip_event(clnt, event)) | 239 | if (rpc_clnt_skip_event(clnt, event)) |
243 | continue; | 240 | continue; |
244 | if (atomic_inc_not_zero(&clnt->cl_count) == 0) | ||
245 | continue; | ||
246 | spin_unlock(&sn->rpc_client_lock); | 241 | spin_unlock(&sn->rpc_client_lock); |
247 | return clnt; | 242 | return clnt; |
248 | } | 243 | } |
@@ -259,7 +254,6 @@ static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, | |||
259 | 254 | ||
260 | while ((clnt = rpc_get_client_for_event(sb->s_fs_info, event))) { | 255 | while ((clnt = rpc_get_client_for_event(sb->s_fs_info, event))) { |
261 | error = __rpc_pipefs_event(clnt, event, sb); | 256 | error = __rpc_pipefs_event(clnt, event, sb); |
262 | rpc_release_client(clnt); | ||
263 | if (error) | 257 | if (error) |
264 | break; | 258 | break; |
265 | } | 259 | } |
@@ -289,12 +283,46 @@ static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename) | |||
289 | memcpy(clnt->cl_nodename, nodename, clnt->cl_nodelen); | 283 | memcpy(clnt->cl_nodename, nodename, clnt->cl_nodelen); |
290 | } | 284 | } |
291 | 285 | ||
286 | static int rpc_client_register(const struct rpc_create_args *args, | ||
287 | struct rpc_clnt *clnt) | ||
288 | { | ||
289 | const struct rpc_program *program = args->program; | ||
290 | struct rpc_auth *auth; | ||
291 | struct net *net = rpc_net_ns(clnt); | ||
292 | struct super_block *pipefs_sb; | ||
293 | int err = 0; | ||
294 | |||
295 | pipefs_sb = rpc_get_sb_net(net); | ||
296 | if (pipefs_sb) { | ||
297 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name, pipefs_sb); | ||
298 | if (err) | ||
299 | goto out; | ||
300 | } | ||
301 | |||
302 | auth = rpcauth_create(args->authflavor, clnt); | ||
303 | if (IS_ERR(auth)) { | ||
304 | dprintk("RPC: Couldn't create auth handle (flavor %u)\n", | ||
305 | args->authflavor); | ||
306 | err = PTR_ERR(auth); | ||
307 | goto err_auth; | ||
308 | } | ||
309 | |||
310 | rpc_register_client(clnt); | ||
311 | out: | ||
312 | if (pipefs_sb) | ||
313 | rpc_put_sb_net(net); | ||
314 | return err; | ||
315 | |||
316 | err_auth: | ||
317 | __rpc_clnt_remove_pipedir(clnt); | ||
318 | goto out; | ||
319 | } | ||
320 | |||
292 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) | 321 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) |
293 | { | 322 | { |
294 | const struct rpc_program *program = args->program; | 323 | const struct rpc_program *program = args->program; |
295 | const struct rpc_version *version; | 324 | const struct rpc_version *version; |
296 | struct rpc_clnt *clnt = NULL; | 325 | struct rpc_clnt *clnt = NULL; |
297 | struct rpc_auth *auth; | ||
298 | int err; | 326 | int err; |
299 | 327 | ||
300 | /* sanity check the name before trying to print it */ | 328 | /* sanity check the name before trying to print it */ |
@@ -354,25 +382,14 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
354 | 382 | ||
355 | atomic_set(&clnt->cl_count, 1); | 383 | atomic_set(&clnt->cl_count, 1); |
356 | 384 | ||
357 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name); | ||
358 | if (err < 0) | ||
359 | goto out_no_path; | ||
360 | |||
361 | auth = rpcauth_create(args->authflavor, clnt); | ||
362 | if (IS_ERR(auth)) { | ||
363 | dprintk("RPC: Couldn't create auth handle (flavor %u)\n", | ||
364 | args->authflavor); | ||
365 | err = PTR_ERR(auth); | ||
366 | goto out_no_auth; | ||
367 | } | ||
368 | |||
369 | /* save the nodename */ | 385 | /* save the nodename */ |
370 | rpc_clnt_set_nodename(clnt, utsname()->nodename); | 386 | rpc_clnt_set_nodename(clnt, utsname()->nodename); |
371 | rpc_register_client(clnt); | 387 | |
388 | err = rpc_client_register(args, clnt); | ||
389 | if (err) | ||
390 | goto out_no_path; | ||
372 | return clnt; | 391 | return clnt; |
373 | 392 | ||
374 | out_no_auth: | ||
375 | rpc_clnt_remove_pipedir(clnt); | ||
376 | out_no_path: | 393 | out_no_path: |
377 | kfree(clnt->cl_principal); | 394 | kfree(clnt->cl_principal); |
378 | out_no_principal: | 395 | out_no_principal: |
@@ -637,8 +654,8 @@ rpc_free_client(struct rpc_clnt *clnt) | |||
637 | rcu_dereference(clnt->cl_xprt)->servername); | 654 | rcu_dereference(clnt->cl_xprt)->servername); |
638 | if (clnt->cl_parent != clnt) | 655 | if (clnt->cl_parent != clnt) |
639 | rpc_release_client(clnt->cl_parent); | 656 | rpc_release_client(clnt->cl_parent); |
640 | rpc_unregister_client(clnt); | ||
641 | rpc_clnt_remove_pipedir(clnt); | 657 | rpc_clnt_remove_pipedir(clnt); |
658 | rpc_unregister_client(clnt); | ||
642 | rpc_free_iostats(clnt->cl_metrics); | 659 | rpc_free_iostats(clnt->cl_metrics); |
643 | kfree(clnt->cl_principal); | 660 | kfree(clnt->cl_principal); |
644 | clnt->cl_metrics = NULL; | 661 | clnt->cl_metrics = NULL; |