aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/clnt.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2013-04-14 10:49:37 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-04-14 12:26:02 -0400
commitba60eb25ff6be6f8e60488cdfd454e5c612bce60 (patch)
treeee5ebe0a500e5926cf52af808096d8c56eae8657 /net/sunrpc/clnt.c
parentb570a975ed276335dc7d148658c1f880ac0a507f (diff)
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.c17
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)
1306 xprt_reserve(task); 1306 xprt_reserve(task);
1307} 1307}
1308 1308
1309static void call_retry_reserve(struct rpc_task *task);
1310
1309/* 1311/*
1310 * 1b. Grok the result of xprt_reserve() 1312 * 1b. Grok the result of xprt_reserve()
1311 */ 1313 */
@@ -1347,7 +1349,7 @@ call_reserveresult(struct rpc_task *task)
1347 case -ENOMEM: 1349 case -ENOMEM:
1348 rpc_delay(task, HZ >> 2); 1350 rpc_delay(task, HZ >> 2);
1349 case -EAGAIN: /* woken up; retry */ 1351 case -EAGAIN: /* woken up; retry */
1350 task->tk_action = call_reserve; 1352 task->tk_action = call_retry_reserve;
1351 return; 1353 return;
1352 case -EIO: /* probably a shutdown */ 1354 case -EIO: /* probably a shutdown */
1353 break; 1355 break;
@@ -1360,6 +1362,19 @@ call_reserveresult(struct rpc_task *task)
1360} 1362}
1361 1363
1362/* 1364/*
1365 * 1c. Retry reserving an RPC call slot
1366 */
1367static void
1368call_retry_reserve(struct rpc_task *task)
1369{
1370 dprint_status(task);
1371
1372 task->tk_status = 0;
1373 task->tk_action = call_reserveresult;
1374 xprt_retry_reserve(task);
1375}
1376
1377/*
1363 * 2. Bind and/or refresh the credentials 1378 * 2. Bind and/or refresh the credentials
1364 */ 1379 */
1365static void 1380static void