]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - fs/nfs/client.c
NFS: Convert v3 into a module
[mirror_ubuntu-bionic-kernel.git] / fs / nfs / client.c
index f005b5bebdc73bba4d548d134699dd4f00c471ca..8687b6b6edc160d69725d5f24dd198526c3f184b 100644 (file)
 #include "internal.h"
 #include "fscache.h"
 #include "pnfs.h"
+#include "nfs.h"
 #include "netns.h"
 
 #define NFSDBG_FACILITY                NFSDBG_CLIENT
 
 static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
-#ifdef CONFIG_NFS_V4
-
-/*
- * Get a unique NFSv4.0 callback identifier which will be used
- * by the V4.0 callback service to lookup the nfs_client struct
- */
-static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
-{
-       int ret = 0;
-       struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
-
-       if (clp->rpc_ops->version != 4 || minorversion != 0)
-               return ret;
-retry:
-       if (!idr_pre_get(&nn->cb_ident_idr, GFP_KERNEL))
-               return -ENOMEM;
-       spin_lock(&nn->nfs_client_lock);
-       ret = idr_get_new(&nn->cb_ident_idr, clp, &clp->cl_cb_ident);
-       spin_unlock(&nn->nfs_client_lock);
-       if (ret == -EAGAIN)
-               goto retry;
-       return ret;
-}
-#endif /* CONFIG_NFS_V4 */
-
-/*
- * Turn off NFSv4 uid/gid mapping when using AUTH_SYS
- */
-static bool nfs4_disable_idmapping = true;
+static DEFINE_SPINLOCK(nfs_version_lock);
+static DEFINE_MUTEX(nfs_version_mutex);
+static LIST_HEAD(nfs_versions);
 
 /*
  * RPC cruft for NFS
  */
 static const struct rpc_version *nfs_version[5] = {
-#ifdef CONFIG_NFS_V2
-       [2]                     = &nfs_version2,
-#endif
-#ifdef CONFIG_NFS_V3
-       [3]                     = &nfs_version3,
-#endif
-#ifdef CONFIG_NFS_V4
-       [4]                     = &nfs_version4,
-#endif
+       [2] = NULL,
+       [3] = NULL,
+       [4] = NULL,
 };
 
 const struct rpc_program nfs_program = {
@@ -114,32 +83,82 @@ struct rpc_stat nfs_rpcstat = {
        .program                = &nfs_program
 };
 
+static struct nfs_subversion *find_nfs_version(unsigned int version)
+{
+       struct nfs_subversion *nfs;
+       spin_lock(&nfs_version_lock);
 
-#ifdef CONFIG_NFS_V3_ACL
-static struct rpc_stat         nfsacl_rpcstat = { &nfsacl_program };
-static const struct rpc_version *nfsacl_version[] = {
-       [3]                     = &nfsacl_version3,
-};
+       list_for_each_entry(nfs, &nfs_versions, list) {
+               if (nfs->rpc_ops->version == version) {
+                       spin_unlock(&nfs_version_lock);
+                       return nfs;
+               }
+       };
 
-const struct rpc_program nfsacl_program = {
-       .name                   = "nfsacl",
-       .number                 = NFS_ACL_PROGRAM,
-       .nrvers                 = ARRAY_SIZE(nfsacl_version),
-       .version                = nfsacl_version,
-       .stats                  = &nfsacl_rpcstat,
-};
-#endif  /* CONFIG_NFS_V3_ACL */
-
-struct nfs_client_initdata {
-       unsigned long init_flags;
-       const char *hostname;
-       const struct sockaddr *addr;
-       size_t addrlen;
-       const struct nfs_rpc_ops *rpc_ops;
-       int proto;
-       u32 minorversion;
-       struct net *net;
-};
+       spin_unlock(&nfs_version_lock);
+       return ERR_PTR(-EPROTONOSUPPORT);;
+}
+
+struct nfs_subversion *get_nfs_version(unsigned int version)
+{
+       struct nfs_subversion *nfs = find_nfs_version(version);
+
+       if (IS_ERR(nfs)) {
+               mutex_lock(&nfs_version_mutex);
+               request_module("nfs%d", version);
+               nfs = find_nfs_version(version);
+               mutex_unlock(&nfs_version_mutex);
+       }
+
+       if (!IS_ERR(nfs))
+               try_module_get(nfs->owner);
+       return nfs;
+}
+
+void put_nfs_version(struct nfs_subversion *nfs)
+{
+       module_put(nfs->owner);
+}
+
+void register_nfs_version(struct nfs_subversion *nfs)
+{
+       spin_lock(&nfs_version_lock);
+
+       list_add(&nfs->list, &nfs_versions);
+       nfs_version[nfs->rpc_ops->version] = nfs->rpc_vers;
+
+       spin_unlock(&nfs_version_lock);
+}
+EXPORT_SYMBOL_GPL(register_nfs_version);
+
+void unregister_nfs_version(struct nfs_subversion *nfs)
+{
+       spin_lock(&nfs_version_lock);
+
+       nfs_version[nfs->rpc_ops->version] = NULL;
+       list_del(&nfs->list);
+
+       spin_unlock(&nfs_version_lock);
+}
+EXPORT_SYMBOL_GPL(unregister_nfs_version);
+
+/*
+ * Preload all configured NFS versions during module init.
+ * This function should be edited after each protocol is converted,
+ * and eventually removed.
+ */
+int __init nfs_register_versions(void)
+{
+       return init_nfs_v4();
+}
+
+/*
+ * Remove each pre-loaded NFS version
+ */
+void nfs_unregister_versions(void)
+{
+       exit_nfs_v4();
+}
 
 /*
  * Allocate a shared client record
@@ -147,7 +166,7 @@ struct nfs_client_initdata {
  * Since these are allocated/deallocated very rarely, we don't
  * bother putting them in a slab cache...
  */
-static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
+struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
 {
        struct nfs_client *clp;
        struct rpc_cred *cred;
@@ -156,7 +175,10 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
        if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
                goto error_0;
 
-       clp->rpc_ops = cl_init->rpc_ops;
+       clp->cl_nfs_mod = cl_init->nfs_mod;
+       try_module_get(clp->cl_nfs_mod->owner);
+
+       clp->rpc_ops = clp->cl_nfs_mod->rpc_ops;
 
        atomic_set(&clp->cl_count, 1);
        clp->cl_cons_state = NFS_CS_INITING;
@@ -177,18 +199,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
        clp->cl_proto = cl_init->proto;
        clp->cl_net = get_net(cl_init->net);
 
-#ifdef CONFIG_NFS_V4
-       err = nfs_get_cb_ident_idr(clp, cl_init->minorversion);
-       if (err)
-               goto error_cleanup;
-
-       spin_lock_init(&clp->cl_lock);
-       INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
-       rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
-       clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
-       clp->cl_minorversion = cl_init->minorversion;
-       clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion];
-#endif
        cred = rpc_lookup_machine_cred("*");
        if (!IS_ERR(cred))
                clp->cl_machine_cred = cred;
@@ -197,51 +207,14 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
        return clp;
 
 error_cleanup:
+       put_nfs_version(clp->cl_nfs_mod);
        kfree(clp);
 error_0:
        return ERR_PTR(err);
 }
+EXPORT_SYMBOL_GPL(nfs_alloc_client);
 
 #ifdef CONFIG_NFS_V4
-#ifdef CONFIG_NFS_V4_1
-static void nfs4_shutdown_session(struct nfs_client *clp)
-{
-       if (nfs4_has_session(clp)) {
-               nfs4_destroy_session(clp->cl_session);
-               nfs4_destroy_clientid(clp);
-       }
-
-}
-#else /* CONFIG_NFS_V4_1 */
-static void nfs4_shutdown_session(struct nfs_client *clp)
-{
-}
-#endif /* CONFIG_NFS_V4_1 */
-
-/*
- * Destroy the NFS4 callback service
- */
-static void nfs4_destroy_callback(struct nfs_client *clp)
-{
-       if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
-               nfs_callback_down(clp->cl_mvops->minor_version);
-}
-
-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);
-       nfs4_destroy_callback(clp);
-       if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
-               nfs_idmap_delete(clp);
-
-       rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
-       kfree(clp->cl_serverowner);
-       kfree(clp->cl_serverscope);
-       kfree(clp->cl_implid);
-}
-
 /* idr_remove_all is not needed as all id's are removed by nfs_put_client */
 void nfs_cleanup_cb_ident_idr(struct net *net)
 {
@@ -264,16 +237,7 @@ static void pnfs_init_server(struct nfs_server *server)
        rpc_init_wait_queue(&server->roc_rpcwaitq, "pNFS ROC");
 }
 
-static void nfs4_destroy_server(struct nfs_server *server)
-{
-       nfs4_purge_state_owners(server);
-}
-
 #else
-static void nfs4_shutdown_client(struct nfs_client *clp)
-{
-}
-
 void nfs_cleanup_cb_ident_idr(struct net *net)
 {
 }
@@ -291,12 +255,10 @@ static void pnfs_init_server(struct nfs_server *server)
 /*
  * Destroy a shared client record
  */
-static void nfs_free_client(struct nfs_client *clp)
+void nfs_free_client(struct nfs_client *clp)
 {
        dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version);
 
-       nfs4_shutdown_client(clp);
-
        nfs_fscache_release_client_cookie(clp);
 
        /* -EIO all pending I/O */
@@ -307,11 +269,13 @@ static void nfs_free_client(struct nfs_client *clp)
                put_rpccred(clp->cl_machine_cred);
 
        put_net(clp->cl_net);
+       put_nfs_version(clp->cl_nfs_mod);
        kfree(clp->cl_hostname);
        kfree(clp);
 
        dprintk("<-- nfs_free_client()\n");
 }
+EXPORT_SYMBOL_GPL(nfs_free_client);
 
 /*
  * Release a reference to a shared client record
@@ -333,7 +297,7 @@ void nfs_put_client(struct nfs_client *clp)
 
                BUG_ON(!list_empty(&clp->cl_superblocks));
 
-               nfs_free_client(clp);
+               clp->rpc_ops->free_client(clp);
        }
 }
 EXPORT_SYMBOL_GPL(nfs_put_client);
@@ -412,8 +376,8 @@ static int nfs_sockaddr_cmp_ip4(const struct sockaddr *sa1,
  * Test if two socket addresses represent the same actual socket,
  * by comparing (only) relevant fields, excluding the port number.
  */
-static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
-                                    const struct sockaddr *sa2)
+int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
+                             const struct sockaddr *sa2)
 {
        if (sa1->sa_family != sa2->sa_family)
                return 0;
@@ -447,33 +411,6 @@ static int nfs_sockaddr_cmp(const struct sockaddr *sa1,
        return 0;
 }
 
-#if defined(CONFIG_NFS_V4_1)
-/* Common match routine for v4.0 and v4.1 callback services */
-static bool nfs4_cb_match_client(const struct sockaddr *addr,
-               struct nfs_client *clp, u32 minorversion)
-{
-       struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
-
-       /* Don't match clients that failed to initialise */
-       if (!(clp->cl_cons_state == NFS_CS_READY ||
-           clp->cl_cons_state == NFS_CS_SESSION_INITING))
-               return false;
-
-       smp_rmb();
-
-       /* Match the version and minorversion */
-       if (clp->rpc_ops->version != 4 ||
-           clp->cl_minorversion != minorversion)
-               return false;
-
-       /* Match only the IP address, not the port number */
-       if (!nfs_sockaddr_match_ipaddr(addr, clap))
-               return false;
-
-       return true;
-}
-#endif /* CONFIG_NFS_V4_1 */
-
 /*
  * Find an nfs_client on the list that matches the initialisation data
  * that is supplied.
@@ -491,7 +428,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
                        continue;
 
                /* Different NFS versions cannot share the same nfs_client */
-               if (clp->rpc_ops != data->rpc_ops)
+               if (clp->rpc_ops != data->nfs_mod->rpc_ops)
                        continue;
 
                if (clp->cl_proto != data->proto)
@@ -552,7 +489,7 @@ nfs_found_client(const struct nfs_client_initdata *cl_init,
  * Look up a client by IP address and protocol version
  * - creates a new record if one doesn't yet exist
  */
-static struct nfs_client *
+struct nfs_client *
 nfs_get_client(const struct nfs_client_initdata *cl_init,
               const struct rpc_timeout *timeparms,
               const char *ip_addr,
@@ -560,9 +497,10 @@ nfs_get_client(const struct nfs_client_initdata *cl_init,
 {
        struct nfs_client *clp, *new = NULL;
        struct nfs_net *nn = net_generic(cl_init->net, nfs_net_id);
+       const struct nfs_rpc_ops *rpc_ops = cl_init->nfs_mod->rpc_ops;
 
        dprintk("--> nfs_get_client(%s,v%u)\n",
-               cl_init->hostname ?: "", cl_init->rpc_ops->version);
+               cl_init->hostname ?: "", rpc_ops->version);
 
        /* see if the client already exists */
        do {
@@ -572,21 +510,20 @@ nfs_get_client(const struct nfs_client_initdata *cl_init,
                if (clp) {
                        spin_unlock(&nn->nfs_client_lock);
                        if (new)
-                               nfs_free_client(new);
+                               new->rpc_ops->free_client(new);
                        return nfs_found_client(cl_init, clp);
                }
                if (new) {
                        list_add(&new->cl_share_link, &nn->nfs_client_list);
                        spin_unlock(&nn->nfs_client_lock);
                        new->cl_flags = cl_init->init_flags;
-                       return cl_init->rpc_ops->init_client(new,
-                                               timeparms, ip_addr,
-                                               authflavour);
+                       return rpc_ops->init_client(new, timeparms, ip_addr,
+                                                   authflavour);
                }
 
                spin_unlock(&nn->nfs_client_lock);
 
-               new = nfs_alloc_client(cl_init);
+               new = rpc_ops->alloc_client(cl_init);
        } while (!IS_ERR(new));
 
        dprintk("<-- nfs_get_client() Failed to find %s (%ld)\n",
@@ -607,7 +544,7 @@ void nfs_mark_client_ready(struct nfs_client *clp, int state)
 /*
  * Initialise the timeout values for a connection
  */
-static void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
+void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
                                    unsigned int timeo, unsigned int retrans)
 {
        to->to_initval = timeo * HZ / 10;
@@ -648,9 +585,9 @@ static void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
 /*
  * Create an RPC client handle
  */
-static int nfs_create_rpc_client(struct nfs_client *clp,
-                                const struct rpc_timeout *timeparms,
-                                rpc_authflavor_t flavor)
+int nfs_create_rpc_client(struct nfs_client *clp,
+                         const struct rpc_timeout *timeparms,
+                         rpc_authflavor_t flavor)
 {
        struct rpc_clnt         *clnt = NULL;
        struct rpc_create_args args = {
@@ -734,40 +671,10 @@ static int nfs_start_lockd(struct nfs_server *server)
        return 0;
 }
 
-/*
- * Initialise an NFSv3 ACL client connection
- */
-#ifdef CONFIG_NFS_V3_ACL
-static void nfs_init_server_aclclient(struct nfs_server *server)
-{
-       if (server->nfs_client->rpc_ops->version != 3)
-               goto out_noacl;
-       if (server->flags & NFS_MOUNT_NOACL)
-               goto out_noacl;
-
-       server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3);
-       if (IS_ERR(server->client_acl))
-               goto out_noacl;
-
-       /* No errors! Assume that Sun nfsacls are supported */
-       server->caps |= NFS_CAP_ACLS;
-       return;
-
-out_noacl:
-       server->caps &= ~NFS_CAP_ACLS;
-}
-#else
-static inline void nfs_init_server_aclclient(struct nfs_server *server)
-{
-       server->flags &= ~NFS_MOUNT_NOACL;
-       server->caps &= ~NFS_CAP_ACLS;
-}
-#endif
-
 /*
  * Create a general RPC client
  */
-static int nfs_init_server_rpcclient(struct nfs_server *server,
+int nfs_init_server_rpcclient(struct nfs_server *server,
                const struct rpc_timeout *timeo,
                rpc_authflavor_t pseudoflavour)
 {
@@ -838,18 +745,20 @@ error:
        dprintk("<-- nfs_init_client() = xerror %d\n", error);
        return ERR_PTR(error);
 }
+EXPORT_SYMBOL_GPL(nfs_init_client);
 
 /*
  * Create a version 2 or 3 client
  */
 static int nfs_init_server(struct nfs_server *server,
-                          const struct nfs_parsed_mount_data *data)
+                          const struct nfs_parsed_mount_data *data,
+                          struct nfs_subversion *nfs_mod)
 {
        struct nfs_client_initdata cl_init = {
                .hostname = data->nfs_server.hostname,
                .addr = (const struct sockaddr *)&data->nfs_server.address,
                .addrlen = data->nfs_server.addrlen,
-               .rpc_ops = NULL,
+               .nfs_mod = nfs_mod,
                .proto = data->nfs_server.protocol,
                .net = data->net,
        };
@@ -859,21 +768,6 @@ static int nfs_init_server(struct nfs_server *server,
 
        dprintk("--> nfs_init_server()\n");
 
-       switch (data->version) {
-#ifdef CONFIG_NFS_V2
-       case 2:
-               cl_init.rpc_ops = &nfs_v2_clientops;
-               break;
-#endif
-#ifdef CONFIG_NFS_V3
-       case 3:
-               cl_init.rpc_ops = &nfs_v3_clientops;
-               break;
-#endif
-       default:
-               return -EPROTONOSUPPORT;
-       }
-
        nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
                        data->timeo, data->retrans);
        if (data->flags & NFS_MOUNT_NORESVPORT)
@@ -927,8 +821,6 @@ static int nfs_init_server(struct nfs_server *server,
        server->mountd_protocol = data->mount_server.protocol;
 
        server->namelen  = data->namlen;
-       /* Create a client RPC handle for the NFSv3 ACL management interface */
-       nfs_init_server_aclclient(server);
        dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp);
        return 0;
 
@@ -975,7 +867,6 @@ static void nfs_server_set_fsinfo(struct nfs_server *server,
                server->wsize = NFS_MAX_FILE_IO_SIZE;
        server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
        server->pnfs_blksize = fsinfo->blksize;
-       set_pnfs_layoutdriver(server, mntfh, fsinfo->layouttype);
 
        server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL);
 
@@ -1001,7 +892,7 @@ static void nfs_server_set_fsinfo(struct nfs_server *server,
 /*
  * Probe filesystem information, including the FSID on v2/v3
  */
-static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs_fattr *fattr)
+int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs_fattr *fattr)
 {
        struct nfs_fsinfo fsinfo;
        struct nfs_client *clp = server->nfs_client;
@@ -1045,7 +936,7 @@ out_error:
 /*
  * Copy useful information when duplicating a server record
  */
-static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source)
+void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source)
 {
        target->flags = source->flags;
        target->rsize = source->rsize;
@@ -1058,7 +949,7 @@ static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_serve
        target->options = source->options;
 }
 
-static void nfs_server_insert_lists(struct nfs_server *server)
+void nfs_server_insert_lists(struct nfs_server *server)
 {
        struct nfs_client *clp = server->nfs_client;
        struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
@@ -1092,7 +983,7 @@ static void nfs_server_remove_lists(struct nfs_server *server)
 /*
  * Allocate and initialise a server record
  */
-static struct nfs_server *nfs_alloc_server(void)
+struct nfs_server *nfs_alloc_server(void)
 {
        struct nfs_server *server;
 
@@ -1138,7 +1029,6 @@ void nfs_free_server(struct nfs_server *server)
        dprintk("--> nfs_free_server()\n");
 
        nfs_server_remove_lists(server);
-       unset_pnfs_layoutdriver(server);
 
        if (server->destroy != NULL)
                server->destroy(server);
@@ -1163,8 +1053,8 @@ void nfs_free_server(struct nfs_server *server)
  * Create a version 2 or 3 volume record
  * - keyed on server and FSID
  */
-struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
-                                    struct nfs_fh *mntfh)
+struct nfs_server *nfs_create_server(struct nfs_mount_info *mount_info,
+                                    struct nfs_subversion *nfs_mod)
 {
        struct nfs_server *server;
        struct nfs_fattr *fattr;
@@ -1180,7 +1070,7 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
                goto error;
 
        /* Get a client representation */
-       error = nfs_init_server(server, data);
+       error = nfs_init_server(server, mount_info->parsed, nfs_mod);
        if (error < 0)
                goto error;
 
@@ -1189,13 +1079,13 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
        BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
 
        /* Probe the root fh to retrieve its FSID */
-       error = nfs_probe_fsinfo(server, mntfh, fattr);
+       error = nfs_probe_fsinfo(server, mount_info->mntfh, fattr);
        if (error < 0)
                goto error;
        if (server->nfs_client->rpc_ops->version == 3) {
                if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
                        server->namelen = NFS3_MAXNAMLEN;
-               if (!(data->flags & NFS_MOUNT_NORDIRPLUS))
+               if (!(mount_info->parsed->flags & NFS_MOUNT_NORDIRPLUS))
                        server->caps |= NFS_CAP_READDIRPLUS;
        } else {
                if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)
@@ -1203,7 +1093,7 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
        }
 
        if (!(fattr->valid & NFS_ATTR_FATTR)) {
-               error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr);
+               error = nfs_mod->rpc_ops->getattr(server, mount_info->mntfh, fattr);
                if (error < 0) {
                        dprintk("nfs_create_server: getattr error = %d\n", -error);
                        goto error;
@@ -1225,522 +1115,7 @@ error:
        nfs_free_server(server);
        return ERR_PTR(error);
 }
-
-#ifdef CONFIG_NFS_V4
-/*
- * NFSv4.0 callback thread helper
- *
- * Find a client by callback identifier
- */
-struct nfs_client *
-nfs4_find_client_ident(struct net *net, int cb_ident)
-{
-       struct nfs_client *clp;
-       struct nfs_net *nn = net_generic(net, nfs_net_id);
-
-       spin_lock(&nn->nfs_client_lock);
-       clp = idr_find(&nn->cb_ident_idr, cb_ident);
-       if (clp)
-               atomic_inc(&clp->cl_count);
-       spin_unlock(&nn->nfs_client_lock);
-       return clp;
-}
-
-#if defined(CONFIG_NFS_V4_1)
-/*
- * NFSv4.1 callback thread helper
- * For CB_COMPOUND calls, find a client by IP address, protocol version,
- * minorversion, and sessionID
- *
- * Returns NULL if no such client
- */
-struct nfs_client *
-nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr,
-                          struct nfs4_sessionid *sid)
-{
-       struct nfs_client *clp;
-       struct nfs_net *nn = net_generic(net, nfs_net_id);
-
-       spin_lock(&nn->nfs_client_lock);
-       list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) {
-               if (nfs4_cb_match_client(addr, clp, 1) == false)
-                       continue;
-
-               if (!nfs4_has_session(clp))
-                       continue;
-
-               /* Match sessionid*/
-               if (memcmp(clp->cl_session->sess_id.data,
-                   sid->data, NFS4_MAX_SESSIONID_LEN) != 0)
-                       continue;
-
-               atomic_inc(&clp->cl_count);
-               spin_unlock(&nn->nfs_client_lock);
-               return clp;
-       }
-       spin_unlock(&nn->nfs_client_lock);
-       return NULL;
-}
-
-#else /* CONFIG_NFS_V4_1 */
-
-struct nfs_client *
-nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr,
-                          struct nfs4_sessionid *sid)
-{
-       return NULL;
-}
-#endif /* CONFIG_NFS_V4_1 */
-
-/*
- * Initialize the NFS4 callback service
- */
-static int nfs4_init_callback(struct nfs_client *clp)
-{
-       int error;
-
-       if (clp->rpc_ops->version == 4) {
-               struct rpc_xprt *xprt;
-
-               xprt = rcu_dereference_raw(clp->cl_rpcclient->cl_xprt);
-
-               if (nfs4_has_session(clp)) {
-                       error = xprt_setup_backchannel(xprt,
-                                               NFS41_BC_MIN_CALLBACKS);
-                       if (error < 0)
-                               return error;
-               }
-
-               error = nfs_callback_up(clp->cl_mvops->minor_version, xprt);
-               if (error < 0) {
-                       dprintk("%s: failed to start callback. Error = %d\n",
-                               __func__, error);
-                       return error;
-               }
-               __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
-       }
-       return 0;
-}
-
-/*
- * 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 */
-
-       return nfs4_init_callback(clp);
-}
-
-/**
- * nfs4_init_client - Initialise an NFS4 client record
- *
- * @clp: nfs_client to initialise
- * @timeparms: timeout parameters for underlying RPC transport
- * @ip_addr: callback IP address in presentation format
- * @authflavor: authentication flavor for underlying RPC transport
- *
- * Returns pointer to an NFS client, or an ERR_PTR value.
- */
-struct nfs_client *nfs4_init_client(struct nfs_client *clp,
-                                   const struct rpc_timeout *timeparms,
-                                   const char *ip_addr,
-                                   rpc_authflavor_t authflavour)
-{
-       char buf[INET6_ADDRSTRLEN + 1];
-       int error;
-
-       if (clp->cl_cons_state == NFS_CS_READY) {
-               /* the client is initialised already */
-               dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp);
-               return clp;
-       }
-
-       /* Check NFS protocol revision and initialize RPC op vector */
-       clp->rpc_ops = &nfs_v4_clientops;
-
-       __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags);
-       error = nfs_create_rpc_client(clp, timeparms, authflavour);
-       if (error < 0)
-               goto error;
-
-       /* If no clientaddr= option was specified, find a usable cb address */
-       if (ip_addr == NULL) {
-               struct sockaddr_storage cb_addr;
-               struct sockaddr *sap = (struct sockaddr *)&cb_addr;
-
-               error = rpc_localaddr(clp->cl_rpcclient, sap, sizeof(cb_addr));
-               if (error < 0)
-                       goto error;
-               error = rpc_ntop(sap, buf, sizeof(buf));
-               if (error < 0)
-                       goto error;
-               ip_addr = (const char *)buf;
-       }
-       strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
-
-       error = nfs_idmap_new(clp);
-       if (error < 0) {
-               dprintk("%s: failed to create idmapper. Error = %d\n",
-                       __func__, error);
-               goto error;
-       }
-       __set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
-
-       error = nfs4_init_client_minor_version(clp);
-       if (error < 0)
-               goto error;
-
-       if (!nfs4_has_session(clp))
-               nfs_mark_client_ready(clp, NFS_CS_READY);
-       return clp;
-
-error:
-       nfs_mark_client_ready(clp, error);
-       nfs_put_client(clp);
-       dprintk("<-- nfs4_init_client() = xerror %d\n", error);
-       return ERR_PTR(error);
-}
-
-/*
- * Set up an NFS4 client
- */
-static int nfs4_set_client(struct nfs_server *server,
-               const char *hostname,
-               const struct sockaddr *addr,
-               const size_t addrlen,
-               const char *ip_addr,
-               rpc_authflavor_t authflavour,
-               int proto, const struct rpc_timeout *timeparms,
-               u32 minorversion, struct net *net)
-{
-       struct nfs_client_initdata cl_init = {
-               .hostname = hostname,
-               .addr = addr,
-               .addrlen = addrlen,
-               .rpc_ops = &nfs_v4_clientops,
-               .proto = proto,
-               .minorversion = minorversion,
-               .net = net,
-       };
-       struct nfs_client *clp;
-       int error;
-
-       dprintk("--> nfs4_set_client()\n");
-
-       if (server->flags & NFS_MOUNT_NORESVPORT)
-               set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
-
-       /* Allocate or find a client reference we can use */
-       clp = nfs_get_client(&cl_init, timeparms, ip_addr, authflavour);
-       if (IS_ERR(clp)) {
-               error = PTR_ERR(clp);
-               goto error;
-       }
-
-       /*
-        * Query for the lease time on clientid setup or renewal
-        *
-        * Note that this will be set on nfs_clients that were created
-        * only for the DS role and did not set this bit, but now will
-        * serve a dual role.
-        */
-       set_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state);
-
-       server->nfs_client = clp;
-       dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp);
-       return 0;
-error:
-       dprintk("<-- nfs4_set_client() = xerror %d\n", error);
-       return error;
-}
-
-/*
- * Set up a pNFS Data Server client.
- *
- * Return any existing nfs_client that matches server address,port,version
- * and minorversion.
- *
- * For a new nfs_client, use a soft mount (default), a low retrans and a
- * low timeout interval so that if a connection is lost, we retry through
- * the MDS.
- */
-struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
-               const struct sockaddr *ds_addr, int ds_addrlen,
-               int ds_proto, unsigned int ds_timeo, unsigned int ds_retrans)
-{
-       struct nfs_client_initdata cl_init = {
-               .addr = ds_addr,
-               .addrlen = ds_addrlen,
-               .rpc_ops = &nfs_v4_clientops,
-               .proto = ds_proto,
-               .minorversion = mds_clp->cl_minorversion,
-               .net = mds_clp->cl_net,
-       };
-       struct rpc_timeout ds_timeout;
-       struct nfs_client *clp;
-
-       /*
-        * Set an authflavor equual to the MDS value. Use the MDS nfs_client
-        * cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS
-        * (section 13.1 RFC 5661).
-        */
-       nfs_init_timeout_values(&ds_timeout, ds_proto, ds_timeo, ds_retrans);
-       clp = nfs_get_client(&cl_init, &ds_timeout, mds_clp->cl_ipaddr,
-                            mds_clp->cl_rpcclient->cl_auth->au_flavor);
-
-       dprintk("<-- %s %p\n", __func__, clp);
-       return clp;
-}
-EXPORT_SYMBOL_GPL(nfs4_set_ds_client);
-
-/*
- * Session has been established, and the client marked ready.
- * Set the mount rsize and wsize with negotiated fore channel
- * attributes which will be bound checked in nfs_server_set_fsinfo.
- */
-static void nfs4_session_set_rwsize(struct nfs_server *server)
-{
-#ifdef CONFIG_NFS_V4_1
-       struct nfs4_session *sess;
-       u32 server_resp_sz;
-       u32 server_rqst_sz;
-
-       if (!nfs4_has_session(server->nfs_client))
-               return;
-       sess = server->nfs_client->cl_session;
-       server_resp_sz = sess->fc_attrs.max_resp_sz - nfs41_maxread_overhead;
-       server_rqst_sz = sess->fc_attrs.max_rqst_sz - nfs41_maxwrite_overhead;
-
-       if (server->rsize > server_resp_sz)
-               server->rsize = server_resp_sz;
-       if (server->wsize > server_rqst_sz)
-               server->wsize = server_rqst_sz;
-#endif /* CONFIG_NFS_V4_1 */
-}
-
-static int nfs4_server_common_setup(struct nfs_server *server,
-               struct nfs_fh *mntfh)
-{
-       struct nfs_fattr *fattr;
-       int error;
-
-       BUG_ON(!server->nfs_client);
-       BUG_ON(!server->nfs_client->rpc_ops);
-       BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
-
-       /* data servers support only a subset of NFSv4.1 */
-       if (is_ds_only_client(server->nfs_client))
-               return -EPROTONOSUPPORT;
-
-       fattr = nfs_alloc_fattr();
-       if (fattr == NULL)
-               return -ENOMEM;
-
-       /* We must ensure the session is initialised first */
-       error = nfs4_init_session(server);
-       if (error < 0)
-               goto out;
-
-       /* Probe the root fh to retrieve its FSID and filehandle */
-       error = nfs4_get_rootfh(server, mntfh);
-       if (error < 0)
-               goto out;
-
-       dprintk("Server FSID: %llx:%llx\n",
-                       (unsigned long long) server->fsid.major,
-                       (unsigned long long) server->fsid.minor);
-       dprintk("Mount FH: %d\n", mntfh->size);
-
-       nfs4_session_set_rwsize(server);
-
-       error = nfs_probe_fsinfo(server, mntfh, fattr);
-       if (error < 0)
-               goto out;
-
-       if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
-               server->namelen = NFS4_MAXNAMLEN;
-
-       nfs_server_insert_lists(server);
-       server->mount_time = jiffies;
-       server->destroy = nfs4_destroy_server;
-out:
-       nfs_free_fattr(fattr);
-       return error;
-}
-
-/*
- * Create a version 4 volume record
- */
-static int nfs4_init_server(struct nfs_server *server,
-               const struct nfs_parsed_mount_data *data)
-{
-       struct rpc_timeout timeparms;
-       int error;
-
-       dprintk("--> nfs4_init_server()\n");
-
-       nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
-                       data->timeo, data->retrans);
-
-       /* Initialise the client representation from the mount data */
-       server->flags = data->flags;
-       server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR|NFS_CAP_POSIX_LOCK;
-       if (!(data->flags & NFS_MOUNT_NORDIRPLUS))
-                       server->caps |= NFS_CAP_READDIRPLUS;
-       server->options = data->options;
-
-       /* Get a client record */
-       error = nfs4_set_client(server,
-                       data->nfs_server.hostname,
-                       (const struct sockaddr *)&data->nfs_server.address,
-                       data->nfs_server.addrlen,
-                       data->client_address,
-                       data->auth_flavors[0],
-                       data->nfs_server.protocol,
-                       &timeparms,
-                       data->minorversion,
-                       data->net);
-       if (error < 0)
-               goto error;
-
-       /*
-        * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower
-        * authentication.
-        */
-       if (nfs4_disable_idmapping && data->auth_flavors[0] == RPC_AUTH_UNIX)
-               server->caps |= NFS_CAP_UIDGID_NOMAP;
-
-       if (data->rsize)
-               server->rsize = nfs_block_size(data->rsize, NULL);
-       if (data->wsize)
-               server->wsize = nfs_block_size(data->wsize, NULL);
-
-       server->acregmin = data->acregmin * HZ;
-       server->acregmax = data->acregmax * HZ;
-       server->acdirmin = data->acdirmin * HZ;
-       server->acdirmax = data->acdirmax * HZ;
-
-       server->port = data->nfs_server.port;
-
-       error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]);
-
-error:
-       /* Done */
-       dprintk("<-- nfs4_init_server() = %d\n", error);
-       return error;
-}
-
-/*
- * Create a version 4 volume record
- * - keyed on server and FSID
- */
-struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
-                                     struct nfs_fh *mntfh)
-{
-       struct nfs_server *server;
-       int error;
-
-       dprintk("--> nfs4_create_server()\n");
-
-       server = nfs_alloc_server();
-       if (!server)
-               return ERR_PTR(-ENOMEM);
-
-       /* set up the general RPC client */
-       error = nfs4_init_server(server, data);
-       if (error < 0)
-               goto error;
-
-       error = nfs4_server_common_setup(server, mntfh);
-       if (error < 0)
-               goto error;
-
-       dprintk("<-- nfs4_create_server() = %p\n", server);
-       return server;
-
-error:
-       nfs_free_server(server);
-       dprintk("<-- nfs4_create_server() = error %d\n", error);
-       return ERR_PTR(error);
-}
-
-/*
- * Create an NFS4 referral server record
- */
-struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
-                                              struct nfs_fh *mntfh)
-{
-       struct nfs_client *parent_client;
-       struct nfs_server *server, *parent_server;
-       int error;
-
-       dprintk("--> nfs4_create_referral_server()\n");
-
-       server = nfs_alloc_server();
-       if (!server)
-               return ERR_PTR(-ENOMEM);
-
-       parent_server = NFS_SB(data->sb);
-       parent_client = parent_server->nfs_client;
-
-       /* Initialise the client representation from the parent server */
-       nfs_server_copy_userdata(server, parent_server);
-       server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR;
-
-       /* Get a client representation.
-        * Note: NFSv4 always uses TCP, */
-       error = nfs4_set_client(server, data->hostname,
-                               data->addr,
-                               data->addrlen,
-                               parent_client->cl_ipaddr,
-                               data->authflavor,
-                               rpc_protocol(parent_server->client),
-                               parent_server->client->cl_timeout,
-                               parent_client->cl_mvops->minor_version,
-                               parent_client->cl_net);
-       if (error < 0)
-               goto error;
-
-       error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout, data->authflavor);
-       if (error < 0)
-               goto error;
-
-       error = nfs4_server_common_setup(server, mntfh);
-       if (error < 0)
-               goto error;
-
-       dprintk("<-- nfs_create_referral_server() = %p\n", server);
-       return server;
-
-error:
-       nfs_free_server(server);
-       dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
-       return ERR_PTR(error);
-}
-
-#endif /* CONFIG_NFS_V4 */
+EXPORT_SYMBOL_GPL(nfs_create_server);
 
 /*
  * Clone an NFS2, NFS3 or NFS4 server record
@@ -1780,8 +1155,6 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
                        flavor);
        if (error < 0)
                goto out_free_server;
-       if (!IS_ERR(source->client_acl))
-               nfs_init_server_aclclient(server);
 
        /* probe the filesystem info for this server filesystem */
        error = nfs_probe_fsinfo(server, fh, fattr_fsinfo);
@@ -1812,6 +1185,7 @@ out_free_server:
        dprintk("<-- nfs_clone_server() = error %d\n", error);
        return ERR_PTR(error);
 }
+EXPORT_SYMBOL_GPL(nfs_clone_server);
 
 void nfs_clients_init(struct net *net)
 {
@@ -2091,7 +1465,3 @@ void nfs_fs_proc_exit(void)
 }
 
 #endif /* CONFIG_PROC_FS */
-
-module_param(nfs4_disable_idmapping, bool, 0644);
-MODULE_PARM_DESC(nfs4_disable_idmapping,
-               "Turn off NFSv4 idmapping when using 'sec=sys'");