]> 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)
committerWilly Tarreau <w@1wt.eu>
Sat, 11 Feb 2012 14:37:49 +0000 (15:37 +0100)
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>
Signed-off-by: Willy Tarreau <w@1wt.eu>
fs/lockd/clntproc.c
include/linux/sunrpc/sched.h
net/sunrpc/clnt.c
net/sunrpc/sched.c

index 31668b690e03d4e482a8affb7657a310cffac1c0..4de7252899a3007c550588ab8bfd47f11f1f0116 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 64981a2f1cae12e1b9f384b758cbc1718ee09721..a825079999933b2968b1aa3eb15c09fd45770c22 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 860b1d4bfd5fd1bafbf7a30a0837fb10c2e2464e..76753a104e7fb0588cec63c17242c93a3497eb02 100644 (file)
@@ -955,6 +955,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 aad8362f9cc11b22b4f4cbfaa906be10fd4e630c..9f66357abd7e3b2432ffa60ec801f19ad534f2ee 100644 (file)
@@ -786,6 +786,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;