]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
sunrpc: fix loss of task->tk_status after rpc_delay call in xprt_alloc_slot
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Sat, 19 May 2012 16:12:53 +0000 (12:12 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 9 Jun 2012 15:36:09 +0000 (00:36 +0900)
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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/sunrpc/clnt.c
net/sunrpc/xprt.c

index adf2990acebfd2ff7513f2344f0a143c326eb6ef..25302c80246069f887fe8203e1811c92958f43a1 100644 (file)
@@ -1288,6 +1288,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;
index 0cbcd1ab49ab5544952d3385b64b2e29b1843872..da72492360b81b8d268cca9aed0eb7ef26ab54ae 100644 (file)
@@ -984,15 +984,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;