]> git.karo-electronics.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 20:32:47 +0000 (12:32 -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 401097781fc0601e5b7359ea15ec76ad2a3f5f03..67f63ddb2fc84e0cf1e68b9b09badab180ea74a0 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 d838bea672ab5dca1fc8c3a0daee42491161d249..b0c56461a1954084277fc5b01920f551fafaba17 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 570da303b015a387b74a154149f0cf5ca510d248..ac94477eb49a80ad5f0c8be8828e755fcb09d7dd 100644 (file)
@@ -784,6 +784,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;