]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
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)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 7 Nov 2011 21:47:37 +0000 (13:47 -0800)
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>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
fs/lockd/clntproc.c
include/linux/sunrpc/sched.h
net/sunrpc/clnt.c
net/sunrpc/sched.c

index c81249fef11f9a3f48b02d772e4d09d3216a2557..c325a834f8df6e9c43893851aa5c2bf3849d4161 100644 (file)
@@ -709,7 +709,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 7bc7fd5291ce37d6abcbe7f44e96156540beb46d..14c4f91de0e8a093a2cd1fd878b5076fcd6de580 100644 (file)
@@ -84,8 +84,8 @@ struct rpc_task {
        long                    tk_rtt;         /* round-trip time (jiffies) */
 
        pid_t                   tk_owner;       /* Process id for batching tasks */
-       unsigned char           tk_priority : 2;/* Task priority */
-
+       unsigned char           tk_priority : 2,/* Task priority */
+                               tk_rebind_retry : 2;
 #ifdef RPC_DEBUG
        unsigned short          tk_pid;         /* debugging aid */
 #endif
index 20b989e22e0d0514bf5e44568245013e8d4bc55e..c5ba898622ad4b4e44469598c755bd5c07ed41d4 100644 (file)
@@ -1052,6 +1052,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 416ca5e9378eaa93aee7041f18242565b8b54398..e961e064a5bc5dbbecc0637e6a8a9572ac8905d4 100644 (file)
@@ -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;