aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2008-07-07 12:18:53 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-07-09 12:09:45 -0400
commit381ba74af55e58bca4c01553835a360a9f6fbb07 (patch)
tree56e5f5159432ebb350af4adf330afa4f50b77a54
parentf45663ce5fb30f76a3414ab3ac69f4dd320e760a (diff)
SUNRPC: Ensure our task is notified when an rpcbind call is done
If another task is busy in rpcb_getport_async number, it is more efficient to have it wake us up when it has finished instead of arbitrarily sleeping for 5 seconds. Also ensure that rpcb_wake_rpcbind_waiters() is called regardless of whether or not rpcb_getport_done() gets called. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--net/sunrpc/clnt.c8
-rw-r--r--net/sunrpc/rpcb_clnt.c38
2 files changed, 23 insertions, 23 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 09631f6e30e9..76739e928d0d 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -942,11 +942,9 @@ call_bind_status(struct rpc_task *task)
942 } 942 }
943 943
944 switch (task->tk_status) { 944 switch (task->tk_status) {
945 case -EAGAIN: 945 case -ENOMEM:
946 dprintk("RPC: %5u rpcbind waiting for another request " 946 dprintk("RPC: %5u rpcbind out of memory\n", task->tk_pid);
947 "to finish\n", task->tk_pid); 947 rpc_delay(task, HZ >> 2);
948 /* avoid busy-waiting here -- could be a network outage. */
949 rpc_delay(task, 5*HZ);
950 goto retry_timeout; 948 goto retry_timeout;
951 case -EACCES: 949 case -EACCES:
952 dprintk("RPC: %5u remote rpcbind: RPC program/version " 950 dprintk("RPC: %5u remote rpcbind: RPC program/version "
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index c62e446723ae..24e93e0a0a22 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -68,6 +68,7 @@ enum {
68#define RPCB_MAXOWNERLEN sizeof(RPCB_OWNER_STRING) 68#define RPCB_MAXOWNERLEN sizeof(RPCB_OWNER_STRING)
69 69
70static void rpcb_getport_done(struct rpc_task *, void *); 70static void rpcb_getport_done(struct rpc_task *, void *);
71static void rpcb_map_release(void *data);
71static struct rpc_program rpcb_program; 72static struct rpc_program rpcb_program;
72 73
73struct rpcbind_args { 74struct rpcbind_args {
@@ -80,6 +81,8 @@ struct rpcbind_args {
80 const char * r_netid; 81 const char * r_netid;
81 const char * r_addr; 82 const char * r_addr;
82 const char * r_owner; 83 const char * r_owner;
84
85 int r_status;
83}; 86};
84 87
85static struct rpc_procinfo rpcb_procedures2[]; 88static struct rpc_procinfo rpcb_procedures2[];
@@ -93,14 +96,6 @@ struct rpcb_info {
93static struct rpcb_info rpcb_next_version[]; 96static struct rpcb_info rpcb_next_version[];
94static struct rpcb_info rpcb_next_version6[]; 97static struct rpcb_info rpcb_next_version6[];
95 98
96static void rpcb_map_release(void *data)
97{
98 struct rpcbind_args *map = data;
99
100 xprt_put(map->r_xprt);
101 kfree(map);
102}
103
104static const struct rpc_call_ops rpcb_getport_ops = { 99static const struct rpc_call_ops rpcb_getport_ops = {
105 .rpc_call_done = rpcb_getport_done, 100 .rpc_call_done = rpcb_getport_done,
106 .rpc_release = rpcb_map_release, 101 .rpc_release = rpcb_map_release,
@@ -112,6 +107,15 @@ static void rpcb_wake_rpcbind_waiters(struct rpc_xprt *xprt, int status)
112 rpc_wake_up_status(&xprt->binding, status); 107 rpc_wake_up_status(&xprt->binding, status);
113} 108}
114 109
110static void rpcb_map_release(void *data)
111{
112 struct rpcbind_args *map = data;
113
114 rpcb_wake_rpcbind_waiters(map->r_xprt, map->r_status);
115 xprt_put(map->r_xprt);
116 kfree(map);
117}
118
115static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, 119static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
116 size_t salen, int proto, u32 version, 120 size_t salen, int proto, u32 version,
117 int privileged) 121 int privileged)
@@ -293,17 +297,16 @@ void rpcb_getport_async(struct rpc_task *task)
293 /* Autobind on cloned rpc clients is discouraged */ 297 /* Autobind on cloned rpc clients is discouraged */
294 BUG_ON(clnt->cl_parent != clnt); 298 BUG_ON(clnt->cl_parent != clnt);
295 299
300 /* Put self on the wait queue to ensure we get notified if
301 * some other task is already attempting to bind the port */
302 rpc_sleep_on(&xprt->binding, task, NULL);
303
296 if (xprt_test_and_set_binding(xprt)) { 304 if (xprt_test_and_set_binding(xprt)) {
297 status = -EAGAIN; /* tell caller to check again */
298 dprintk("RPC: %5u %s: waiting for another binder\n", 305 dprintk("RPC: %5u %s: waiting for another binder\n",
299 task->tk_pid, __func__); 306 task->tk_pid, __func__);
300 goto bailout_nowake; 307 return;
301 } 308 }
302 309
303 /* Put self on queue before sending rpcbind request, in case
304 * rpcb_getport_done completes before we return from rpc_run_task */
305 rpc_sleep_on(&xprt->binding, task, NULL);
306
307 /* Someone else may have bound if we slept */ 310 /* Someone else may have bound if we slept */
308 if (xprt_bound(xprt)) { 311 if (xprt_bound(xprt)) {
309 status = 0; 312 status = 0;
@@ -365,15 +368,15 @@ void rpcb_getport_async(struct rpc_task *task)
365 map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); 368 map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID);
366 map->r_addr = rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR); 369 map->r_addr = rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR);
367 map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */ 370 map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */
371 map->r_status = -EIO;
368 372
369 child = rpcb_call_async(rpcb_clnt, map, proc); 373 child = rpcb_call_async(rpcb_clnt, map, proc);
370 rpc_release_client(rpcb_clnt); 374 rpc_release_client(rpcb_clnt);
371 if (IS_ERR(child)) { 375 if (IS_ERR(child)) {
372 status = -EIO;
373 /* rpcb_map_release() has freed the arguments */ 376 /* rpcb_map_release() has freed the arguments */
374 dprintk("RPC: %5u %s: rpc_run_task failed\n", 377 dprintk("RPC: %5u %s: rpc_run_task failed\n",
375 task->tk_pid, __func__); 378 task->tk_pid, __func__);
376 goto bailout_nofree; 379 return;
377 } 380 }
378 rpc_put_task(child); 381 rpc_put_task(child);
379 382
@@ -382,7 +385,6 @@ void rpcb_getport_async(struct rpc_task *task)
382 385
383bailout_nofree: 386bailout_nofree:
384 rpcb_wake_rpcbind_waiters(xprt, status); 387 rpcb_wake_rpcbind_waiters(xprt, status);
385bailout_nowake:
386 task->tk_status = status; 388 task->tk_status = status;
387} 389}
388EXPORT_SYMBOL_GPL(rpcb_getport_async); 390EXPORT_SYMBOL_GPL(rpcb_getport_async);
@@ -421,7 +423,7 @@ static void rpcb_getport_done(struct rpc_task *child, void *data)
421 dprintk("RPC: %5u rpcb_getport_done(status %d, port %u)\n", 423 dprintk("RPC: %5u rpcb_getport_done(status %d, port %u)\n",
422 child->tk_pid, status, map->r_port); 424 child->tk_pid, status, map->r_port);
423 425
424 rpcb_wake_rpcbind_waiters(xprt, status); 426 map->r_status = status;
425} 427}
426 428
427static int rpcb_encode_mapping(struct rpc_rqst *req, __be32 *p, 429static int rpcb_encode_mapping(struct rpc_rqst *req, __be32 *p,