From aaaa99423b4b1f9cfd33ea5643d9274c25f62491 Mon Sep 17 00:00:00 2001
From: Trond Myklebust <Trond.Myklebust@netapp.com>
Date: Wed, 1 Feb 2006 12:18:25 -0500
Subject: [PATCH] NLM: Ensure that nlmclnt_cancel_callback() doesn't loop
 forever

 If the server returns NLM_LCK_DENIED_NOLOCKS, we currently retry the
 entire NLM_CANCEL request. This may end up looping forever unless the
 server changes its mind (why would it do that, though?).

 Ensure that we limit the number of retries (to 3).

 See bug# 5957 in bugzilla.kernel.org.

 Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
 fs/lockd/clntproc.c         | 4 ++++
 include/linux/lockd/lockd.h | 1 +
 2 files changed, 5 insertions(+)

diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index b8ecfa1168f3e..220058d8616d1 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -22,6 +22,7 @@
 #define NLMDBG_FACILITY		NLMDBG_CLIENT
 #define NLMCLNT_GRACE_WAIT	(5*HZ)
 #define NLMCLNT_POLL_TIMEOUT	(30*HZ)
+#define NLMCLNT_MAX_RETRIES	3
 
 static int	nlmclnt_test(struct nlm_rqst *, struct file_lock *);
 static int	nlmclnt_lock(struct nlm_rqst *, struct file_lock *);
@@ -802,6 +803,9 @@ static void nlmclnt_cancel_callback(struct rpc_task *task, void *data)
 	return;
 
 retry_cancel:
+	/* Don't ever retry more than 3 times */
+	if (req->a_retries++ >= NLMCLNT_MAX_RETRIES)
+		goto die;
 	nlm_rebind_host(req->a_host);
 	rpc_restart_call(task);
 	rpc_delay(task, 30 * HZ);
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index afe9a8f5c5aed..920766cea79cb 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -84,6 +84,7 @@ struct nlm_rqst {
 	struct nlm_args		a_args;		/* arguments */
 	struct nlm_res		a_res;		/* result */
 	struct nlm_wait *	a_block;
+	unsigned int		a_retries;	/* Retry count */
 	char			a_owner[NLMCLNT_OHSIZE];
 };
 
-- 
GitLab