forked from mirrors/linux
		
	NFS: Add nfs4_update_server
New function nfs4_update_server() moves an nfs_server to a different nfs_client. This is done as part of migration recovery. Though it may be appealing to think of them as the same thing, migration recovery is not the same as following a referral. For a referral, the client has not descended into the file system yet: it has no nfs_server, no super block, no inodes or open state. It is enough to simply instantiate the nfs_server and super block, and perform a referral mount. For a migration, however, we have all of those things already, and they have to be moved to a different nfs_client. No local namespace changes are needed here. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
		
							parent
							
								
									40b00b6b17
								
							
						
					
					
						commit
						32e62b7c3e
					
				
					 3 changed files with 113 additions and 1 deletions
				
			
		| 
						 | 
					@ -945,7 +945,7 @@ void nfs_server_insert_lists(struct nfs_server *server)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(nfs_server_insert_lists);
 | 
					EXPORT_SYMBOL_GPL(nfs_server_insert_lists);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void nfs_server_remove_lists(struct nfs_server *server)
 | 
					void nfs_server_remove_lists(struct nfs_server *server)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct nfs_client *clp = server->nfs_client;
 | 
						struct nfs_client *clp = server->nfs_client;
 | 
				
			||||||
	struct nfs_net *nn;
 | 
						struct nfs_net *nn;
 | 
				
			||||||
| 
						 | 
					@ -962,6 +962,7 @@ static void nfs_server_remove_lists(struct nfs_server *server)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	synchronize_rcu();
 | 
						synchronize_rcu();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(nfs_server_remove_lists);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Allocate and initialise a server record
 | 
					 * Allocate and initialise a server record
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -154,6 +154,7 @@ struct nfs_client *nfs_get_client(const struct nfs_client_initdata *,
 | 
				
			||||||
				  rpc_authflavor_t);
 | 
									  rpc_authflavor_t);
 | 
				
			||||||
int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *, struct nfs_fattr *);
 | 
					int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *, struct nfs_fattr *);
 | 
				
			||||||
void nfs_server_insert_lists(struct nfs_server *);
 | 
					void nfs_server_insert_lists(struct nfs_server *);
 | 
				
			||||||
 | 
					void nfs_server_remove_lists(struct nfs_server *);
 | 
				
			||||||
void nfs_init_timeout_values(struct rpc_timeout *, int, unsigned int, unsigned int);
 | 
					void nfs_init_timeout_values(struct rpc_timeout *, int, unsigned int, unsigned int);
 | 
				
			||||||
int nfs_init_server_rpcclient(struct nfs_server *, const struct rpc_timeout *t,
 | 
					int nfs_init_server_rpcclient(struct nfs_server *, const struct rpc_timeout *t,
 | 
				
			||||||
		rpc_authflavor_t);
 | 
							rpc_authflavor_t);
 | 
				
			||||||
| 
						 | 
					@ -174,6 +175,8 @@ extern struct nfs_server *nfs4_create_server(
 | 
				
			||||||
					struct nfs_subversion *);
 | 
										struct nfs_subversion *);
 | 
				
			||||||
extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *,
 | 
					extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *,
 | 
				
			||||||
						      struct nfs_fh *);
 | 
											      struct nfs_fh *);
 | 
				
			||||||
 | 
					extern int nfs4_update_server(struct nfs_server *server, const char *hostname,
 | 
				
			||||||
 | 
										struct sockaddr *sap, size_t salen);
 | 
				
			||||||
extern void nfs_free_server(struct nfs_server *server);
 | 
					extern void nfs_free_server(struct nfs_server *server);
 | 
				
			||||||
extern struct nfs_server *nfs_clone_server(struct nfs_server *,
 | 
					extern struct nfs_server *nfs_clone_server(struct nfs_server *,
 | 
				
			||||||
					   struct nfs_fh *,
 | 
										   struct nfs_fh *,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1092,3 +1092,111 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
 | 
				
			||||||
	dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
 | 
						dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
 | 
				
			||||||
	return ERR_PTR(error);
 | 
						return ERR_PTR(error);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Grab the destination's particulars, including lease expiry time.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns zero if probe succeeded and retrieved FSID matches the FSID
 | 
				
			||||||
 | 
					 * we have cached.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int nfs_probe_destination(struct nfs_server *server)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct inode *inode = server->super->s_root->d_inode;
 | 
				
			||||||
 | 
						struct nfs_fattr *fattr;
 | 
				
			||||||
 | 
						int error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fattr = nfs_alloc_fattr();
 | 
				
			||||||
 | 
						if (fattr == NULL)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Sanity: the probe won't work if the destination server
 | 
				
			||||||
 | 
						 * does not recognize the migrated FH. */
 | 
				
			||||||
 | 
						error = nfs_probe_fsinfo(server, NFS_FH(inode), fattr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nfs_free_fattr(fattr);
 | 
				
			||||||
 | 
						return error;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * nfs4_update_server - Move an nfs_server to a different nfs_client
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @server: represents FSID to be moved
 | 
				
			||||||
 | 
					 * @hostname: new end-point's hostname
 | 
				
			||||||
 | 
					 * @sap: new end-point's socket address
 | 
				
			||||||
 | 
					 * @salen: size of "sap"
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The nfs_server must be quiescent before this function is invoked.
 | 
				
			||||||
 | 
					 * Either its session is drained (NFSv4.1+), or its transport is
 | 
				
			||||||
 | 
					 * plugged and drained (NFSv4.0).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns zero on success, or a negative errno value.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nfs_server_remove_lists(server);
 | 
				
			||||||
 | 
						error = nfs4_set_client(server, hostname, sap, salen, buf,
 | 
				
			||||||
 | 
									clp->cl_rpcclient->cl_auth->au_flavor,
 | 
				
			||||||
 | 
									clp->cl_proto, clnt->cl_timeout,
 | 
				
			||||||
 | 
									clp->cl_minorversion, clp->cl_net);
 | 
				
			||||||
 | 
						nfs_put_client(clp);
 | 
				
			||||||
 | 
						if (error != 0) {
 | 
				
			||||||
 | 
							nfs_server_insert_lists(server);
 | 
				
			||||||
 | 
							dprintk("<-- %s(): nfs4_set_client returned %d\n",
 | 
				
			||||||
 | 
								__func__, error);
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (server->nfs_client->cl_hostname == NULL)
 | 
				
			||||||
 | 
							server->nfs_client->cl_hostname = kstrdup(hostname, GFP_KERNEL);
 | 
				
			||||||
 | 
						nfs_server_insert_lists(server);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						error = nfs_probe_destination(server);
 | 
				
			||||||
 | 
						if (error < 0)
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dprintk("<-- %s() succeeded\n", __func__);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						return error;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue