aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc')
-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: