aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/rpcb_clnt.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2008-10-03 16:48:34 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-10-07 18:18:53 -0400
commit9a4bd29fe8f6d3f015fe1c8e5450eb62cfebfcc9 (patch)
treec3175a0a07ecf41f8eae1204ef5f5421c4b023f5 /net/sunrpc/rpcb_clnt.c
parentd1ce02e1689dff9d413138f60a79b4e3affb4708 (diff)
SUNRPC: Fix autobind on cloned rpc clients
Despite the fact that cloned rpc clients won't have the cl_autobind flag set, they may still find themselves calling rpcb_getport_async(). For this to happen, it suffices for a _parent_ rpc_clnt to use autobinding, in which case any clone may find itself triggering the !xprt_bound() case in call_bind(). The correct fix for this is to walk back up the tree of cloned rpc clients, in order to find the parent that 'owns' the transport, either because it has clnt->cl_autobind set, or because it originally created the transport... Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc/rpcb_clnt.c')
-rw-r--r--net/sunrpc/rpcb_clnt.c36
1 files changed, 29 insertions, 7 deletions
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 24db2b4d12d3..172935b046de 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -469,6 +469,28 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi
469 return rpc_run_task(&task_setup_data); 469 return rpc_run_task(&task_setup_data);
470} 470}
471 471
472/*
473 * In the case where rpc clients have been cloned, we want to make
474 * sure that we use the program number/version etc of the actual
475 * owner of the xprt. To do so, we walk back up the tree of parents
476 * to find whoever created the transport and/or whoever has the
477 * autobind flag set.
478 */
479static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt)
480{
481 struct rpc_clnt *parent = clnt->cl_parent;
482
483 while (parent != clnt) {
484 if (parent->cl_xprt != clnt->cl_xprt)
485 break;
486 if (clnt->cl_autobind)
487 break;
488 clnt = parent;
489 parent = parent->cl_parent;
490 }
491 return clnt;
492}
493
472/** 494/**
473 * rpcb_getport_async - obtain the port for a given RPC service on a given host 495 * rpcb_getport_async - obtain the port for a given RPC service on a given host
474 * @task: task that is waiting for portmapper request 496 * @task: task that is waiting for portmapper request
@@ -478,10 +500,10 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi
478 */ 500 */
479void rpcb_getport_async(struct rpc_task *task) 501void rpcb_getport_async(struct rpc_task *task)
480{ 502{
481 struct rpc_clnt *clnt = task->tk_client; 503 struct rpc_clnt *clnt;
482 struct rpc_procinfo *proc; 504 struct rpc_procinfo *proc;
483 u32 bind_version; 505 u32 bind_version;
484 struct rpc_xprt *xprt = task->tk_xprt; 506 struct rpc_xprt *xprt;
485 struct rpc_clnt *rpcb_clnt; 507 struct rpc_clnt *rpcb_clnt;
486 static struct rpcbind_args *map; 508 static struct rpcbind_args *map;
487 struct rpc_task *child; 509 struct rpc_task *child;
@@ -490,13 +512,13 @@ void rpcb_getport_async(struct rpc_task *task)
490 size_t salen; 512 size_t salen;
491 int status; 513 int status;
492 514
515 clnt = rpcb_find_transport_owner(task->tk_client);
516 xprt = clnt->cl_xprt;
517
493 dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", 518 dprintk("RPC: %5u %s(%s, %u, %u, %d)\n",
494 task->tk_pid, __func__, 519 task->tk_pid, __func__,
495 clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot); 520 clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot);
496 521
497 /* Autobind on cloned rpc clients is discouraged */
498 BUG_ON(clnt->cl_parent != clnt);
499
500 /* Put self on the wait queue to ensure we get notified if 522 /* Put self on the wait queue to ensure we get notified if
501 * some other task is already attempting to bind the port */ 523 * some other task is already attempting to bind the port */
502 rpc_sleep_on(&xprt->binding, task, NULL); 524 rpc_sleep_on(&xprt->binding, task, NULL);
@@ -578,9 +600,9 @@ void rpcb_getport_async(struct rpc_task *task)
578 task->tk_pid, __func__); 600 task->tk_pid, __func__);
579 return; 601 return;
580 } 602 }
581 rpc_put_task(child);
582 603
583 task->tk_xprt->stat.bind_count++; 604 xprt->stat.bind_count++;
605 rpc_put_task(child);
584 return; 606 return;
585 607
586bailout_nofree: 608bailout_nofree: