NFSv4: Remove redundant RENEW calls if we know the lease has expired

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 1c6fbd1..76eda46 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -39,6 +39,7 @@
 
 enum nfs4_client_state {
 	NFS4CLNT_STATE_RECOVER  = 0,
+	NFS4CLNT_CHECK_LEASE,
 	NFS4CLNT_LEASE_EXPIRED,
 	NFS4CLNT_RECLAIM_REBOOT,
 	NFS4CLNT_RECLAIM_NOGRACE,
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 279ab36..780ba00 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -984,7 +984,8 @@
 		ret = nfs4_wait_clnt_recover(server->client, clp);
 		if (ret != 0)
 			return ret;
-		if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
+		if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) &&
+		    !test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state))
 			break;
 		nfs4_schedule_state_recovery(clp);
 	}
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index e5cd8ca..3cc88a5 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -817,6 +817,8 @@
 {
 	if (!clp)
 		return;
+	if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
+		set_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state);
 	if (test_and_set_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) == 0)
 		nfs4_recover_state(clp);
 }
@@ -1019,6 +1021,23 @@
 	clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
 }
 
+static void nfs4_recovery_handle_error(struct nfs_client *clp, int error)
+{
+	switch (error) {
+		case -NFS4ERR_CB_PATH_DOWN:
+			set_bit(NFS4CLNT_CB_PATH_DOWN, &clp->cl_state);
+			break;
+		case -NFS4ERR_STALE_CLIENTID:
+		case -NFS4ERR_LEASE_MOVED:
+			set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
+			nfs4_state_start_reclaim_reboot(clp);
+			break;
+		case -NFS4ERR_EXPIRED:
+			set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
+			nfs4_state_start_reclaim_nograce(clp);
+	}
+}
+
 static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recovery_ops *ops)
 {
 	struct rb_node *pos;
@@ -1031,6 +1050,7 @@
 		if (status < 0)
 			break;
 	}
+	nfs4_recovery_handle_error(clp, status);
 	return status;
 }
 
@@ -1045,19 +1065,7 @@
 		/* Yes there are: try to renew the old lease */
 		status = nfs4_proc_renew(clp, cred);
 		put_rpccred(cred);
-		switch (status) {
-			case -NFS4ERR_CB_PATH_DOWN:
-				set_bit(NFS4CLNT_CB_PATH_DOWN, &clp->cl_state);
-				break;
-			case -NFS4ERR_STALE_CLIENTID:
-			case -NFS4ERR_LEASE_MOVED:
-				set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
-				nfs4_state_start_reclaim_reboot(clp);
-				break;
-			case -NFS4ERR_EXPIRED:
-				set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
-				nfs4_state_start_reclaim_nograce(clp);
-		}
+		nfs4_recovery_handle_error(clp, status);
 		return status;
 	}
 
@@ -1095,8 +1103,6 @@
 	/* Ensure exclusive access to NFSv4 state */
 	down_write(&clp->cl_sem);
 	while (!list_empty(&clp->cl_superblocks)) {
-		status = nfs4_check_lease(clp);
-
 		if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) {
 			/* We're going to have to re-establish a clientid */
 			status = nfs4_reclaim_lease(clp);
@@ -1106,16 +1112,21 @@
 					continue;
 				goto out_error;
 			}
+			clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state);
+		}
+
+		if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) {
+			status = nfs4_check_lease(clp);
+			if (status != 0)
+				continue;
 		}
 
 		/* First recover reboot state... */
 		if (test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) {
 			/* Note: list is protected by exclusive lock on cl->cl_sem */
 			status = nfs4_do_reclaim(clp, &nfs4_reboot_recovery_ops);
-			if (status == -NFS4ERR_STALE_CLIENTID) {
-				set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state);
+			if (status == -NFS4ERR_STALE_CLIENTID)
 				continue;
-			}
 			nfs4_state_end_reclaim_reboot(clp);
 			continue;
 		}