diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2006-10-20 02:28:43 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-20 13:26:39 -0400 |
commit | 71bdcf8056f910dc57ea3d0def80a9329e7dc52d (patch) | |
tree | 293bf48584d44b5e27cb5050d4e4ccb5254388a2 | |
parent | b87c0adfeaaf8d8310c4f790d76072a5961b3518 (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>
-rw-r--r-- | net/sunrpc/pmap_clnt.c | 14 |
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 | ||