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 | |
| 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')
| -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 | /* |
