aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/rpcb_clnt.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/rpcb_clnt.c')
-rw-r--r--net/sunrpc/rpcb_clnt.c40
1 files changed, 32 insertions, 8 deletions
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 34abc91058d8..41013dd66ac3 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -460,6 +460,28 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi
460 return rpc_run_task(&task_setup_data); 460 return rpc_run_task(&task_setup_data);
461} 461}
462 462
463/*
464 * In the case where rpc clients have been cloned, we want to make
465 * sure that we use the program number/version etc of the actual
466 * owner of the xprt. To do so, we walk back up the tree of parents
467 * to find whoever created the transport and/or whoever has the
468 * autobind flag set.
469 */
470static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt)
471{
472 struct rpc_clnt *parent = clnt->cl_parent;
473
474 while (parent != clnt) {
475 if (parent->cl_xprt != clnt->cl_xprt)
476 break;
477 if (clnt->cl_autobind)
478 break;
479 clnt = parent;
480 parent = parent->cl_parent;
481 }
482 return clnt;
483}
484
463/** 485/**
464 * rpcb_getport_async - obtain the port for a given RPC service on a given host 486 * rpcb_getport_async - obtain the port for a given RPC service on a given host
465 * @task: task that is waiting for portmapper request 487 * @task: task that is waiting for portmapper request
@@ -469,10 +491,10 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi
469 */ 491 */
470void rpcb_getport_async(struct rpc_task *task) 492void rpcb_getport_async(struct rpc_task *task)
471{ 493{
472 struct rpc_clnt *clnt = task->tk_client; 494 struct rpc_clnt *clnt;
473 struct rpc_procinfo *proc; 495 struct rpc_procinfo *proc;
474 u32 bind_version; 496 u32 bind_version;
475 struct rpc_xprt *xprt = task->tk_xprt; 497 struct rpc_xprt *xprt;
476 struct rpc_clnt *rpcb_clnt; 498 struct rpc_clnt *rpcb_clnt;
477 static struct rpcbind_args *map; 499 static struct rpcbind_args *map;
478 struct rpc_task *child; 500 struct rpc_task *child;
@@ -481,13 +503,13 @@ void rpcb_getport_async(struct rpc_task *task)
481 size_t salen; 503 size_t salen;
482 int status; 504 int status;
483 505
506 clnt = rpcb_find_transport_owner(task->tk_client);
507 xprt = clnt->cl_xprt;
508
484 dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", 509 dprintk("RPC: %5u %s(%s, %u, %u, %d)\n",
485 task->tk_pid, __func__, 510 task->tk_pid, __func__,
486 clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot); 511 clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot);
487 512
488 /* Autobind on cloned rpc clients is discouraged */
489 BUG_ON(clnt->cl_parent != clnt);
490
491 /* Put self on the wait queue to ensure we get notified if 513 /* Put self on the wait queue to ensure we get notified if
492 * some other task is already attempting to bind the port */ 514 * some other task is already attempting to bind the port */
493 rpc_sleep_on(&xprt->binding, task, NULL); 515 rpc_sleep_on(&xprt->binding, task, NULL);
@@ -549,7 +571,7 @@ void rpcb_getport_async(struct rpc_task *task)
549 status = -ENOMEM; 571 status = -ENOMEM;
550 dprintk("RPC: %5u %s: no memory available\n", 572 dprintk("RPC: %5u %s: no memory available\n",
551 task->tk_pid, __func__); 573 task->tk_pid, __func__);
552 goto bailout_nofree; 574 goto bailout_release_client;
553 } 575 }
554 map->r_prog = clnt->cl_prog; 576 map->r_prog = clnt->cl_prog;
555 map->r_vers = clnt->cl_vers; 577 map->r_vers = clnt->cl_vers;
@@ -569,11 +591,13 @@ void rpcb_getport_async(struct rpc_task *task)
569 task->tk_pid, __func__); 591 task->tk_pid, __func__);
570 return; 592 return;
571 } 593 }
572 rpc_put_task(child);
573 594
574 task->tk_xprt->stat.bind_count++; 595 xprt->stat.bind_count++;
596 rpc_put_task(child);
575 return; 597 return;
576 598
599bailout_release_client:
600 rpc_release_client(rpcb_clnt);
577bailout_nofree: 601bailout_nofree:
578 rpcb_wake_rpcbind_waiters(xprt, status); 602 rpcb_wake_rpcbind_waiters(xprt, status);
579 task->tk_status = status; 603 task->tk_status = status;