| From 86fdcc288a4778446e4335ca7bef23885f5ed645 Mon Sep 17 00:00:00 2001 |
| From: Trond Myklebust <Trond.Myklebust@netapp.com> |
| Date: Tue, 31 May 2011 15:15:34 -0400 |
| Subject: [PATCH] NLM: Don't hang forever on NLM unlock requests |
| |
| commit 0b760113a3a155269a3fba93a409c640031dd68f upstream. |
| |
| If the NLM daemon is killed on the NFS server, we can currently end up |
| hanging forever on an 'unlock' request, instead of aborting. Basically, |
| if the rpcbind request fails, or the server keeps returning garbage, we |
| really want to quit instead of retrying. |
| |
| Tested-by: Vasily Averin <vvs@sw.ru> |
| Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> |
| [PG: struct rpc_task in sched.h slightly different layout vs. v3.0] |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c |
| index 7932c39..f4ef9d1 100644 |
| --- a/fs/lockd/clntproc.c |
| +++ b/fs/lockd/clntproc.c |
| @@ -710,7 +710,13 @@ static void nlmclnt_unlock_callback(struct rpc_task *task, void *data) |
| |
| if (task->tk_status < 0) { |
| dprintk("lockd: unlock failed (err = %d)\n", -task->tk_status); |
| - goto retry_rebind; |
| + switch (task->tk_status) { |
| + case -EACCES: |
| + case -EIO: |
| + goto die; |
| + default: |
| + goto retry_rebind; |
| + } |
| } |
| if (status == NLM_LCK_DENIED_GRACE_PERIOD) { |
| rpc_delay(task, NLMCLNT_GRACE_WAIT); |
| diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h |
| index 7bc7fd5..f2338ca 100644 |
| --- a/include/linux/sunrpc/sched.h |
| +++ b/include/linux/sunrpc/sched.h |
| @@ -55,6 +55,7 @@ struct rpc_task { |
| struct rpc_message tk_msg; /* RPC call info */ |
| __u8 tk_garb_retry; |
| __u8 tk_cred_retry; |
| + __u8 tk_rebind_retry; |
| |
| /* |
| * callback to be executed after waking up |
| diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c |
| index 0ad7828..018903c 100644 |
| --- a/net/sunrpc/clnt.c |
| +++ b/net/sunrpc/clnt.c |
| @@ -1053,6 +1053,9 @@ call_bind_status(struct rpc_task *task) |
| status = -EOPNOTSUPP; |
| break; |
| } |
| + if (task->tk_rebind_retry == 0) |
| + break; |
| + task->tk_rebind_retry--; |
| rpc_delay(task, 3*HZ); |
| goto retry_timeout; |
| case -ETIMEDOUT: |
| diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c |
| index 416ca5e..e961e06 100644 |
| --- a/net/sunrpc/sched.c |
| +++ b/net/sunrpc/sched.c |
| @@ -799,6 +799,7 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta |
| /* Initialize retry counters */ |
| task->tk_garb_retry = 2; |
| task->tk_cred_retry = 2; |
| + task->tk_rebind_retry = 2; |
| |
| task->tk_priority = task_setup_data->priority - RPC_PRIORITY_LOW; |
| task->tk_owner = current->tgid; |
| -- |
| 1.7.12.rc1.1.gbce1580 |
| |