pNFS: return status from nfs4_pnfs_ds_connect
The nfs4_pnfs_ds_connect path can call rpc_create which can fail or it can wait on another context to reach the same failure. This checks that the rpc_create succeeded and returns the error to the caller. When an error is returned, both the files and flexfiles layouts will return NULL from _prepare_ds(). The flexfiles layout will also return the layout with the error NFS4ERR_NXIO. Signed-off-by: Weston Andros Adamson <dros@primarydata.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
		
							parent
							
								
									033853325f
								
							
						
					
					
						commit
						a33e4b036d
					
				| @ -325,10 +325,33 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat | |||||||
| 	return NULL; | 	return NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool nfs_client_init_is_complete(const struct nfs_client *clp) | /*
 | ||||||
|  |  * Return true if @clp is done initializing, false if still working on it. | ||||||
|  |  * | ||||||
|  |  * Use nfs_client_init_status to check if it was successful. | ||||||
|  |  */ | ||||||
|  | bool nfs_client_init_is_complete(const struct nfs_client *clp) | ||||||
| { | { | ||||||
| 	return clp->cl_cons_state <= NFS_CS_READY; | 	return clp->cl_cons_state <= NFS_CS_READY; | ||||||
| } | } | ||||||
|  | EXPORT_SYMBOL_GPL(nfs_client_init_is_complete); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Return 0 if @clp was successfully initialized, -errno otherwise. | ||||||
|  |  * | ||||||
|  |  * This must be called *after* nfs_client_init_is_complete() returns true, | ||||||
|  |  * otherwise it will pop WARN_ON_ONCE and return -EINVAL | ||||||
|  |  */ | ||||||
|  | int nfs_client_init_status(const struct nfs_client *clp) | ||||||
|  | { | ||||||
|  | 	/* called without checking nfs_client_init_is_complete */ | ||||||
|  | 	if (clp->cl_cons_state > NFS_CS_READY) { | ||||||
|  | 		WARN_ON_ONCE(1); | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | 	return clp->cl_cons_state; | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL_GPL(nfs_client_init_status); | ||||||
| 
 | 
 | ||||||
| int nfs_wait_client_init_complete(const struct nfs_client *clp) | int nfs_wait_client_init_complete(const struct nfs_client *clp) | ||||||
| { | { | ||||||
|  | |||||||
| @ -266,6 +266,7 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx) | |||||||
| 	struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg); | 	struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg); | ||||||
| 	struct nfs4_pnfs_ds *ret = ds; | 	struct nfs4_pnfs_ds *ret = ds; | ||||||
| 	struct nfs_server *s = NFS_SERVER(lseg->pls_layout->plh_inode); | 	struct nfs_server *s = NFS_SERVER(lseg->pls_layout->plh_inode); | ||||||
|  | 	int status; | ||||||
| 
 | 
 | ||||||
| 	if (ds == NULL) { | 	if (ds == NULL) { | ||||||
| 		printk(KERN_ERR "NFS: %s: No data server for offset index %d\n", | 		printk(KERN_ERR "NFS: %s: No data server for offset index %d\n", | ||||||
| @ -277,9 +278,13 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx) | |||||||
| 	if (ds->ds_clp) | 	if (ds->ds_clp) | ||||||
| 		goto out_test_devid; | 		goto out_test_devid; | ||||||
| 
 | 
 | ||||||
| 	nfs4_pnfs_ds_connect(s, ds, devid, dataserver_timeo, | 	status = nfs4_pnfs_ds_connect(s, ds, devid, dataserver_timeo, | ||||||
| 			     dataserver_retrans, 4, | 			     dataserver_retrans, 4, | ||||||
| 			     s->nfs_client->cl_minorversion); | 			     s->nfs_client->cl_minorversion); | ||||||
|  | 	if (status) { | ||||||
|  | 		ret = NULL; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| out_test_devid: | out_test_devid: | ||||||
| 	if (ret->ds_clp == NULL || | 	if (ret->ds_clp == NULL || | ||||||
|  | |||||||
| @ -384,6 +384,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx, | |||||||
| 	struct inode *ino = lseg->pls_layout->plh_inode; | 	struct inode *ino = lseg->pls_layout->plh_inode; | ||||||
| 	struct nfs_server *s = NFS_SERVER(ino); | 	struct nfs_server *s = NFS_SERVER(ino); | ||||||
| 	unsigned int max_payload; | 	unsigned int max_payload; | ||||||
|  | 	int status; | ||||||
| 
 | 
 | ||||||
| 	if (!ff_layout_mirror_valid(lseg, mirror, true)) { | 	if (!ff_layout_mirror_valid(lseg, mirror, true)) { | ||||||
| 		pr_err_ratelimited("NFS: %s: No data server for offset index %d\n", | 		pr_err_ratelimited("NFS: %s: No data server for offset index %d\n", | ||||||
| @ -404,7 +405,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx, | |||||||
| 	/* FIXME: For now we assume the server sent only one version of NFS
 | 	/* FIXME: For now we assume the server sent only one version of NFS
 | ||||||
| 	 * to use for the DS. | 	 * to use for the DS. | ||||||
| 	 */ | 	 */ | ||||||
| 	nfs4_pnfs_ds_connect(s, ds, devid, dataserver_timeo, | 	status = nfs4_pnfs_ds_connect(s, ds, devid, dataserver_timeo, | ||||||
| 			     dataserver_retrans, | 			     dataserver_retrans, | ||||||
| 			     mirror->mirror_ds->ds_versions[0].version, | 			     mirror->mirror_ds->ds_versions[0].version, | ||||||
| 			     mirror->mirror_ds->ds_versions[0].minor_version); | 			     mirror->mirror_ds->ds_versions[0].minor_version); | ||||||
|  | |||||||
| @ -186,6 +186,8 @@ extern struct nfs_server *nfs_clone_server(struct nfs_server *, | |||||||
| 					   struct nfs_fh *, | 					   struct nfs_fh *, | ||||||
| 					   struct nfs_fattr *, | 					   struct nfs_fattr *, | ||||||
| 					   rpc_authflavor_t); | 					   rpc_authflavor_t); | ||||||
|  | extern bool nfs_client_init_is_complete(const struct nfs_client *clp); | ||||||
|  | extern int nfs_client_init_status(const struct nfs_client *clp); | ||||||
| extern int nfs_wait_client_init_complete(const struct nfs_client *clp); | extern int nfs_wait_client_init_complete(const struct nfs_client *clp); | ||||||
| extern void nfs_mark_client_ready(struct nfs_client *clp, int state); | extern void nfs_mark_client_ready(struct nfs_client *clp, int state); | ||||||
| extern struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv, | extern struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv, | ||||||
|  | |||||||
| @ -367,7 +367,7 @@ void nfs4_pnfs_ds_put(struct nfs4_pnfs_ds *ds); | |||||||
| struct nfs4_pnfs_ds *nfs4_pnfs_ds_add(struct list_head *dsaddrs, | struct nfs4_pnfs_ds *nfs4_pnfs_ds_add(struct list_head *dsaddrs, | ||||||
| 				      gfp_t gfp_flags); | 				      gfp_t gfp_flags); | ||||||
| void nfs4_pnfs_v3_ds_connect_unload(void); | void nfs4_pnfs_v3_ds_connect_unload(void); | ||||||
| void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds, | int nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds, | ||||||
| 			  struct nfs4_deviceid_node *devid, unsigned int timeo, | 			  struct nfs4_deviceid_node *devid, unsigned int timeo, | ||||||
| 			  unsigned int retrans, u32 version, u32 minor_version); | 			  unsigned int retrans, u32 version, u32 minor_version); | ||||||
| struct nfs4_pnfs_ds_addr *nfs4_decode_mp_ds_addr(struct net *net, | struct nfs4_pnfs_ds_addr *nfs4_decode_mp_ds_addr(struct net *net, | ||||||
|  | |||||||
| @ -745,9 +745,9 @@ out: | |||||||
| /*
 | /*
 | ||||||
|  * Create an rpc connection to the nfs4_pnfs_ds data server. |  * Create an rpc connection to the nfs4_pnfs_ds data server. | ||||||
|  * Currently only supports IPv4 and IPv6 addresses. |  * Currently only supports IPv4 and IPv6 addresses. | ||||||
|  * If connection fails, make devid unavailable. |  * If connection fails, make devid unavailable and return a -errno. | ||||||
|  */ |  */ | ||||||
| void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds, | int nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds, | ||||||
| 			  struct nfs4_deviceid_node *devid, unsigned int timeo, | 			  struct nfs4_deviceid_node *devid, unsigned int timeo, | ||||||
| 			  unsigned int retrans, u32 version, u32 minor_version) | 			  unsigned int retrans, u32 version, u32 minor_version) | ||||||
| { | { | ||||||
| @ -772,6 +772,17 @@ void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds, | |||||||
| 	} else { | 	} else { | ||||||
| 		nfs4_wait_ds_connect(ds); | 		nfs4_wait_ds_connect(ds); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * At this point the ds->ds_clp should be ready, but it might have | ||||||
|  | 	 * hit an error. | ||||||
|  | 	 */ | ||||||
|  | 	if (!ds->ds_clp || !nfs_client_init_is_complete(ds->ds_clp)) { | ||||||
|  | 		WARN_ON_ONCE(1); | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nfs_client_init_status(ds->ds_clp); | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(nfs4_pnfs_ds_connect); | EXPORT_SYMBOL_GPL(nfs4_pnfs_ds_connect); | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user