NLM: Don't hang forever on NLM unlock requests
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 31 May 2011 19:15:34 +0000 (15:15 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 15 Jun 2011 15:24:27 +0000 (11:24 -0400)
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>
Cc: stable@kernel.org
fs/lockd/clntproc.c
include/linux/sunrpc/sched.h
net/sunrpc/clnt.c
net/sunrpc/sched.c

index adb45ec9038cc95530e5d1be50d521a927110ac2..e374050a911c6141342bf5b464bb04fca396ce3e 100644 (file)
@@ -708,7 +708,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);
index f73c482ec9c6080cc5201c047546928c53c8b723..fe2d8e6b923b416908220e2ef70bed01dee60897 100644 (file)
@@ -84,7 +84,8 @@ struct rpc_task {
 #endif
        unsigned char           tk_priority : 2,/* Task priority */
                                tk_garb_retry : 2,
-                               tk_cred_retry : 2;
+                               tk_cred_retry : 2,
+                               tk_rebind_retry : 2;
 };
 #define tk_xprt                        tk_client->cl_xprt
 
index b84d7395535e7aae2d523797134c27d8a9e57c11..566bcfd067f67d6cbfa35d9cd60b579994d443cd 100644 (file)
@@ -1175,6 +1175,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:
index 6b43ee7221d5a830b8b0acea4375f9341aacfc90..a27406b1654f190f645e9b3c393b46f4b6d939fb 100644 (file)
@@ -792,6 +792,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;
This page took 0.031621 seconds and 5 git commands to generate.