diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-05-19 12:12:53 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-05-19 12:12:53 -0400 |
commit | 1afeaf5c29aa07db25760d2fbed5c08a3aec3498 (patch) | |
tree | b8fefaefd78e8d4cc3378378e968987297f73c04 /net/sunrpc | |
parent | 6b34309936ed5c85cbe5868655814065f42c2f38 (diff) |
sunrpc: fix loss of task->tk_status after rpc_delay call in xprt_alloc_slot
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>
Cc: stable@vger.kernel.org [>= 3.1]
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/clnt.c | 2 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 5 |
2 files changed, 5 insertions, 2 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index adf2990acebf..25302c802460 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -1288,6 +1288,8 @@ call_reserveresult(struct rpc_task *task) | |||
1288 | } | 1288 | } |
1289 | 1289 | ||
1290 | switch (status) { | 1290 | switch (status) { |
1291 | case -ENOMEM: | ||
1292 | rpc_delay(task, HZ >> 2); | ||
1291 | case -EAGAIN: /* woken up; retry */ | 1293 | case -EAGAIN: /* woken up; retry */ |
1292 | task->tk_action = call_reserve; | 1294 | task->tk_action = call_reserve; |
1293 | return; | 1295 | return; |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index b239e75c483f..d7ccd7923eab 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -984,15 +984,16 @@ static void xprt_alloc_slot(struct rpc_task *task) | |||
984 | goto out_init_req; | 984 | goto out_init_req; |
985 | switch (PTR_ERR(req)) { | 985 | switch (PTR_ERR(req)) { |
986 | case -ENOMEM: | 986 | case -ENOMEM: |
987 | rpc_delay(task, HZ >> 2); | ||
988 | dprintk("RPC: dynamic allocation of request slot " | 987 | dprintk("RPC: dynamic allocation of request slot " |
989 | "failed! Retrying\n"); | 988 | "failed! Retrying\n"); |
989 | task->tk_status = -ENOMEM; | ||
990 | break; | 990 | break; |
991 | case -EAGAIN: | 991 | case -EAGAIN: |
992 | rpc_sleep_on(&xprt->backlog, task, NULL); | 992 | rpc_sleep_on(&xprt->backlog, task, NULL); |
993 | dprintk("RPC: waiting for request slot\n"); | 993 | dprintk("RPC: waiting for request slot\n"); |
994 | default: | ||
995 | task->tk_status = -EAGAIN; | ||
994 | } | 996 | } |
995 | task->tk_status = -EAGAIN; | ||
996 | return; | 997 | return; |
997 | out_init_req: | 998 | out_init_req: |
998 | task->tk_status = 0; | 999 | task->tk_status = 0; |