aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/pmap_clnt.c
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2006-10-20 02:28:43 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-20 13:26:39 -0400
commit71bdcf8056f910dc57ea3d0def80a9329e7dc52d (patch)
tree293bf48584d44b5e27cb5050d4e4ccb5254388a2 /net/sunrpc/pmap_clnt.c
parentb87c0adfeaaf8d8310c4f790d76072a5961b3518 (diff)
[PATCH] SUNRPC: fix race in in-kernel RPC portmapper client
When submitting a request to a fast portmapper (such as the local rpcbind daemon), the request can complete before the parent task is even queued up on xprt->binding. Fix this by queuing before submitting the rpcbind request. Test plan: Connectathon locking test with UDP. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'net/sunrpc/pmap_clnt.c')
-rw-r--r--net/sunrpc/pmap_clnt.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
index 919d5ba7ca0a..e52afab413de 100644
--- a/net/sunrpc/pmap_clnt.c
+++ b/net/sunrpc/pmap_clnt.c
@@ -101,11 +101,13 @@ void rpc_getport(struct rpc_task *task)
101 /* Autobind on cloned rpc clients is discouraged */ 101 /* Autobind on cloned rpc clients is discouraged */
102 BUG_ON(clnt->cl_parent != clnt); 102 BUG_ON(clnt->cl_parent != clnt);
103 103
104 if (xprt_test_and_set_binding(xprt)) { 104 /* Put self on queue before sending rpcbind request, in case
105 task->tk_status = -EACCES; /* tell caller to check again */ 105 * pmap_getport_done completes before we return from rpc_run_task */
106 rpc_sleep_on(&xprt->binding, task, NULL, NULL); 106 rpc_sleep_on(&xprt->binding, task, NULL, NULL);
107 return; 107
108 } 108 status = -EACCES; /* tell caller to check again */
109 if (xprt_test_and_set_binding(xprt))
110 goto bailout_nofree;
109 111
110 /* Someone else may have bound if we slept */ 112 /* Someone else may have bound if we slept */
111 status = 0; 113 status = 0;
@@ -134,8 +136,6 @@ void rpc_getport(struct rpc_task *task)
134 goto bailout; 136 goto bailout;
135 rpc_release_task(child); 137 rpc_release_task(child);
136 138
137 rpc_sleep_on(&xprt->binding, task, NULL, NULL);
138
139 task->tk_xprt->stat.bind_count++; 139 task->tk_xprt->stat.bind_count++;
140 return; 140 return;
141 141