All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chuck Lever <chuck.lever@oracle.com>
To: trond.myklebust@netapp.com
Cc: linux-nfs@vger.kernel.org
Subject: [PATCH 12/16] NFS: Add functions to swap transports during migration recovery
Date: Mon, 09 May 2011 15:38:13 -0400	[thread overview]
Message-ID: <20110509193813.16568.4549.stgit@matisse.1015granger.net> (raw)
In-Reply-To: <20110509192522.16568.59082.stgit@matisse.1015granger.net>

Introduce functions that can walk through an array of returned
fs_locations information and connect a transport to one of the
destination servers listed therein.

Note that NFS minor version 1 introduces "fs_locations_info" which
extends the locations array sorting criteria available to clients.
This is not supported yet.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---

 fs/nfs/internal.h      |    2 
 fs/nfs/nfs4namespace.c |  202 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 204 insertions(+), 0 deletions(-)

diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 0bf4e67..191c5b4 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -177,6 +177,8 @@ static inline void nfs_fs_proc_exit(void)
 /* nfs4namespace.c */
 #ifdef CONFIG_NFS_V4
 extern struct vfsmount *nfs_do_refmount(struct dentry *dentry);
+extern int nfs4_replace_transport(struct nfs_server *server,
+		const struct nfs4_fs_locations *locations);
 #else
 static inline
 struct vfsmount *nfs_do_refmount(struct dentry *dentry)
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index bb80c49..2fa024c 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -22,6 +22,8 @@
 
 #define NFSDBG_FACILITY		NFSDBG_VFS
 
+#undef USE_RPC_LOCK_CLIENT
+
 /*
  * Convert the NFSv4 pathname components into a standard posix path.
  *
@@ -263,3 +265,203 @@ out:
 	dprintk("%s: done\n", __func__);
 	return mnt;
 }
+
+#undef NFSDBG_FACILITY
+#define NFSDBG_FACILITY		NFSDBG_CLIENT
+
+/*
+ * Returns zero on success, or a negative errno value.
+ */
+static int nfs4_update_server(struct nfs_server *server, const char *hostname,
+			      struct sockaddr *sap, size_t salen)
+{
+	struct nfs_client *clp = server->nfs_client;
+	struct rpc_clnt *clnt = server->client;
+	struct xprt_create xargs = {
+		.ident		= clp->cl_proto,
+		.net		= &init_net,
+		.dstaddr	= sap,
+		.addrlen	= salen,
+		.servername	= hostname,
+	};
+	char buf[INET6_ADDRSTRLEN + 1];
+	struct sockaddr_storage address;
+	struct sockaddr *localaddr = (struct sockaddr *)&address;
+	int error;
+
+	dprintk("--> %s: move FSID %llx:%llx to \"%s\")\n", __func__,
+			(unsigned long long)server->fsid.major,
+			(unsigned long long)server->fsid.minor,
+			hostname);
+
+	/*
+	 * rpc_lock_client() deadlocks here.  This is because the tasks
+	 * that received NFS4ERR_MOVED are waiting for us to wake them
+	 * when we are done recovering.  But they have bumped
+	 * cl_active_tasks for this clnt, so rpc_lock_client() can't make
+	 * any progress.
+	 */
+#ifdef USE_RPC_LOCK_CLIENT
+	error = rpc_lock_client(clnt, clnt->cl_timeout->to_maxval);
+	if (error != 0) {
+		dprintk("<-- %s(): rpc_lock_client returned %d\n",
+			__func__, error);
+		goto out;
+	}
+#endif	/* USE_RPC_LOCK_CLIENT */
+
+	error = rpc_switch_client_transport(clnt, &xargs, clnt->cl_timeout);
+	if (error != 0) {
+		dprintk("<-- %s(): rpc_switch_client_transport returned %d\n",
+			__func__, error);
+		goto out;
+	}
+
+	/*
+	 * If we were able to contact the server at @sap, set up a new
+	 * nfs_client and move @server to it.
+	 */
+	error = rpc_localaddr(clnt, localaddr, sizeof(address));
+	if (error != 0) {
+		dprintk("<-- %s(): rpc_localaddr returned %d\n",
+			__func__, error);
+		goto out;
+	}
+	error = -EAFNOSUPPORT;
+	if (rpc_ntop(localaddr, buf, sizeof(buf)) == 0) {
+		dprintk("<-- %s(): rpc_ntop returned %d\n",
+			__func__, error);
+		goto out;
+	}
+	error = nfs4_clone_client(clp, sap, salen, buf, server);
+	if (error != 0) {
+		dprintk("<-- %s(): nfs4_clone_client returned %d\n",
+			__func__, error);
+		goto out;
+	}
+	if (server->nfs_client->cl_hostname == NULL)
+		server->nfs_client->cl_hostname = kstrdup(hostname, GFP_KERNEL);
+
+	dprintk("<-- %s() succeeded\n", __func__);
+
+out:
+#ifdef USE_RPC_LOCK_CLIENT
+	rpc_unlock_client(clnt);
+#endif	/* USE_RPC_LOCK_CLIENT */
+	return error;
+}
+
+/*
+ * Try one location from the fs_locations array.
+ *
+ * Returns zero on success, or a negative errno value.
+ */
+static int nfs4_try_replacing_one_location(struct nfs_server *server,
+		char *page, char *page2,
+		const struct nfs4_fs_location *location)
+{
+	const size_t addr_bufsize = sizeof(struct sockaddr_storage);
+	struct sockaddr *sap;
+	unsigned int s;
+	size_t salen;
+	int error;
+
+	dprintk("--> %s(%llx:%llx)\n", __func__,
+			(unsigned long long)server->fsid.major,
+			(unsigned long long)server->fsid.minor);
+
+	error = -ENOMEM;
+	sap = kmalloc(addr_bufsize, GFP_KERNEL);
+	if (sap == NULL)
+		goto out;
+
+	error = -ENOENT;
+	for (s = 0; s < location->nservers; s++) {
+		const struct nfs4_string *buf = &location->servers[s];
+		char *hostname;
+
+		if (buf->len <= 0 || buf->len > PAGE_SIZE)
+			continue;
+
+		/* XXX: IPv6 not supported? */
+		if (memchr(buf->data, IPV6_SCOPE_DELIMITER, buf->len) != NULL)
+			continue;
+
+		salen = nfs_parse_server_name(buf->data, buf->len,
+						sap, addr_bufsize);
+		if (salen == 0)
+			continue;
+		rpc_set_port(sap, NFS_PORT);
+
+		error = -ENOMEM;
+		hostname = kstrndup(buf->data, buf->len, GFP_KERNEL);
+		if (hostname == NULL)
+			break;
+
+		error = nfs4_update_server(server, hostname, sap, salen);
+		kfree(hostname);
+		if (error == 0)
+			break;
+	}
+
+	kfree(sap);
+out:
+	dprintk("<-- %s() = %d\n", __func__, error);
+	return error;
+}
+
+/**
+ * nfs4_replace_transport - set up transport to destination server
+ *
+ * @server: export being migrated
+ * @locations: fs_locations array
+ *
+ * Returns zero on success, or a negative errno value.
+ *
+ * The client tries all the entries in the "locations" array, in the
+ * order returned by the server, until one works or the end of the
+ * array is reached.
+ */
+int nfs4_replace_transport(struct nfs_server *server,
+			   const struct nfs4_fs_locations *locations)
+{
+	char *page = NULL, *page2 = NULL;
+	int loc, error;
+
+	dprintk("--> %s(%llx:%llx)\n", __func__,
+			(unsigned long long)server->fsid.major,
+			(unsigned long long)server->fsid.minor);
+
+	error = -ENOENT;
+	if (locations == NULL || locations->nlocations <= 0)
+		goto out;
+
+	error = -ENOMEM;
+	page = (char *) __get_free_page(GFP_USER);
+	if (!page)
+		goto out;
+	page2 = (char *) __get_free_page(GFP_USER);
+	if (!page2)
+		goto out;
+
+	for (loc = 0; loc < locations->nlocations; loc++) {
+		const struct nfs4_fs_location *location =
+						&locations->locations[loc];
+
+		if (location == NULL || location->nservers <= 0 ||
+		    location->rootpath.ncomponents == 0)
+			continue;
+
+		error = nfs4_try_replacing_one_location(server, page,
+							page2, location);
+		if (error == 0)
+			break;
+	}
+
+out:
+	free_page((unsigned long)page);
+	free_page((unsigned long)page2);
+
+	dprintk("<-- %s() = %d\n", __func__, error);
+	return error;
+}


  parent reply	other threads:[~2011-05-09 19:38 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-05-09 19:36 [PATCH 00/16] Client-side migration support for 2.6.40 [take 3] Chuck Lever
2011-05-09 19:36 ` [PATCH 01/16] SUNRPC: Allow temporary blocking of an rpc client Chuck Lever
2011-05-09 19:36 ` [PATCH 02/16] SUNRPC: Use RCU to dereference the rpc_clnt.cl_xprt field Chuck Lever
2011-05-09 19:36 ` [PATCH 03/16] SUNRPC: Move clnt->cl_server into struct rpc_xprt Chuck Lever
2011-05-09 19:36 ` [PATCH 04/16] SUNRPC: Add a helper to switch the transport of the rpc_client Chuck Lever
2011-05-09 19:37 ` [PATCH 05/16] SUNRPC: Add API to acquire source address Chuck Lever
2011-05-09 19:37 ` [PATCH 06/16] NFS: Add a client-side function to display file handles Chuck Lever
2011-05-09 19:37 ` [PATCH 07/16] NFS: Save root file handle in nfs_server Chuck Lever
2011-05-09 19:37 ` [PATCH 08/16] NFS: Introduce NFS_ATTR_FATTR_V4_LOCATIONS Chuck Lever
2011-05-09 19:37 ` [PATCH 09/16] NFS: Introduce nfs4_proc_get_mig_status() Chuck Lever
2011-05-09 19:37 ` [PATCH 10/16] NFS: Add infrastructure for updating callback data Chuck Lever
2011-05-09 19:38 ` [PATCH 11/16] NFS: Add an API for cloning an nfs_client Chuck Lever
2011-05-12 17:30   ` Chuck Lever
2011-05-12 19:30     ` Trond Myklebust
2011-05-09 19:38 ` Chuck Lever [this message]
2011-05-09 19:38 ` [PATCH 13/16] NFS: Add basic migration support to state manager thread Chuck Lever
2011-05-09 19:38 ` [PATCH 14/16] NFS: Remove "const" from "struct nfs_server *" fields Chuck Lever
2011-05-09 19:38 ` [PATCH 15/16] NFS: Add migration recovery callouts in nfs4proc.c Chuck Lever
2011-05-09 19:38 ` [PATCH 16/16] NFS: Implement support for NFS4ERR_LEASE_MOVED Chuck Lever
2011-05-09 22:48   ` Chuck Lever
2011-05-11  0:20     ` Tom Haynes
     [not found]       ` <4DC9D636.3050307-8AdZ+HgO7noAvxtiuMwx3w@public.gmane.org>
2011-05-11 14:04         ` Chuck Lever
2011-05-12 15:37       ` 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=20110509193813.16568.4549.stgit@matisse.1015granger.net \
    --to=chuck.lever@oracle.com \
    --cc=linux-nfs@vger.kernel.org \
    --cc=trond.myklebust@netapp.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.