aboutsummaryrefslogtreecommitdiff
path: root/net/sunrpc
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-05-19 12:12:53 -0400
committerBen Hutchings <ben@decadent.org.uk>2012-06-10 14:41:32 +0100
commitb35e0437787ca030484a278d052d3aada0bb9947 (patch)
treea45910983f27a3d0f7649635a7287a12bc416c98 /net/sunrpc
parent90f560e0729cc5483324673cb13522b8abcd8ca5 (diff)
sunrpc: fix loss of task->tk_status after rpc_delay call in xprt_alloc_slot
commit 1afeaf5c29aa07db25760d2fbed5c08a3aec3498 upstream. xprt_alloc_slot will call rpc_delay() to make the task wait a bit before retrying when it gets back an -ENOMEM error from xprt_dynamic_alloc_slot. The problem is that rpc_delay will clear the task->tk_status, causing call_reserveresult to abort the task. The solution is simply to let call_reserveresult handle the ENOMEM error directly. Reported-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/clnt.c2
-rw-r--r--net/sunrpc/xprt.c5
2 files changed, 5 insertions, 2 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index f0268ea7e71..b2250da4b59 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -959,6 +959,8 @@ call_reserveresult(struct rpc_task *task)
}
switch (status) {
+ case -ENOMEM:
+ rpc_delay(task, HZ >> 2);
case -EAGAIN: /* woken up; retry */
task->tk_action = call_reserve;
return;
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index c64c0ef519b..3ac978989da 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -977,15 +977,16 @@ static void xprt_alloc_slot(struct rpc_task *task)
goto out_init_req;
switch (PTR_ERR(req)) {
case -ENOMEM:
- rpc_delay(task, HZ >> 2);
dprintk("RPC: dynamic allocation of request slot "
"failed! Retrying\n");
+ task->tk_status = -ENOMEM;
break;
case -EAGAIN:
rpc_sleep_on(&xprt->backlog, task, NULL);
dprintk("RPC: waiting for request slot\n");
+ default:
+ task->tk_status = -EAGAIN;
}
- task->tk_status = -EAGAIN;
return;
out_init_req:
task->tk_status = 0;