linux-nfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Chuck Lever <chuck.lever@oracle.com>
To: linux-nfs@vger.kernel.org
Subject: [PATCH v1 18/19] NFS: Implement support for NFS4ERR_LEASE_MOVED
Date: Fri, 12 Jul 2013 12:34:04 -0400	[thread overview]
Message-ID: <20130712163404.1444.39607.stgit@seurat.1015granger.net> (raw)
In-Reply-To: <20130712155303.1444.62697.stgit@seurat.1015granger.net>

To recover from NFS4ERR_LEASE_MOVED, walk the cl_superblocks list and
invoke nfs4_try_migration() on each server's root file handle if that
FSID is no longer present on the server.  The FSID presence check also
informs servers that this client has recognized the LEASE_MOVED
condition and therefore should no longer receive NFS4ERR_LEASE_MOVED.

Minor version 1 servers set a bit flag to signal LEASE_MOVED rather
than returning an NFS4ERR status code, as minor version 0 servers do.
Our client must recognize this flag and kick off migration recovery.
The flag is detected when processing the SEQUENCE reply in each mv1
compound.

Note also that with minor version 0, the asynchronous lease RENEW
heartbeat can return NFS4ERR_LEASE_MOVED.  Error recovery logic for
async RENEW is a separate code path from the generic NFS proc paths,
so it must be updated to handle LEASE_MOVED as well.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 fs/nfs/nfs4_fs.h   |    2 +
 fs/nfs/nfs4proc.c  |   19 +++++++++++++-
 fs/nfs/nfs4state.c |   70 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 87 insertions(+), 4 deletions(-)

diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 77313db..9f2fe35 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -31,6 +31,7 @@ enum nfs4_client_state {
 	NFS4CLNT_BIND_CONN_TO_SESSION,
 	NFS4CLNT_BLOCK_XPRT,
 	NFS4CLNT_MOVED,
+	NFS4CLNT_LEASE_MOVED,
 };
 
 #define NFS4_RENEW_TIMEOUT		0x01
@@ -352,6 +353,7 @@ extern void nfs4_schedule_state_manager(struct nfs_client *);
 extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp);
 extern int nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *);
 extern int nfs4_schedule_migration_recovery(struct inode *);
+extern void nfs4_schedule_lease_moved_recovery(struct nfs_client *);
 extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags);
 extern void nfs41_handle_server_scope(struct nfs_client *,
 				      struct nfs41_server_scope **);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index a870a59..80afb9f 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -350,6 +350,9 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode,
 			if (ret < 0)
 				break;
 			goto wait_on_recovery;
+		case -NFS4ERR_LEASE_MOVED:
+			nfs4_schedule_lease_moved_recovery(clp);
+			goto wait_on_recovery;
 		case -NFS4ERR_FILE_OPEN:
 			if (exception->timeout > HZ) {
 				/* We have retried a decent amount, time to
@@ -3937,7 +3940,13 @@ static void nfs4_renew_done(struct rpc_task *task, void *calldata)
 	struct nfs_client *clp = data->client;
 	unsigned long timestamp = data->timestamp;
 
-	if (task->tk_status < 0) {
+	switch (task->tk_status) {
+	case 0:
+		break;
+	case -NFS4ERR_LEASE_MOVED:
+		nfs4_schedule_lease_moved_recovery(clp);
+		break;
+	default:
 		/* Unless we're shutting down, schedule state recovery! */
 		if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) == 0)
 			return;
@@ -4342,6 +4351,14 @@ static int nfs4_async_handle_error(struct rpc_task *task,
 				rpc_wake_up_queued_task(&clp->cl_rpcwaitq,
 									task);
 			goto restart_call;
+		case -NFS4ERR_LEASE_MOVED:
+			rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
+			nfs4_schedule_lease_moved_recovery(clp);
+			if (test_bit(NFS4CLNT_MANAGER_RUNNING,
+							&clp->cl_state) == 0)
+				rpc_wake_up_queued_task(&clp->cl_rpcwaitq,
+									task);
+			goto restart_call;
 		case -NFS4ERR_DELAY:
 			nfs_inc_server_stats(server, NFSIOS_DELAY);
 		case -NFS4ERR_GRACE:
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 4757188..ce2b51d 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1258,6 +1258,22 @@ int nfs4_schedule_migration_recovery(struct inode *inode)
 }
 EXPORT_SYMBOL_GPL(nfs4_schedule_migration_recovery);
 
+/**
+ * nfs4_schedule_lease_moved_recovery - start lease-moved recovery
+ *
+ * @clp: server to check for moved leases
+ *
+ */
+void nfs4_schedule_lease_moved_recovery(struct nfs_client *clp)
+{
+	dprintk("%s: scheduling lease-moved recovery for client ID %llx on %s\n",
+		__func__, clp->cl_clientid, clp->cl_hostname);
+
+	set_bit(NFS4CLNT_LEASE_MOVED, &clp->cl_state);
+	nfs4_schedule_state_manager(clp);
+}
+EXPORT_SYMBOL_GPL(nfs4_schedule_lease_moved_recovery);
+
 int nfs4_wait_clnt_recover(struct nfs_client *clp)
 {
 	int res;
@@ -1680,7 +1696,6 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
 			nfs4_state_end_reclaim_reboot(clp);
 			break;
 		case -NFS4ERR_STALE_CLIENTID:
-		case -NFS4ERR_LEASE_MOVED:
 			set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
 			nfs4_state_clear_reclaim_reboot(clp);
 			nfs4_state_start_reclaim_reboot(clp);
@@ -2007,7 +2022,46 @@ restart:
 		goto restart;
 	}
 	rcu_read_unlock();
+	dprintk("<-- %s\n", __func__);
+	return 0;
+}
+
+/*
+ * Test each nfs_server on the clp's cl_superblocks list to see
+ * if it's moved to another server.  Stop when the server no longer
+ * returns NFS4ERR_LEASE_MOVED.
+ */
+static int nfs4_handle_lease_moved(struct nfs_client *clp)
+{
+	struct nfs_server *server;
+
+	dprintk("--> %s: \"%s\" (client ID %llx)\n",
+		__func__, clp->cl_hostname, clp->cl_clientid);
+
+	clp->cl_mig_gen++;
+restart:
+	rcu_read_lock();
+	list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
+		struct inode *inode;
+		int status;
+
+		if (server->mig_gen == clp->cl_mig_gen)
+			continue;
+		server->mig_gen = clp->cl_mig_gen;
+
+		rcu_read_unlock();
+
+		inode = server->super->s_root->d_inode;
+		status = nfs4_proc_fsid_present(inode);
+		if (status != -NFS4ERR_MOVED)
+			goto restart;	/* wasn't this one */
+		if (nfs4_try_migration(server) == -NFS4ERR_LEASE_MOVED)
+			goto restart;	/* there are more */
+		goto out;
+	}
+	rcu_read_unlock();
 
+out:
 	dprintk("<-- %s\n", __func__);
 	return 0;
 }
@@ -2201,9 +2255,10 @@ void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags)
 		nfs41_handle_server_reboot(clp);
 	if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED |
 			    SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED |
-			    SEQ4_STATUS_ADMIN_STATE_REVOKED |
-			    SEQ4_STATUS_LEASE_MOVED))
+			    SEQ4_STATUS_ADMIN_STATE_REVOKED))
 		nfs41_handle_state_revoked(clp);
+	if (flags & SEQ4_STATUS_LEASE_MOVED)
+		nfs4_schedule_lease_moved_recovery(clp);
 	if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED)
 		nfs41_handle_recallable_state_revoked(clp);
 	if (flags & SEQ4_STATUS_BACKCHANNEL_FAULT)
@@ -2352,6 +2407,15 @@ static void nfs4_state_manager(struct nfs_client *clp)
 			continue;
 		}
 
+		if (test_bit(NFS4CLNT_LEASE_MOVED, &clp->cl_state)) {
+			section = "lease moved";
+			status = nfs4_handle_lease_moved(clp);
+			if (status < 0)
+				goto out_error;
+			clear_bit(NFS4CLNT_LEASE_MOVED, &clp->cl_state);
+			continue;
+		}
+
 		/* First recover reboot state... */
 		if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) {
 			section = "reclaim reboot";


  parent reply	other threads:[~2013-07-12 16:34 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-12 16:31 [PATCH v1 00/19] NFSv4 migration Chuck Lever
2013-07-12 16:31 ` [PATCH v1 01/19] NFS: Never use user credentials for lease renewal Chuck Lever
2013-07-22 18:33   ` Myklebust, Trond
2013-07-22 18:52     ` Chuck Lever
2013-07-22 18:53       ` Myklebust, Trond
2013-07-22 18:56         ` Chuck Lever
2013-07-12 16:31 ` [PATCH v1 02/19] NFS: Fix return type of nfs4_end_drain_session() stub Chuck Lever
2013-07-12 16:31 ` [PATCH v1 03/19] NFS: Introduce a vector of migration recovery ops Chuck Lever
2013-07-12 16:32 ` [PATCH v1 04/19] NFS: Refactor nfs4_call_data_sequence() Chuck Lever
2013-07-22 19:08   ` Myklebust, Trond
2013-07-12 16:32 ` [PATCH v1 05/19] NFS: Rename nfs41_call_sync_data as a common data structure Chuck Lever
2013-07-12 16:32 ` [PATCH v1 06/19] NFS: Clean up nfs4_setup_sequence() Chuck Lever
2013-07-12 16:32 ` [PATCH v1 07/19] NFS: Fix compiler warning in nfs_setup_sequence() Chuck Lever
2013-07-22 19:03   ` Myklebust, Trond
2013-07-22 20:16     ` Chuck Lever
2013-07-22 20:22       ` Myklebust, Trond
2013-07-22 20:24         ` Chuck Lever
2013-07-12 16:32 ` [PATCH v1 08/19] NFS: Use RPC callouts to start NFSv4.0 synchronous requests Chuck Lever
2013-07-12 16:32 ` [PATCH v1 09/19] NFS: Add a "struct nfs_server *" argument to nfs4_sequence_done() Chuck Lever
2013-07-22 19:27   ` Myklebust, Trond
2013-07-24 22:04     ` Chuck Lever
2013-07-12 16:32 ` [PATCH v1 10/19] NFS: Implement a transport blocking scheme for migration Chuck Lever
2013-07-12 16:33 ` [PATCH v1 11/19] SUNRPC: Add a helper to switch the transport of an rpc_clnt Chuck Lever
2013-07-12 16:33 ` [PATCH v1 12/19] NFS: Add a super_block backpointer to the nfs_server struct Chuck Lever
2013-07-12 16:33 ` [PATCH v1 13/19] NFS: Add functions to swap transports during migration recovery Chuck Lever
2013-07-12 16:33 ` [PATCH v1 14/19] NFS: Add method to retrieve fs_locations " Chuck Lever
2013-07-12 16:33 ` [PATCH v1 15/19] NFS: Add basic migration support to state manager thread Chuck Lever
2013-07-12 16:33 ` [PATCH v1 16/19] NFS: Add migration recovery callouts in nfs4proc.c Chuck Lever
2013-07-12 16:33 ` [PATCH v1 17/19] NFS: Add method to detect whether an FSID is still on the server Chuck Lever
2013-07-12 16:34 ` Chuck Lever [this message]
2013-07-12 16:34 ` [PATCH v1 19/19] NFS: Set EXCHGID4_FLAG_SUPP_MOVED_MIGR Chuck Lever

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130712163404.1444.39607.stgit@seurat.1015granger.net \
    --to=chuck.lever@oracle.com \
    --cc=linux-nfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).