Commit fb9100d0 authored by Trond Myklebust's avatar Trond Myklebust Committed by Linus Torvalds

[PATCH] Clean up the RPC socket slot allocation code [2/2]

Patch by Chuck Lever. Remove the timeout logic from call_reserve.
This improves the overall RPC call ordering, and ensures that soft
tasks don't time out and give up before they have attempted to send
their message down the socket.
parent 7a72fa16
...@@ -57,8 +57,7 @@ struct rpc_timeout { ...@@ -57,8 +57,7 @@ struct rpc_timeout {
unsigned long to_current, /* current timeout */ unsigned long to_current, /* current timeout */
to_initval, /* initial timeout */ to_initval, /* initial timeout */
to_maxval, /* max timeout */ to_maxval, /* max timeout */
to_increment, /* if !exponential */ to_increment; /* if !exponential */
to_resrvval; /* reserve timeout */
short to_retries; /* max # of retries */ short to_retries; /* max # of retries */
unsigned char to_exponential; unsigned char to_exponential;
}; };
...@@ -173,7 +172,7 @@ void xprt_default_timeout(struct rpc_timeout *, int); ...@@ -173,7 +172,7 @@ void xprt_default_timeout(struct rpc_timeout *, int);
void xprt_set_timeout(struct rpc_timeout *, unsigned int, void xprt_set_timeout(struct rpc_timeout *, unsigned int,
unsigned long); unsigned long);
int xprt_reserve(struct rpc_task *); void xprt_reserve(struct rpc_task *);
void xprt_transmit(struct rpc_task *); void xprt_transmit(struct rpc_task *);
void xprt_receive(struct rpc_task *); void xprt_receive(struct rpc_task *);
int xprt_adjust_timeout(struct rpc_timeout *); int xprt_adjust_timeout(struct rpc_timeout *);
......
...@@ -394,8 +394,6 @@ call_start(struct rpc_task *task) ...@@ -394,8 +394,6 @@ call_start(struct rpc_task *task)
static void static void
call_reserve(struct rpc_task *task) call_reserve(struct rpc_task *task)
{ {
struct rpc_clnt *clnt = task->tk_client;
dprintk("RPC: %4d call_reserve\n", task->tk_pid); dprintk("RPC: %4d call_reserve\n", task->tk_pid);
if (!rpcauth_uptodatecred(task)) { if (!rpcauth_uptodatecred(task)) {
...@@ -405,7 +403,6 @@ call_reserve(struct rpc_task *task) ...@@ -405,7 +403,6 @@ call_reserve(struct rpc_task *task)
task->tk_status = 0; task->tk_status = 0;
task->tk_action = call_reserveresult; task->tk_action = call_reserveresult;
task->tk_timeout = clnt->cl_timeout.to_resrvval;
xprt_reserve(task); xprt_reserve(task);
} }
...@@ -448,17 +445,10 @@ call_reserveresult(struct rpc_task *task) ...@@ -448,17 +445,10 @@ call_reserveresult(struct rpc_task *task)
} }
switch (status) { switch (status) {
case -EAGAIN: case -EAGAIN: /* woken up; retry */
case -ENOBUFS:
task->tk_timeout = task->tk_client->cl_timeout.to_resrvval;
task->tk_action = call_reserve; task->tk_action = call_reserve;
return; return;
case -ETIMEDOUT: case -EIO: /* probably a shutdown */
dprintk("RPC: timed out while reserving request slot\n");
task->tk_action = call_timeout;
return;
case -EIO:
/* probably a shutdown */
break; break;
default: default:
printk(KERN_ERR "%s: unrecognized error %d, exiting\n", printk(KERN_ERR "%s: unrecognized error %d, exiting\n",
...@@ -560,6 +550,9 @@ call_bind(struct rpc_task *task) ...@@ -560,6 +550,9 @@ call_bind(struct rpc_task *task)
struct rpc_clnt *clnt = task->tk_client; struct rpc_clnt *clnt = task->tk_client;
struct rpc_xprt *xprt = clnt->cl_xprt; struct rpc_xprt *xprt = clnt->cl_xprt;
dprintk("RPC: %4d call_bind xprt %p %s connected\n", task->tk_pid,
xprt, (xprt_connected(xprt) ? "is" : "is not"));
task->tk_action = (xprt_connected(xprt)) ? call_transmit : call_reconnect; task->tk_action = (xprt_connected(xprt)) ? call_transmit : call_reconnect;
if (!clnt->cl_port) { if (!clnt->cl_port) {
...@@ -696,20 +689,15 @@ static void ...@@ -696,20 +689,15 @@ static void
call_timeout(struct rpc_task *task) call_timeout(struct rpc_task *task)
{ {
struct rpc_clnt *clnt = task->tk_client; struct rpc_clnt *clnt = task->tk_client;
struct rpc_rqst *req = task->tk_rqstp; struct rpc_timeout *to = &task->tk_rqstp->rq_timeout;
if (req) {
struct rpc_timeout *to = &req->rq_timeout;
if (xprt_adjust_timeout(to)) { if (xprt_adjust_timeout(to)) {
dprintk("RPC: %4d call_timeout (minor timeo)\n", dprintk("RPC: %4d call_timeout (minor)\n", task->tk_pid);
task->tk_pid); goto retry;
goto minor_timeout;
} }
to->to_retries = clnt->cl_timeout.to_retries; to->to_retries = clnt->cl_timeout.to_retries;
}
dprintk("RPC: %4d call_timeout (major timeo)\n", task->tk_pid); dprintk("RPC: %4d call_timeout (major)\n", task->tk_pid);
if (clnt->cl_softrtry) { if (clnt->cl_softrtry) {
if (clnt->cl_chatty && !task->tk_exit) if (clnt->cl_chatty && !task->tk_exit)
printk(KERN_NOTICE "%s: server %s not responding, timed out\n", printk(KERN_NOTICE "%s: server %s not responding, timed out\n",
...@@ -717,33 +705,18 @@ call_timeout(struct rpc_task *task) ...@@ -717,33 +705,18 @@ call_timeout(struct rpc_task *task)
rpc_exit(task, -EIO); rpc_exit(task, -EIO);
return; return;
} }
if (clnt->cl_chatty && !(task->tk_flags & RPC_CALL_MAJORSEEN) && rpc_ntimeo(&clnt->cl_rtt) > 7) { if (clnt->cl_chatty && !(task->tk_flags & RPC_CALL_MAJORSEEN) && rpc_ntimeo(&clnt->cl_rtt) > 7) {
task->tk_flags |= RPC_CALL_MAJORSEEN; task->tk_flags |= RPC_CALL_MAJORSEEN;
if (req)
printk(KERN_NOTICE "%s: server %s not responding, still trying\n", printk(KERN_NOTICE "%s: server %s not responding, still trying\n",
clnt->cl_protname, clnt->cl_server); clnt->cl_protname, clnt->cl_server);
#ifdef RPC_DEBUG
else
printk(KERN_NOTICE "%s: task %d can't get a request slot\n",
clnt->cl_protname, task->tk_pid);
#endif
} }
if (clnt->cl_autobind) if (clnt->cl_autobind)
clnt->cl_port = 0; clnt->cl_port = 0;
minor_timeout: retry:
if (!req)
task->tk_action = call_reserve;
else if (!clnt->cl_port) {
task->tk_action = call_bind;
clnt->cl_stats->rpcretrans++;
} else if (!xprt_connected(clnt->cl_xprt)) {
task->tk_action = call_reconnect;
clnt->cl_stats->rpcretrans++;
} else {
task->tk_action = call_transmit;
clnt->cl_stats->rpcretrans++; clnt->cl_stats->rpcretrans++;
} task->tk_action = call_bind;
task->tk_status = 0; task->tk_status = 0;
} }
......
...@@ -84,7 +84,7 @@ ...@@ -84,7 +84,7 @@
*/ */
static void xprt_request_init(struct rpc_task *, struct rpc_xprt *); static void xprt_request_init(struct rpc_task *, struct rpc_xprt *);
static void do_xprt_transmit(struct rpc_task *); static void do_xprt_transmit(struct rpc_task *);
static void xprt_reserve_status(struct rpc_task *task); static inline void do_xprt_reserve(struct rpc_task *);
static void xprt_disconnect(struct rpc_xprt *); static void xprt_disconnect(struct rpc_xprt *);
static void xprt_reconn_status(struct rpc_task *task); static void xprt_reconn_status(struct rpc_task *task);
static struct socket *xprt_create_socket(int, struct rpc_timeout *); static struct socket *xprt_create_socket(int, struct rpc_timeout *);
...@@ -1179,61 +1179,39 @@ do_xprt_transmit(struct rpc_task *task) ...@@ -1179,61 +1179,39 @@ do_xprt_transmit(struct rpc_task *task)
/* /*
* Reserve an RPC call slot. * Reserve an RPC call slot.
*/ */
int void
xprt_reserve(struct rpc_task *task) xprt_reserve(struct rpc_task *task)
{ {
struct rpc_xprt *xprt = task->tk_xprt; struct rpc_xprt *xprt = task->tk_xprt;
/* We already have an initialized request. */ task->tk_status = -EIO;
if (task->tk_rqstp) if (!xprt->shutdown) {
return 0;
spin_lock(&xprt->xprt_lock); spin_lock(&xprt->xprt_lock);
xprt_reserve_status(task); do_xprt_reserve(task);
if (task->tk_rqstp) {
task->tk_timeout = 0;
} else if (!task->tk_timeout) {
task->tk_status = -ENOBUFS;
} else {
dprintk("RPC: xprt_reserve waiting on backlog\n");
task->tk_status = -EAGAIN;
rpc_sleep_on(&xprt->backlog, task, NULL, NULL);
}
spin_unlock(&xprt->xprt_lock); spin_unlock(&xprt->xprt_lock);
dprintk("RPC: %4d xprt_reserve returns %d\n", }
task->tk_pid, task->tk_status);
return task->tk_status;
} }
/* static inline void
* Reservation callback do_xprt_reserve(struct rpc_task *task)
*/
static void
xprt_reserve_status(struct rpc_task *task)
{ {
struct rpc_xprt *xprt = task->tk_xprt; struct rpc_xprt *xprt = task->tk_xprt;
struct rpc_rqst *req;
if (xprt->shutdown) { task->tk_status = 0;
task->tk_status = -EIO; if (task->tk_rqstp)
} else if (task->tk_status < 0) { return;
/* NOP */ if (xprt->free) {
} else if (task->tk_rqstp) { struct rpc_rqst *req = xprt->free;
/* We've already been given a request slot: NOP */
} else {
if (!(req = xprt->free))
goto out_nofree;
/* OK: There's room for us. Grab a free slot */
xprt->free = req->rq_next; xprt->free = req->rq_next;
req->rq_next = NULL; req->rq_next = NULL;
task->tk_rqstp = req; task->tk_rqstp = req;
xprt_request_init(task, xprt); xprt_request_init(task, xprt);
}
return; return;
}
out_nofree: dprintk("RPC: waiting for request slot\n");
task->tk_status = -EAGAIN; task->tk_status = -EAGAIN;
task->tk_timeout = 0;
rpc_sleep_on(&xprt->backlog, task, NULL, NULL);
} }
/* /*
...@@ -1249,7 +1227,6 @@ xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt) ...@@ -1249,7 +1227,6 @@ xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
xid = CURRENT_TIME << 12; xid = CURRENT_TIME << 12;
dprintk("RPC: %4d reserved req %p xid %08x\n", task->tk_pid, req, xid); dprintk("RPC: %4d reserved req %p xid %08x\n", task->tk_pid, req, xid);
task->tk_status = 0;
req->rq_timeout = xprt->timeout; req->rq_timeout = xprt->timeout;
req->rq_task = task; req->rq_task = task;
req->rq_xprt = xprt; req->rq_xprt = xprt;
...@@ -1311,7 +1288,6 @@ xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr) ...@@ -1311,7 +1288,6 @@ xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr)
to->to_initval = to->to_initval =
to->to_increment = incr; to->to_increment = incr;
to->to_maxval = incr * retr; to->to_maxval = incr * retr;
to->to_resrvval = incr * retr;
to->to_retries = retr; to->to_retries = retr;
to->to_exponential = 0; to->to_exponential = 0;
} }
...@@ -1352,7 +1328,6 @@ xprt_setup(struct socket *sock, int proto, ...@@ -1352,7 +1328,6 @@ xprt_setup(struct socket *sock, int proto,
if (to) { if (to) {
xprt->timeout = *to; xprt->timeout = *to;
xprt->timeout.to_current = to->to_initval; xprt->timeout.to_current = to->to_initval;
xprt->timeout.to_resrvval = to->to_maxval << 1;
} else } else
xprt_default_timeout(&xprt->timeout, xprt->prot); xprt_default_timeout(&xprt->timeout, xprt->prot);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment