forked from mirrors/linux
		
	NFS: Add a slot table to struct nfs_client for NFSv4.0 transport blocking
Anchor an nfs4_slot_table in the nfs_client for use with NFSv4.0 transport blocking. It is initialized only for NFSv4.0 nfs_client's. Introduce appropriate minor version ops to handle nfs_client initialization and shutdown requirements that differ for each minor version. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
		
							parent
							
								
									eb2a1cd3c9
								
							
						
					
					
						commit
						abf79bb341
					
				
					 4 changed files with 89 additions and 27 deletions
				
			
		| 
						 | 
					@ -38,6 +38,8 @@ struct nfs4_minor_version_ops {
 | 
				
			||||||
	u32	minor_version;
 | 
						u32	minor_version;
 | 
				
			||||||
	unsigned init_caps;
 | 
						unsigned init_caps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int	(*init_client)(struct nfs_client *);
 | 
				
			||||||
 | 
						void	(*shutdown_client)(struct nfs_client *);
 | 
				
			||||||
	bool	(*match_stateid)(const nfs4_stateid *,
 | 
						bool	(*match_stateid)(const nfs4_stateid *,
 | 
				
			||||||
			const nfs4_stateid *);
 | 
								const nfs4_stateid *);
 | 
				
			||||||
	int	(*find_root_sec)(struct nfs_server *, struct nfs_fh *,
 | 
						int	(*find_root_sec)(struct nfs_server *, struct nfs_fh *,
 | 
				
			||||||
| 
						 | 
					@ -292,6 +294,10 @@ extern const u32 nfs4_pathconf_bitmap[3];
 | 
				
			||||||
extern const u32 nfs4_fsinfo_bitmap[3];
 | 
					extern const u32 nfs4_fsinfo_bitmap[3];
 | 
				
			||||||
extern const u32 nfs4_fs_locations_bitmap[3];
 | 
					extern const u32 nfs4_fs_locations_bitmap[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void nfs40_shutdown_client(struct nfs_client *);
 | 
				
			||||||
 | 
					void nfs41_shutdown_client(struct nfs_client *);
 | 
				
			||||||
 | 
					int nfs40_init_client(struct nfs_client *);
 | 
				
			||||||
 | 
					int nfs41_init_client(struct nfs_client *);
 | 
				
			||||||
void nfs4_free_client(struct nfs_client *);
 | 
					void nfs4_free_client(struct nfs_client *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *);
 | 
					struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,7 @@ static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_NFS_V4_1
 | 
					#ifdef CONFIG_NFS_V4_1
 | 
				
			||||||
static void nfs4_shutdown_session(struct nfs_client *clp)
 | 
					void nfs41_shutdown_client(struct nfs_client *clp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (nfs4_has_session(clp)) {
 | 
						if (nfs4_has_session(clp)) {
 | 
				
			||||||
		nfs4_destroy_session(clp->cl_session);
 | 
							nfs4_destroy_session(clp->cl_session);
 | 
				
			||||||
| 
						 | 
					@ -49,11 +49,15 @@ static void nfs4_shutdown_session(struct nfs_client *clp)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#else /* CONFIG_NFS_V4_1 */
 | 
					#endif	/* CONFIG_NFS_V4_1 */
 | 
				
			||||||
static void nfs4_shutdown_session(struct nfs_client *clp)
 | 
					
 | 
				
			||||||
 | 
					void nfs40_shutdown_client(struct nfs_client *clp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						if (clp->cl_slot_tbl) {
 | 
				
			||||||
 | 
							nfs4_release_slot_table(clp->cl_slot_tbl);
 | 
				
			||||||
 | 
							kfree(clp->cl_slot_tbl);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif /* CONFIG_NFS_V4_1 */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init)
 | 
					struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -97,7 +101,7 @@ static void nfs4_shutdown_client(struct nfs_client *clp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
 | 
						if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
 | 
				
			||||||
		nfs4_kill_renewd(clp);
 | 
							nfs4_kill_renewd(clp);
 | 
				
			||||||
	nfs4_shutdown_session(clp);
 | 
						clp->cl_mvops->shutdown_client(clp);
 | 
				
			||||||
	nfs4_destroy_callback(clp);
 | 
						nfs4_destroy_callback(clp);
 | 
				
			||||||
	if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
 | 
						if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
 | 
				
			||||||
		nfs_idmap_delete(clp);
 | 
							nfs_idmap_delete(clp);
 | 
				
			||||||
| 
						 | 
					@ -144,34 +148,77 @@ static int nfs4_init_callback(struct nfs_client *clp)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * nfs40_init_client - nfs_client initialization tasks for NFSv4.0
 | 
				
			||||||
 | 
					 * @clp - nfs_client to initialize
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns zero on success, or a negative errno if some error occurred.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nfs40_init_client(struct nfs_client *clp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nfs4_slot_table *tbl;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tbl = kzalloc(sizeof(*tbl), GFP_NOFS);
 | 
				
			||||||
 | 
						if (tbl == NULL)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = nfs4_setup_slot_table(tbl, NFS4_MAX_SLOT_TABLE,
 | 
				
			||||||
 | 
										"NFSv4.0 transport Slot table");
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							kfree(tbl);
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						clp->cl_slot_tbl = tbl;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(CONFIG_NFS_V4_1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * nfs41_init_client - nfs_client initialization tasks for NFSv4.1+
 | 
				
			||||||
 | 
					 * @clp - nfs_client to initialize
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns zero on success, or a negative errno if some error occurred.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int nfs41_init_client(struct nfs_client *clp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nfs4_session *session = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Create the session and mark it expired.
 | 
				
			||||||
 | 
						 * When a SEQUENCE operation encounters the expired session
 | 
				
			||||||
 | 
						 * it will do session recovery to initialize it.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						session = nfs4_alloc_session(clp);
 | 
				
			||||||
 | 
						if (!session)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						clp->cl_session = session;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * The create session reply races with the server back
 | 
				
			||||||
 | 
						 * channel probe. Mark the client NFS_CS_SESSION_INITING
 | 
				
			||||||
 | 
						 * so that the client back channel can find the
 | 
				
			||||||
 | 
						 * nfs_client struct
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						nfs_mark_client_ready(clp, NFS_CS_SESSION_INITING);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif	/* CONFIG_NFS_V4_1 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Initialize the minor version specific parts of an NFS4 client record
 | 
					 * Initialize the minor version specific parts of an NFS4 client record
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int nfs4_init_client_minor_version(struct nfs_client *clp)
 | 
					static int nfs4_init_client_minor_version(struct nfs_client *clp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#if defined(CONFIG_NFS_V4_1)
 | 
						int ret;
 | 
				
			||||||
	if (clp->cl_mvops->minor_version) {
 | 
					 | 
				
			||||||
		struct nfs4_session *session = NULL;
 | 
					 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * Create the session and mark it expired.
 | 
					 | 
				
			||||||
		 * When a SEQUENCE operation encounters the expired session
 | 
					 | 
				
			||||||
		 * it will do session recovery to initialize it.
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		session = nfs4_alloc_session(clp);
 | 
					 | 
				
			||||||
		if (!session)
 | 
					 | 
				
			||||||
			return -ENOMEM;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		clp->cl_session = session;
 | 
					 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * The create session reply races with the server back
 | 
					 | 
				
			||||||
		 * channel probe. Mark the client NFS_CS_SESSION_INITING
 | 
					 | 
				
			||||||
		 * so that the client back channel can find the
 | 
					 | 
				
			||||||
		 * nfs_client struct
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		nfs_mark_client_ready(clp, NFS_CS_SESSION_INITING);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
#endif /* CONFIG_NFS_V4_1 */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = clp->cl_mvops->init_client(clp);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
	return nfs4_init_callback(clp);
 | 
						return nfs4_init_callback(clp);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7533,6 +7533,8 @@ static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = {
 | 
				
			||||||
		| NFS_CAP_ATOMIC_OPEN
 | 
							| NFS_CAP_ATOMIC_OPEN
 | 
				
			||||||
		| NFS_CAP_CHANGE_ATTR
 | 
							| NFS_CAP_CHANGE_ATTR
 | 
				
			||||||
		| NFS_CAP_POSIX_LOCK,
 | 
							| NFS_CAP_POSIX_LOCK,
 | 
				
			||||||
 | 
						.init_client = nfs40_init_client,
 | 
				
			||||||
 | 
						.shutdown_client = nfs40_shutdown_client,
 | 
				
			||||||
	.match_stateid = nfs4_match_stateid,
 | 
						.match_stateid = nfs4_match_stateid,
 | 
				
			||||||
	.find_root_sec = nfs4_find_root_sec,
 | 
						.find_root_sec = nfs4_find_root_sec,
 | 
				
			||||||
	.free_lock_state = nfs4_release_lockowner,
 | 
						.free_lock_state = nfs4_release_lockowner,
 | 
				
			||||||
| 
						 | 
					@ -7551,6 +7553,8 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = {
 | 
				
			||||||
		| NFS_CAP_POSIX_LOCK
 | 
							| NFS_CAP_POSIX_LOCK
 | 
				
			||||||
		| NFS_CAP_STATEID_NFSV41
 | 
							| NFS_CAP_STATEID_NFSV41
 | 
				
			||||||
		| NFS_CAP_ATOMIC_OPEN_V1,
 | 
							| NFS_CAP_ATOMIC_OPEN_V1,
 | 
				
			||||||
 | 
						.init_client = nfs41_init_client,
 | 
				
			||||||
 | 
						.shutdown_client = nfs41_shutdown_client,
 | 
				
			||||||
	.match_stateid = nfs41_match_stateid,
 | 
						.match_stateid = nfs41_match_stateid,
 | 
				
			||||||
	.find_root_sec = nfs41_find_root_sec,
 | 
						.find_root_sec = nfs41_find_root_sec,
 | 
				
			||||||
	.free_lock_state = nfs41_free_lock_state,
 | 
						.free_lock_state = nfs41_free_lock_state,
 | 
				
			||||||
| 
						 | 
					@ -7570,6 +7574,8 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = {
 | 
				
			||||||
		| NFS_CAP_POSIX_LOCK
 | 
							| NFS_CAP_POSIX_LOCK
 | 
				
			||||||
		| NFS_CAP_STATEID_NFSV41
 | 
							| NFS_CAP_STATEID_NFSV41
 | 
				
			||||||
		| NFS_CAP_ATOMIC_OPEN_V1,
 | 
							| NFS_CAP_ATOMIC_OPEN_V1,
 | 
				
			||||||
 | 
						.init_client = nfs41_init_client,
 | 
				
			||||||
 | 
						.shutdown_client = nfs41_shutdown_client,
 | 
				
			||||||
	.match_stateid = nfs41_match_stateid,
 | 
						.match_stateid = nfs41_match_stateid,
 | 
				
			||||||
	.find_root_sec = nfs41_find_root_sec,
 | 
						.find_root_sec = nfs41_find_root_sec,
 | 
				
			||||||
	.free_lock_state = nfs41_free_lock_state,
 | 
						.free_lock_state = nfs41_free_lock_state,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -78,6 +78,9 @@ struct nfs_client {
 | 
				
			||||||
	u32			cl_cb_ident;	/* v4.0 callback identifier */
 | 
						u32			cl_cb_ident;	/* v4.0 callback identifier */
 | 
				
			||||||
	const struct nfs4_minor_version_ops *cl_mvops;
 | 
						const struct nfs4_minor_version_ops *cl_mvops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* NFSv4.0 transport blocking */
 | 
				
			||||||
 | 
						struct nfs4_slot_table	*cl_slot_tbl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* The sequence id to use for the next CREATE_SESSION */
 | 
						/* The sequence id to use for the next CREATE_SESSION */
 | 
				
			||||||
	u32			cl_seqid;
 | 
						u32			cl_seqid;
 | 
				
			||||||
	/* The flags used for obtaining the clientid during EXCHANGE_ID */
 | 
						/* The flags used for obtaining the clientid during EXCHANGE_ID */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue