diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2012-09-14 17:23:52 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-10-01 18:32:07 -0400 |
commit | 1b63a75180c6c65c71655c250a4e6b578ba7d1c0 (patch) | |
tree | 85743d02287e488622cf0504281973b455af8387 /net/sunrpc | |
parent | 632f0d0503accb8ab749a1165af99d344579c37b (diff) |
SUNRPC: Refactor rpc_clone_client()
rpc_clone_client() does most of the same tasks as rpc_new_client(),
so there is an opportunity for code re-use. Create a generic helper
that makes it easy to clone an RPC client while replacing any of the
clnt's parameters.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/clnt.c | 83 |
1 files changed, 43 insertions, 40 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index fa48c60aef23..afbeefab6600 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -490,59 +490,62 @@ EXPORT_SYMBOL_GPL(rpc_create); | |||
490 | * same transport while varying parameters such as the authentication | 490 | * same transport while varying parameters such as the authentication |
491 | * flavour. | 491 | * flavour. |
492 | */ | 492 | */ |
493 | struct rpc_clnt * | 493 | static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args, |
494 | rpc_clone_client(struct rpc_clnt *clnt) | 494 | struct rpc_clnt *clnt) |
495 | { | 495 | { |
496 | struct rpc_clnt *new; | ||
497 | struct rpc_xprt *xprt; | 496 | struct rpc_xprt *xprt; |
498 | int err = -ENOMEM; | 497 | struct rpc_clnt *new; |
498 | int err; | ||
499 | 499 | ||
500 | new = kmemdup(clnt, sizeof(*new), GFP_KERNEL); | 500 | err = -ENOMEM; |
501 | if (!new) | ||
502 | goto out_no_clnt; | ||
503 | new->cl_parent = clnt; | ||
504 | /* Turn off autobind on clones */ | ||
505 | new->cl_autobind = 0; | ||
506 | INIT_LIST_HEAD(&new->cl_tasks); | ||
507 | spin_lock_init(&new->cl_lock); | ||
508 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_timeout->to_initval); | ||
509 | new->cl_metrics = rpc_alloc_iostats(clnt); | ||
510 | if (new->cl_metrics == NULL) | ||
511 | goto out_no_stats; | ||
512 | if (clnt->cl_principal) { | ||
513 | new->cl_principal = kstrdup(clnt->cl_principal, GFP_KERNEL); | ||
514 | if (new->cl_principal == NULL) | ||
515 | goto out_no_principal; | ||
516 | } | ||
517 | rcu_read_lock(); | 501 | rcu_read_lock(); |
518 | xprt = xprt_get(rcu_dereference(clnt->cl_xprt)); | 502 | xprt = xprt_get(rcu_dereference(clnt->cl_xprt)); |
519 | rcu_read_unlock(); | 503 | rcu_read_unlock(); |
520 | if (xprt == NULL) | 504 | if (xprt == NULL) |
521 | goto out_no_transport; | 505 | goto out_err; |
522 | rcu_assign_pointer(new->cl_xprt, xprt); | 506 | args->servername = xprt->servername; |
523 | atomic_set(&new->cl_count, 1); | 507 | |
524 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); | 508 | new = rpc_new_client(args, xprt); |
525 | if (err != 0) | 509 | if (IS_ERR(new)) { |
526 | goto out_no_path; | 510 | err = PTR_ERR(new); |
527 | rpc_clnt_set_nodename(new, utsname()->nodename); | 511 | goto out_put; |
528 | if (new->cl_auth) | 512 | } |
529 | atomic_inc(&new->cl_auth->au_count); | 513 | |
530 | atomic_inc(&clnt->cl_count); | 514 | atomic_inc(&clnt->cl_count); |
531 | rpc_register_client(new); | 515 | new->cl_parent = clnt; |
532 | rpciod_up(); | 516 | |
517 | /* Turn off autobind on clones */ | ||
518 | new->cl_autobind = 0; | ||
519 | new->cl_softrtry = clnt->cl_softrtry; | ||
520 | new->cl_discrtry = clnt->cl_discrtry; | ||
521 | new->cl_chatty = clnt->cl_chatty; | ||
533 | return new; | 522 | return new; |
534 | out_no_path: | 523 | |
524 | out_put: | ||
535 | xprt_put(xprt); | 525 | xprt_put(xprt); |
536 | out_no_transport: | 526 | out_err: |
537 | kfree(new->cl_principal); | ||
538 | out_no_principal: | ||
539 | rpc_free_iostats(new->cl_metrics); | ||
540 | out_no_stats: | ||
541 | kfree(new); | ||
542 | out_no_clnt: | ||
543 | dprintk("RPC: %s: returned error %d\n", __func__, err); | 527 | dprintk("RPC: %s: returned error %d\n", __func__, err); |
544 | return ERR_PTR(err); | 528 | return ERR_PTR(err); |
545 | } | 529 | } |
530 | |||
531 | /** | ||
532 | * rpc_clone_client - Clone an RPC client structure | ||
533 | * | ||
534 | * @clnt: RPC client whose parameters are copied | ||
535 | * | ||
536 | * Returns a fresh RPC client or an ERR_PTR. | ||
537 | */ | ||
538 | struct rpc_clnt *rpc_clone_client(struct rpc_clnt *clnt) | ||
539 | { | ||
540 | struct rpc_create_args args = { | ||
541 | .program = clnt->cl_program, | ||
542 | .prognumber = clnt->cl_prog, | ||
543 | .version = clnt->cl_vers, | ||
544 | .authflavor = clnt->cl_auth->au_flavor, | ||
545 | .client_name = clnt->cl_principal, | ||
546 | }; | ||
547 | return __rpc_clone_client(&args, clnt); | ||
548 | } | ||
546 | EXPORT_SYMBOL_GPL(rpc_clone_client); | 549 | EXPORT_SYMBOL_GPL(rpc_clone_client); |
547 | 550 | ||
548 | /* | 551 | /* |