diff options
Diffstat (limited to 'net/sunrpc/clnt.c')
-rw-r--r-- | net/sunrpc/clnt.c | 70 |
1 files changed, 46 insertions, 24 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index dfeea4fea95a..aba528b9ae76 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/smp_lock.h> | ||
30 | #include <linux/utsname.h> | 31 | #include <linux/utsname.h> |
31 | #include <linux/workqueue.h> | 32 | #include <linux/workqueue.h> |
32 | 33 | ||
@@ -141,6 +142,10 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
141 | clnt->cl_vers = version->number; | 142 | clnt->cl_vers = version->number; |
142 | clnt->cl_stats = program->stats; | 143 | clnt->cl_stats = program->stats; |
143 | clnt->cl_metrics = rpc_alloc_iostats(clnt); | 144 | clnt->cl_metrics = rpc_alloc_iostats(clnt); |
145 | err = -ENOMEM; | ||
146 | if (clnt->cl_metrics == NULL) | ||
147 | goto out_no_stats; | ||
148 | clnt->cl_program = program; | ||
144 | 149 | ||
145 | if (!xprt_bound(clnt->cl_xprt)) | 150 | if (!xprt_bound(clnt->cl_xprt)) |
146 | clnt->cl_autobind = 1; | 151 | clnt->cl_autobind = 1; |
@@ -173,6 +178,8 @@ out_no_auth: | |||
173 | rpc_put_mount(); | 178 | rpc_put_mount(); |
174 | } | 179 | } |
175 | out_no_path: | 180 | out_no_path: |
181 | rpc_free_iostats(clnt->cl_metrics); | ||
182 | out_no_stats: | ||
176 | if (clnt->cl_server != clnt->cl_inline_name) | 183 | if (clnt->cl_server != clnt->cl_inline_name) |
177 | kfree(clnt->cl_server); | 184 | kfree(clnt->cl_server); |
178 | kfree(clnt); | 185 | kfree(clnt); |
@@ -252,12 +259,19 @@ struct rpc_clnt * | |||
252 | rpc_clone_client(struct rpc_clnt *clnt) | 259 | rpc_clone_client(struct rpc_clnt *clnt) |
253 | { | 260 | { |
254 | struct rpc_clnt *new; | 261 | struct rpc_clnt *new; |
262 | int err = -ENOMEM; | ||
255 | 263 | ||
256 | new = kmemdup(clnt, sizeof(*new), GFP_KERNEL); | 264 | new = kmemdup(clnt, sizeof(*new), GFP_KERNEL); |
257 | if (!new) | 265 | if (!new) |
258 | goto out_no_clnt; | 266 | goto out_no_clnt; |
259 | atomic_set(&new->cl_count, 1); | 267 | atomic_set(&new->cl_count, 1); |
260 | atomic_set(&new->cl_users, 0); | 268 | atomic_set(&new->cl_users, 0); |
269 | new->cl_metrics = rpc_alloc_iostats(clnt); | ||
270 | if (new->cl_metrics == NULL) | ||
271 | goto out_no_stats; | ||
272 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); | ||
273 | if (err != 0) | ||
274 | goto out_no_path; | ||
261 | new->cl_parent = clnt; | 275 | new->cl_parent = clnt; |
262 | atomic_inc(&clnt->cl_count); | 276 | atomic_inc(&clnt->cl_count); |
263 | new->cl_xprt = xprt_get(clnt->cl_xprt); | 277 | new->cl_xprt = xprt_get(clnt->cl_xprt); |
@@ -265,16 +279,17 @@ rpc_clone_client(struct rpc_clnt *clnt) | |||
265 | new->cl_autobind = 0; | 279 | new->cl_autobind = 0; |
266 | new->cl_oneshot = 0; | 280 | new->cl_oneshot = 0; |
267 | new->cl_dead = 0; | 281 | new->cl_dead = 0; |
268 | if (!IS_ERR(new->cl_dentry)) | ||
269 | dget(new->cl_dentry); | ||
270 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); | 282 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); |
271 | if (new->cl_auth) | 283 | if (new->cl_auth) |
272 | atomic_inc(&new->cl_auth->au_count); | 284 | atomic_inc(&new->cl_auth->au_count); |
273 | new->cl_metrics = rpc_alloc_iostats(clnt); | ||
274 | return new; | 285 | return new; |
286 | out_no_path: | ||
287 | rpc_free_iostats(new->cl_metrics); | ||
288 | out_no_stats: | ||
289 | kfree(new); | ||
275 | out_no_clnt: | 290 | out_no_clnt: |
276 | printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__); | 291 | dprintk("RPC: %s returned error %d\n", __FUNCTION__, err); |
277 | return ERR_PTR(-ENOMEM); | 292 | return ERR_PTR(err); |
278 | } | 293 | } |
279 | 294 | ||
280 | /* | 295 | /* |
@@ -327,16 +342,14 @@ rpc_destroy_client(struct rpc_clnt *clnt) | |||
327 | rpcauth_destroy(clnt->cl_auth); | 342 | rpcauth_destroy(clnt->cl_auth); |
328 | clnt->cl_auth = NULL; | 343 | clnt->cl_auth = NULL; |
329 | } | 344 | } |
330 | if (clnt->cl_parent != clnt) { | ||
331 | if (!IS_ERR(clnt->cl_dentry)) | ||
332 | dput(clnt->cl_dentry); | ||
333 | rpc_destroy_client(clnt->cl_parent); | ||
334 | goto out_free; | ||
335 | } | ||
336 | if (!IS_ERR(clnt->cl_dentry)) { | 345 | if (!IS_ERR(clnt->cl_dentry)) { |
337 | rpc_rmdir(clnt->cl_dentry); | 346 | rpc_rmdir(clnt->cl_dentry); |
338 | rpc_put_mount(); | 347 | rpc_put_mount(); |
339 | } | 348 | } |
349 | if (clnt->cl_parent != clnt) { | ||
350 | rpc_destroy_client(clnt->cl_parent); | ||
351 | goto out_free; | ||
352 | } | ||
340 | if (clnt->cl_server != clnt->cl_inline_name) | 353 | if (clnt->cl_server != clnt->cl_inline_name) |
341 | kfree(clnt->cl_server); | 354 | kfree(clnt->cl_server); |
342 | out_free: | 355 | out_free: |
@@ -466,10 +479,9 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) | |||
466 | 479 | ||
467 | BUG_ON(flags & RPC_TASK_ASYNC); | 480 | BUG_ON(flags & RPC_TASK_ASYNC); |
468 | 481 | ||
469 | status = -ENOMEM; | ||
470 | task = rpc_new_task(clnt, flags, &rpc_default_ops, NULL); | 482 | task = rpc_new_task(clnt, flags, &rpc_default_ops, NULL); |
471 | if (task == NULL) | 483 | if (task == NULL) |
472 | goto out; | 484 | return -ENOMEM; |
473 | 485 | ||
474 | /* Mask signals on RPC calls _and_ GSS_AUTH upcalls */ | 486 | /* Mask signals on RPC calls _and_ GSS_AUTH upcalls */ |
475 | rpc_task_sigmask(task, &oldset); | 487 | rpc_task_sigmask(task, &oldset); |
@@ -478,15 +490,17 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) | |||
478 | 490 | ||
479 | /* Set up the call info struct and execute the task */ | 491 | /* Set up the call info struct and execute the task */ |
480 | status = task->tk_status; | 492 | status = task->tk_status; |
481 | if (status == 0) { | 493 | if (status != 0) { |
482 | atomic_inc(&task->tk_count); | 494 | rpc_release_task(task); |
483 | status = rpc_execute(task); | 495 | goto out; |
484 | if (status == 0) | ||
485 | status = task->tk_status; | ||
486 | } | 496 | } |
487 | rpc_restore_sigmask(&oldset); | 497 | atomic_inc(&task->tk_count); |
488 | rpc_release_task(task); | 498 | status = rpc_execute(task); |
499 | if (status == 0) | ||
500 | status = task->tk_status; | ||
501 | rpc_put_task(task); | ||
489 | out: | 502 | out: |
503 | rpc_restore_sigmask(&oldset); | ||
490 | return status; | 504 | return status; |
491 | } | 505 | } |
492 | 506 | ||
@@ -528,8 +542,7 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, | |||
528 | rpc_restore_sigmask(&oldset); | 542 | rpc_restore_sigmask(&oldset); |
529 | return status; | 543 | return status; |
530 | out_release: | 544 | out_release: |
531 | if (tk_ops->rpc_release != NULL) | 545 | rpc_release_calldata(tk_ops, data); |
532 | tk_ops->rpc_release(data); | ||
533 | return status; | 546 | return status; |
534 | } | 547 | } |
535 | 548 | ||
@@ -581,7 +594,11 @@ EXPORT_SYMBOL_GPL(rpc_peeraddr); | |||
581 | char *rpc_peeraddr2str(struct rpc_clnt *clnt, enum rpc_display_format_t format) | 594 | char *rpc_peeraddr2str(struct rpc_clnt *clnt, enum rpc_display_format_t format) |
582 | { | 595 | { |
583 | struct rpc_xprt *xprt = clnt->cl_xprt; | 596 | struct rpc_xprt *xprt = clnt->cl_xprt; |
584 | return xprt->ops->print_addr(xprt, format); | 597 | |
598 | if (xprt->address_strings[format] != NULL) | ||
599 | return xprt->address_strings[format]; | ||
600 | else | ||
601 | return "unprintable"; | ||
585 | } | 602 | } |
586 | EXPORT_SYMBOL_GPL(rpc_peeraddr2str); | 603 | EXPORT_SYMBOL_GPL(rpc_peeraddr2str); |
587 | 604 | ||
@@ -811,8 +828,10 @@ call_encode(struct rpc_task *task) | |||
811 | if (encode == NULL) | 828 | if (encode == NULL) |
812 | return; | 829 | return; |
813 | 830 | ||
831 | lock_kernel(); | ||
814 | task->tk_status = rpcauth_wrap_req(task, encode, req, p, | 832 | task->tk_status = rpcauth_wrap_req(task, encode, req, p, |
815 | task->tk_msg.rpc_argp); | 833 | task->tk_msg.rpc_argp); |
834 | unlock_kernel(); | ||
816 | if (task->tk_status == -ENOMEM) { | 835 | if (task->tk_status == -ENOMEM) { |
817 | /* XXX: Is this sane? */ | 836 | /* XXX: Is this sane? */ |
818 | rpc_delay(task, 3*HZ); | 837 | rpc_delay(task, 3*HZ); |
@@ -1143,9 +1162,12 @@ call_decode(struct rpc_task *task) | |||
1143 | 1162 | ||
1144 | task->tk_action = rpc_exit_task; | 1163 | task->tk_action = rpc_exit_task; |
1145 | 1164 | ||
1146 | if (decode) | 1165 | if (decode) { |
1166 | lock_kernel(); | ||
1147 | task->tk_status = rpcauth_unwrap_resp(task, decode, req, p, | 1167 | task->tk_status = rpcauth_unwrap_resp(task, decode, req, p, |
1148 | task->tk_msg.rpc_resp); | 1168 | task->tk_msg.rpc_resp); |
1169 | unlock_kernel(); | ||
1170 | } | ||
1149 | dprintk("RPC: %4d call_decode result %d\n", task->tk_pid, | 1171 | dprintk("RPC: %4d call_decode result %d\n", task->tk_pid, |
1150 | task->tk_status); | 1172 | task->tk_status); |
1151 | return; | 1173 | return; |