diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-11-20 11:13:31 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-11-22 13:22:39 -0500 |
commit | 5fc43978a79e8021c189660ab63249fd29c5fb32 (patch) | |
tree | cac3a18f6bc6c5b91e5c2592c2d7b0ad459db50e /net/sunrpc | |
parent | 3561d43fd289f590fdae672e5eb831b8d5cf0bf6 (diff) |
SUNRPC: Fix an infinite loop in call_refresh/call_refreshresult
If the rpcauth_refreshcred() call returns an error other than
EACCES, ENOMEM or ETIMEDOUT, we currently end up looping forever
between call_refresh and call_refreshresult.
The correct thing to do here is to exit on all errors except
EAGAIN and ETIMEDOUT, for which case we retry 3 times, then
return EACCES.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/clnt.c | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 9dab9573be4..92ce94f5146 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -989,20 +989,26 @@ call_refreshresult(struct rpc_task *task) | |||
989 | dprint_status(task); | 989 | dprint_status(task); |
990 | 990 | ||
991 | task->tk_status = 0; | 991 | task->tk_status = 0; |
992 | task->tk_action = call_allocate; | 992 | task->tk_action = call_refresh; |
993 | if (status >= 0 && rpcauth_uptodatecred(task)) | ||
994 | return; | ||
995 | switch (status) { | 993 | switch (status) { |
996 | case -EACCES: | 994 | case 0: |
997 | rpc_exit(task, -EACCES); | 995 | if (rpcauth_uptodatecred(task)) |
998 | return; | 996 | task->tk_action = call_allocate; |
999 | case -ENOMEM: | ||
1000 | rpc_exit(task, -ENOMEM); | ||
1001 | return; | 997 | return; |
1002 | case -ETIMEDOUT: | 998 | case -ETIMEDOUT: |
1003 | rpc_delay(task, 3*HZ); | 999 | rpc_delay(task, 3*HZ); |
1000 | case -EAGAIN: | ||
1001 | status = -EACCES; | ||
1002 | if (!task->tk_cred_retry) | ||
1003 | break; | ||
1004 | task->tk_cred_retry--; | ||
1005 | dprintk("RPC: %5u %s: retry refresh creds\n", | ||
1006 | task->tk_pid, __func__); | ||
1007 | return; | ||
1004 | } | 1008 | } |
1005 | task->tk_action = call_refresh; | 1009 | dprintk("RPC: %5u %s: refresh creds failed with error %d\n", |
1010 | task->tk_pid, __func__, status); | ||
1011 | rpc_exit(task, status); | ||
1006 | } | 1012 | } |
1007 | 1013 | ||
1008 | /* | 1014 | /* |