NFS: Add a slot table to struct nfs_client for NFSv4.0 transport blocking
authorChuck Lever <chuck.lever@oracle.com>
Fri, 9 Aug 2013 16:49:11 +0000 (12:49 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 3 Sep 2013 19:26:35 +0000 (15:26 -0400)
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>
fs/nfs/nfs4_fs.h
fs/nfs/nfs4client.c
fs/nfs/nfs4proc.c
include/linux/nfs_fs_sb.h

index 8de9b934dcac7e2d74d7653c1c1b4d56e78bcc99..af2d5bf043f0d75ca489cf85dc7a6c5261f8ed01 100644 (file)
@@ -38,6 +38,8 @@ struct nfs4_minor_version_ops {
        u32     minor_version;
        unsigned init_caps;
 
+       int     (*init_client)(struct nfs_client *);
+       void    (*shutdown_client)(struct nfs_client *);
        bool    (*match_stateid)(const nfs4_stateid *,
                        const nfs4_stateid *);
        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_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 *);
 
 struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *);
index 767a5e37fe9731673a81ae284123979b4b72134d..98c0104bb0c4d93f3bcf0501b5d3705c2d406cef 100644 (file)
@@ -41,7 +41,7 @@ static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
 }
 
 #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)) {
                nfs4_destroy_session(clp->cl_session);
@@ -49,11 +49,15 @@ static void nfs4_shutdown_session(struct nfs_client *clp)
        }
 
 }
-#else /* CONFIG_NFS_V4_1 */
-static void nfs4_shutdown_session(struct nfs_client *clp)
+#endif /* CONFIG_NFS_V4_1 */
+
+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)
 {
@@ -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))
                nfs4_kill_renewd(clp);
-       nfs4_shutdown_session(clp);
+       clp->cl_mvops->shutdown_client(clp);
        nfs4_destroy_callback(clp);
        if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
                nfs_idmap_delete(clp);
@@ -144,34 +148,77 @@ static int nfs4_init_callback(struct nfs_client *clp)
        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
  */
 static int nfs4_init_client_minor_version(struct nfs_client *clp)
 {
-#if defined(CONFIG_NFS_V4_1)
-       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 */
+       int ret;
 
+       ret = clp->cl_mvops->init_client(clp);
+       if (ret)
+               return ret;
        return nfs4_init_callback(clp);
 }
 
index 3abd32caec2f56903e8831cae4b14e1d478377cf..3b5166c20962cb0e91d71d3d97231900bd5ef786 100644 (file)
@@ -7533,6 +7533,8 @@ static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = {
                | NFS_CAP_ATOMIC_OPEN
                | NFS_CAP_CHANGE_ATTR
                | NFS_CAP_POSIX_LOCK,
+       .init_client = nfs40_init_client,
+       .shutdown_client = nfs40_shutdown_client,
        .match_stateid = nfs4_match_stateid,
        .find_root_sec = nfs4_find_root_sec,
        .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_STATEID_NFSV41
                | NFS_CAP_ATOMIC_OPEN_V1,
+       .init_client = nfs41_init_client,
+       .shutdown_client = nfs41_shutdown_client,
        .match_stateid = nfs41_match_stateid,
        .find_root_sec = nfs41_find_root_sec,
        .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_STATEID_NFSV41
                | NFS_CAP_ATOMIC_OPEN_V1,
+       .init_client = nfs41_init_client,
+       .shutdown_client = nfs41_shutdown_client,
        .match_stateid = nfs41_match_stateid,
        .find_root_sec = nfs41_find_root_sec,
        .free_lock_state = nfs41_free_lock_state,
index d2212432c456a3fb2b1cbe33311d6e789d518173..fc83d3d384d06585b52b0b378647ab7e44f49c77 100644 (file)
@@ -78,6 +78,9 @@ struct nfs_client {
        u32                     cl_cb_ident;    /* v4.0 callback identifier */
        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 */
        u32                     cl_seqid;
        /* The flags used for obtaining the clientid during EXCHANGE_ID */