diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-04-14 18:49:37 +0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-04-14 20:26:02 +0400 |
commit | ba60eb25ff6be6f8e60488cdfd454e5c612bce60 (patch) | |
tree | ee5ebe0a500e5926cf52af808096d8c56eae8657 /net/sunrpc/clnt.c | |
parent | b570a975ed276335dc7d148658c1f880ac0a507f (diff) | |
download | linux-ba60eb25ff6be6f8e60488cdfd454e5c612bce60.tar.xz |
SUNRPC: Fix a livelock problem in the xprt->backlog queue
This patch ensures that we throttle new RPC requests if there are
requests already waiting in the xprt->backlog queue. The reason for
doing this is to fix livelock issues that can occur when an existing
(high priority) task is waiting in the backlog queue, gets woken up
by xprt_free_slot(), but a new task then steals the slot.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc/clnt.c')
-rw-r--r-- | net/sunrpc/clnt.c | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index b95a0a2d5eea..a80ee9b80dcf 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -1306,6 +1306,8 @@ call_reserve(struct rpc_task *task) xprt_reserve(task); } +static void call_retry_reserve(struct rpc_task *task); + /* * 1b. Grok the result of xprt_reserve() */ @@ -1347,7 +1349,7 @@ call_reserveresult(struct rpc_task *task) case -ENOMEM: rpc_delay(task, HZ >> 2); case -EAGAIN: /* woken up; retry */ - task->tk_action = call_reserve; + task->tk_action = call_retry_reserve; return; case -EIO: /* probably a shutdown */ break; @@ -1360,6 +1362,19 @@ call_reserveresult(struct rpc_task *task) } /* + * 1c. Retry reserving an RPC call slot + */ +static void +call_retry_reserve(struct rpc_task *task) +{ + dprint_status(task); + + task->tk_status = 0; + task->tk_action = call_reserveresult; + xprt_retry_reserve(task); +} + +/* * 2. Bind and/or refresh the credentials */ static void |