From: Chuck Lever <chuck.lever@oracle.com>
To: linux-nfs@vger.kernel.org
Subject: [PATCH v1 10/19] NFS: Implement a transport blocking scheme for migration
Date: Fri, 12 Jul 2013 12:32:54 -0400 [thread overview]
Message-ID: <20130712163254.1444.29296.stgit@seurat.1015granger.net> (raw)
In-Reply-To: <20130712155303.1444.62697.stgit@seurat.1015granger.net>
When an NFSv4 migration event occurs, an NFS client must redirect
a mount point's underlying RPC transport to a different NFS server.
Before performing this redirection, the client must plug the RPC
transport to prevent the initiation of new requests, and allow
any pending requests or the migrating FSID to complete.
Only then is it safe to swap in a transport to the destination
server. This is like NFSv4.1 session draining, so we adopt a
similar approach.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfs/nfs4_fs.h | 1 +
fs/nfs/nfs4client.c | 4 ++++
fs/nfs/nfs4proc.c | 43 ++++++++++++++++++++++++++++++++++++++-----
fs/nfs/nfs4state.c | 19 +++++++++++++++++++
include/linux/nfs_fs_sb.h | 4 ++++
5 files changed, 66 insertions(+), 5 deletions(-)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index ae05978..b9c839e 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -29,6 +29,7 @@ enum nfs4_client_state {
NFS4CLNT_SERVER_SCOPE_MISMATCH,
NFS4CLNT_PURGE_STATE,
NFS4CLNT_BIND_CONN_TO_SESSION,
+ NFS4CLNT_BLOCK_XPRT,
};
#define NFS4_RENEW_TIMEOUT 0x01
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index 3aec2de..4d208e0 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -72,6 +72,10 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init)
clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
clp->cl_minorversion = cl_init->minorversion;
clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion];
+ if (clp->cl_minorversion == 0) {
+ init_completion(&clp->cl_xpcomplete);
+ rpc_init_wait_queue(&clp->cl_xpwaitq, "NFSv4.0 xprt");
+ }
return clp;
error:
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 20768e8..bb5100a 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -414,6 +414,40 @@ static int nfs4_run_rpc_task(struct rpc_clnt *clnt,
return ret;
}
+/*
+ * Returns -EAGAIN if task must wait for migration recovery;
+ * otherwise, zero is returned.
+ */
+static int nfs4_transport_setup(const struct nfs_server *server,
+ struct rpc_task *task)
+{
+ struct nfs_client *clp = server->nfs_client;
+
+ spin_lock(&clp->cl_lock);
+ if (test_bit(NFS4CLNT_BLOCK_XPRT, &clp->cl_state)) {
+ rpc_sleep_on(&clp->cl_xpwaitq, task, NULL);
+ spin_unlock(&clp->cl_lock);
+ dprintk("--> %s transport blocked for server %s\n",
+ __func__, clp->cl_hostname);
+ return -EAGAIN;
+ }
+ atomic_inc(&clp->cl_xppending);
+ spin_unlock(&clp->cl_lock);
+
+ rpc_call_start(task);
+ return 0;
+}
+
+static int nfs4_transport_done(const struct nfs_server *server)
+{
+ struct nfs_client *clp = server->nfs_client;
+
+ if (atomic_dec_and_test(&clp->cl_xppending) &&
+ test_bit(NFS4CLNT_BLOCK_XPRT, &clp->cl_state))
+ complete(&clp->cl_xpcomplete);
+ return 1;
+}
+
#if defined(CONFIG_NFS_V4_1)
static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
@@ -558,7 +592,7 @@ static int nfs4_sequence_done(const struct nfs_server *server,
struct nfs4_sequence_res *res)
{
if (res->sr_slot == NULL)
- return 1;
+ return nfs4_transport_done(server);
return nfs41_sequence_done(task, res);
}
@@ -650,7 +684,7 @@ static int nfs4_setup_sequence(const struct nfs_server *server,
int ret = 0;
if (session == NULL) {
- rpc_call_start(task);
+ ret = nfs4_transport_setup(server, task);
goto out;
}
@@ -723,15 +757,14 @@ static int nfs4_setup_sequence(const struct nfs_server *server,
struct nfs4_sequence_res *res,
struct rpc_task *task)
{
- rpc_call_start(task);
- return 0;
+ return nfs4_transport_setup(server, task);
}
static int nfs4_sequence_done(const struct nfs_server *server,
struct rpc_task *task,
struct nfs4_sequence_res *res)
{
- return 1;
+ return nfs4_transport_done(server);
}
#endif /* CONFIG_NFS_V4_1 */
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 71fc85d..ae482b2 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -355,6 +355,25 @@ int nfs41_discover_server_trunking(struct nfs_client *clp,
#endif /* CONFIG_NFS_V4_1 */
+static void nfs4_end_drain_xprt(struct nfs_client *clp)
+{
+ if (test_and_clear_bit(NFS4CLNT_BLOCK_XPRT, &clp->cl_state))
+ rpc_wake_up(&clp->cl_xpwaitq);
+}
+
+static int nfs4_begin_drain_xprt(struct nfs_client *clp)
+{
+ set_bit(NFS4CLNT_BLOCK_XPRT, &clp->cl_state);
+ spin_lock(&clp->cl_lock);
+ if (atomic_read(&clp->cl_xppending)) {
+ INIT_COMPLETION(clp->cl_xpcomplete);
+ spin_unlock(&clp->cl_lock);
+ return wait_for_completion_interruptible(&clp->cl_xpcomplete);
+ }
+ spin_unlock(&clp->cl_lock);
+ return 0;
+}
+
/**
* nfs4_get_clid_cred - Acquire credential for a setclientid operation
* @clp: client state handle
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 3b7fa2a..ad47c90 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -78,6 +78,10 @@ struct nfs_client {
u32 cl_cb_ident; /* v4.0 callback identifier */
const struct nfs4_minor_version_ops *cl_mvops;
+ atomic_t cl_xppending;
+ struct completion cl_xpcomplete;
+ struct rpc_wait_queue cl_xpwaitq;
+
/* The sequence id to use for the next CREATE_SESSION */
u32 cl_seqid;
/* The flags used for obtaining the clientid during EXCHANGE_ID */
next prev parent reply other threads:[~2013-07-12 16:38 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 ` Chuck Lever [this message]
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 ` [PATCH v1 18/19] NFS: Implement support for NFS4ERR_LEASE_MOVED Chuck Lever
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=20130712163254.1444.29296.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).