]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge tag 'nfs-for-3.6-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 1 Aug 2012 01:45:44 +0000 (18:45 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 1 Aug 2012 01:45:44 +0000 (18:45 -0700)
Pull second wave of NFS client updates from Trond Myklebust:

 - Patches from Bryan to allow splitting of the NFSv2/v3/v4 code into
   separate modules.

 - Fix Oopses in the NFSv4 idmapper

 - Fix a deadlock whereby rpciod tries to allocate a new socket and ends
   up recursing into the NFS code due to memory reclaim.

 - Increase the number of permitted callback connections.

* tag 'nfs-for-3.6-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  nfs: explicitly reject LOCK_MAND flock() requests
  nfs: increase number of permitted callback connections.
  SUNRPC: return negative value in case rpcbind client creation error
  NFS: Convert v4 into a module
  NFS: Convert v3 into a module
  NFS: Convert v2 into a module
  NFS: Keep module parameters in the generic NFS client
  NFS: Split out remaining NFS v4 inode functions
  NFS: Pass super operations and xattr handlers in the nfs_subversion
  NFS: Only initialize the ACL client in the v3 case
  NFS: Create a try_mount rpc op
  NFS: Remove the NFS v4 xdev mount function
  NFS: Add version registering framework
  NFS: Fix a number of bugs in the idmapper
  nfs: skip commit in releasepage if we're freeing memory for fs-related reasons
  sunrpc: clarify comments on rpc_make_runnable
  pnfsblock: bail out partial page IO

40 files changed:
fs/nfs/Kconfig
fs/nfs/Makefile
fs/nfs/blocklayout/blocklayout.c
fs/nfs/callback.c
fs/nfs/callback.h
fs/nfs/client.c
fs/nfs/delegation.h
fs/nfs/dir.c
fs/nfs/direct.c
fs/nfs/dns_resolve.c
fs/nfs/file.c
fs/nfs/idmap.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/namespace.c
fs/nfs/netns.h
fs/nfs/nfs.h [new file with mode: 0644]
fs/nfs/nfs2super.c [new file with mode: 0644]
fs/nfs/nfs3client.c [new file with mode: 0644]
fs/nfs/nfs3proc.c
fs/nfs/nfs3super.c [new file with mode: 0644]
fs/nfs/nfs4_fs.h
fs/nfs/nfs4client.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4super.c
fs/nfs/nfs4xdr.c
fs/nfs/pagelist.c
fs/nfs/pnfs.c
fs/nfs/proc.c
fs/nfs/read.c
fs/nfs/super.c
fs/nfs/write.c
include/linux/nfs_fs.h
include/linux/nfs_fs_sb.h
include/linux/nfs_idmap.h
include/linux/nfs_xdr.h
net/sunrpc/rpcb_clnt.c
net/sunrpc/sched.c
net/sunrpc/xprtrdma/transport.c
net/sunrpc/xprtsock.c

index 404c6a8ac394423da4079aa965fd987e80a0e0cc..195c1ea6151ada1e372c063878d358b4cb4dcd9f 100644 (file)
@@ -30,7 +30,7 @@ config NFS_FS
          If unsure, say N.
 
 config NFS_V2
-       bool "NFS client support for NFS version 2"
+       tristate "NFS client support for NFS version 2"
        depends on NFS_FS
        default y
        help
@@ -40,7 +40,7 @@ config NFS_V2
          If unsure, say Y.
 
 config NFS_V3
-       bool "NFS client support for NFS version 3"
+       tristate "NFS client support for NFS version 3"
        depends on NFS_FS
        default y
        help
@@ -72,7 +72,7 @@ config NFS_V3_ACL
          If unsure, say N.
 
 config NFS_V4
-       bool "NFS client support for NFS version 4"
+       tristate "NFS client support for NFS version 4"
        depends on NFS_FS
        select SUNRPC_GSS
        select KEYS
index 0b96c2038346309bde0926e971ade7db4f72d37a..8bf3a3f6925ab7459d93416f171b05d8cbf13cb7 100644 (file)
@@ -9,21 +9,22 @@ nfs-y                         := client.o dir.o file.o getroot.o inode.o super.o \
                           write.o namespace.o mount_clnt.o \
                           dns_resolve.o cache_lib.o
 nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
-nfs-$(CONFIG_NFS_V2)   += proc.o nfs2xdr.o
-nfs-$(CONFIG_NFS_V3)   += nfs3proc.o nfs3xdr.o
-nfs-$(CONFIG_NFS_V3_ACL)       += nfs3acl.o
-nfs-$(CONFIG_NFS_V4)   += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
-                          nfs4super.o nfs4file.o delegation.o idmap.o \
-                          callback.o callback_xdr.o callback_proc.o \
-                          nfs4namespace.o nfs4getroot.o nfs4client.o
-nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o
+nfs-$(CONFIG_SYSCTL)   += sysctl.o
+nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
 
-ifeq ($(CONFIG_SYSCTL), y)
-nfs-y += sysctl.o
-nfs-$(CONFIG_NFS_V4) += nfs4sysctl.o
-endif
+obj-$(CONFIG_NFS_V2) += nfs2.o
+nfs2-y := nfs2super.o proc.o nfs2xdr.o
 
-nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
+obj-$(CONFIG_NFS_V3) += nfs3.o
+nfs3-y := nfs3super.o nfs3client.o nfs3proc.o nfs3xdr.o
+nfs3-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
+
+obj-$(CONFIG_NFS_V4) += nfs4.o
+nfs4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \
+         delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \
+         nfs4namespace.o nfs4getroot.o nfs4client.o
+nfs4-$(CONFIG_SYSCTL)  += nfs4sysctl.o
+nfs4-$(CONFIG_NFS_V4_1)        += pnfs.o pnfs_dev.o
 
 obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o
 nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o
index 7ae8a608956f60d7343fdfa9e77be7532b2db17d..dd392ed5f2e28ef48a85b37d0dc2ade6ab903d80 100644 (file)
@@ -228,6 +228,14 @@ bl_end_par_io_read(void *data, int unused)
        schedule_work(&rdata->task.u.tk_work);
 }
 
+static bool
+bl_check_alignment(u64 offset, u32 len, unsigned long blkmask)
+{
+       if ((offset & blkmask) || (len & blkmask))
+               return false;
+       return true;
+}
+
 static enum pnfs_try_status
 bl_read_pagelist(struct nfs_read_data *rdata)
 {
@@ -244,6 +252,9 @@ bl_read_pagelist(struct nfs_read_data *rdata)
        dprintk("%s enter nr_pages %u offset %lld count %u\n", __func__,
               rdata->pages.npages, f_offset, (unsigned int)rdata->args.count);
 
+       if (!bl_check_alignment(f_offset, rdata->args.count, PAGE_CACHE_MASK))
+               goto use_mds;
+
        par = alloc_parallel(rdata);
        if (!par)
                goto use_mds;
@@ -552,7 +563,7 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync)
        struct bio *bio = NULL;
        struct pnfs_block_extent *be = NULL, *cow_read = NULL;
        sector_t isect, last_isect = 0, extent_length = 0;
-       struct parallel_io *par;
+       struct parallel_io *par = NULL;
        loff_t offset = wdata->args.offset;
        size_t count = wdata->args.count;
        struct page **pages = wdata->args.pages;
@@ -563,6 +574,10 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync)
            NFS_SERVER(header->inode)->pnfs_blksize >> PAGE_CACHE_SHIFT;
 
        dprintk("%s enter, %Zu@%lld\n", __func__, count, offset);
+       /* Check for alignment first */
+       if (!bl_check_alignment(offset, count, PAGE_CACHE_MASK))
+               goto out_mds;
+
        /* At this point, wdata->pages is a (sequential) list of nfs_pages.
         * We want to write each, and if there is an error set pnfs_error
         * to have it redone using nfs.
@@ -996,14 +1011,32 @@ bl_clear_layoutdriver(struct nfs_server *server)
        return 0;
 }
 
+static void
+bl_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
+{
+       if (!bl_check_alignment(req->wb_offset, req->wb_bytes, PAGE_CACHE_MASK))
+               nfs_pageio_reset_read_mds(pgio);
+       else
+               pnfs_generic_pg_init_read(pgio, req);
+}
+
+static void
+bl_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
+{
+       if (!bl_check_alignment(req->wb_offset, req->wb_bytes, PAGE_CACHE_MASK))
+               nfs_pageio_reset_write_mds(pgio);
+       else
+               pnfs_generic_pg_init_write(pgio, req);
+}
+
 static const struct nfs_pageio_ops bl_pg_read_ops = {
-       .pg_init = pnfs_generic_pg_init_read,
+       .pg_init = bl_pg_init_read,
        .pg_test = pnfs_generic_pg_test,
        .pg_doio = pnfs_generic_pg_readpages,
 };
 
 static const struct nfs_pageio_ops bl_pg_write_ops = {
-       .pg_init = pnfs_generic_pg_init_write,
+       .pg_init = bl_pg_init_write,
        .pg_test = pnfs_generic_pg_test,
        .pg_doio = pnfs_generic_pg_writepages,
 };
index 23ff18fe080afd0b6470e6d72df4fa9a8b9d0dab..4c8459e5bdeef904e930cff50def65f7ac91f672 100644 (file)
@@ -37,31 +37,7 @@ static struct nfs_callback_data nfs_callback_info[NFS4_MAX_MINOR_VERSION + 1];
 static DEFINE_MUTEX(nfs_callback_mutex);
 static struct svc_program nfs4_callback_program;
 
-unsigned int nfs_callback_set_tcpport;
-unsigned short nfs_callback_tcpport;
 unsigned short nfs_callback_tcpport6;
-#define NFS_CALLBACK_MAXPORTNR (65535U)
-
-static int param_set_portnr(const char *val, const struct kernel_param *kp)
-{
-       unsigned long num;
-       int ret;
-
-       if (!val)
-               return -EINVAL;
-       ret = strict_strtoul(val, 0, &num);
-       if (ret == -EINVAL || num > NFS_CALLBACK_MAXPORTNR)
-               return -EINVAL;
-       *((unsigned int *)kp->arg) = num;
-       return 0;
-}
-static struct kernel_param_ops param_ops_portnr = {
-       .set = param_set_portnr,
-       .get = param_get_uint,
-};
-#define param_check_portnr(name, p) __param_check(name, p, unsigned int);
-
-module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644);
 
 /*
  * This is the NFSv4 callback kernel thread.
@@ -265,6 +241,10 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
                ret = -ENOMEM;
                goto out_err;
        }
+       /* As there is only one thread we need to over-ride the
+        * default maximum of 80 connections
+        */
+       serv->sv_maxconn = 1024;
 
        ret = svc_bind(serv, net);
        if (ret < 0) {
index a5527c90a5aae67a67e2320ffa9d2dea1b00d4d3..b44d7b128b71973678ff265a9ea13dbeb1415c00 100644 (file)
@@ -192,7 +192,7 @@ extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args,
                                    struct cb_process_state *cps);
 extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy,
                                   struct cb_process_state *cps);
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 extern int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt);
 extern void nfs_callback_down(int minorversion);
 extern int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation,
index 65afa382c5e3583c78a24e3deb907dd8bdfc276a..9fc0d9dfc91b8a5e4226b0fcfb56bb55658f0869 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);
+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 = {
@@ -85,21 +83,64 @@ 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 */
+       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);
 
 /*
  * Allocate a shared client record
@@ -116,7 +157,10 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
        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;
@@ -145,12 +189,14 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
        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
+#if IS_ENABLED(CONFIG_NFS_V4)
 /* 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)
 {
@@ -205,11 +251,13 @@ 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
@@ -324,6 +372,7 @@ int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
        }
        return 0;
 }
+EXPORT_SYMBOL_GPL(nfs_sockaddr_match_ipaddr);
 #endif /* CONFIG_NFS_V4_1 */
 
 /*
@@ -362,7 +411,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)
@@ -390,6 +439,7 @@ int nfs_wait_client_init_complete(const struct nfs_client *clp)
        return wait_event_killable(nfs_client_active_wq,
                        nfs_client_init_is_complete(clp));
 }
+EXPORT_SYMBOL_GPL(nfs_wait_client_init_complete);
 
 /*
  * Found an existing client.  Make sure it's ready before returning.
@@ -431,9 +481,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 {
@@ -450,20 +501,20 @@ nfs_get_client(const struct nfs_client_initdata *cl_init,
                        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 = cl_init->rpc_ops->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",
                cl_init->hostname ?: "", PTR_ERR(new));
        return new;
 }
+EXPORT_SYMBOL_GPL(nfs_get_client);
 
 /*
  * Mark a server as ready or failed
@@ -474,6 +525,7 @@ void nfs_mark_client_ready(struct nfs_client *clp, int state)
        clp->cl_cons_state = state;
        wake_up_all(&nfs_client_active_wq);
 }
+EXPORT_SYMBOL_GPL(nfs_mark_client_ready);
 
 /*
  * Initialise the timeout values for a connection
@@ -515,6 +567,7 @@ void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
                BUG();
        }
 }
+EXPORT_SYMBOL_GPL(nfs_init_timeout_values);
 
 /*
  * Create an RPC client handle
@@ -554,6 +607,7 @@ int nfs_create_rpc_client(struct nfs_client *clp,
        clp->cl_rpcclient = clnt;
        return 0;
 }
+EXPORT_SYMBOL_GPL(nfs_create_rpc_client);
 
 /*
  * Version 2 or 3 client destruction
@@ -605,36 +659,6 @@ 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
  */
@@ -670,6 +694,7 @@ int nfs_init_server_rpcclient(struct nfs_server *server,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(nfs_init_server_rpcclient);
 
 /**
  * nfs_init_client - Initialise an NFS2 or NFS3 client
@@ -709,18 +734,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,
        };
@@ -730,21 +757,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)
@@ -798,8 +810,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;
 
@@ -911,6 +921,7 @@ out_error:
        dprintk("nfs_probe_fsinfo: error = %d\n", -error);
        return error;
 }
+EXPORT_SYMBOL_GPL(nfs_probe_fsinfo);
 
 /*
  * Copy useful information when duplicating a server record
@@ -927,6 +938,7 @@ void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *sour
        target->caps = source->caps;
        target->options = source->options;
 }
+EXPORT_SYMBOL_GPL(nfs_server_copy_userdata);
 
 void nfs_server_insert_lists(struct nfs_server *server)
 {
@@ -940,6 +952,7 @@ void nfs_server_insert_lists(struct nfs_server *server)
        spin_unlock(&nn->nfs_client_lock);
 
 }
+EXPORT_SYMBOL_GPL(nfs_server_insert_lists);
 
 static void nfs_server_remove_lists(struct nfs_server *server)
 {
@@ -999,6 +1012,7 @@ struct nfs_server *nfs_alloc_server(void)
 
        return server;
 }
+EXPORT_SYMBOL_GPL(nfs_alloc_server);
 
 /*
  * Free up a server record
@@ -1027,13 +1041,14 @@ void nfs_free_server(struct nfs_server *server)
        nfs_release_automount_timer();
        dprintk("<-- nfs_free_server()\n");
 }
+EXPORT_SYMBOL_GPL(nfs_free_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;
@@ -1049,7 +1064,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;
 
@@ -1058,13 +1073,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)
@@ -1072,7 +1087,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;
@@ -1094,6 +1109,7 @@ error:
        nfs_free_server(server);
        return ERR_PTR(error);
 }
+EXPORT_SYMBOL_GPL(nfs_create_server);
 
 /*
  * Clone an NFS2, NFS3 or NFS4 server record
@@ -1133,8 +1149,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);
@@ -1165,6 +1179,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)
 {
@@ -1172,7 +1187,7 @@ void nfs_clients_init(struct net *net)
 
        INIT_LIST_HEAD(&nn->nfs_client_list);
        INIT_LIST_HEAD(&nn->nfs_volume_list);
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
        idr_init(&nn->cb_ident_idr);
 #endif
        spin_lock_init(&nn->nfs_client_lock);
index 1f3ccd934635dd4b3a03abc0831dcfbe7b6ab865..bbc6a4dba0d8e05d1940bc8d1136b5bc9d754778 100644 (file)
@@ -8,7 +8,7 @@
 #ifndef FS_NFS_DELEGATION_H
 #define FS_NFS_DELEGATION_H
 
-#if defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V4)
 /*
  * NFSv4 delegation
  */
index d49f1b9cd3fdc058e9863384629fc618ffb49314..627f108ede23327e3339d4e35ac47f6cb09490d3 100644 (file)
@@ -17,6 +17,7 @@
  *  6 Jun 1999 Cache readdir lookups in the page cache. -DaveM
  */
 
+#include <linux/module.h>
 #include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/stat.h>
@@ -935,6 +936,7 @@ void nfs_force_lookup_revalidate(struct inode *dir)
 {
        NFS_I(dir)->cache_change_attribute++;
 }
+EXPORT_SYMBOL_GPL(nfs_force_lookup_revalidate);
 
 /*
  * A check for whether or not the parent directory has changed.
@@ -1196,6 +1198,7 @@ const struct dentry_operations nfs_dentry_operations = {
        .d_automount    = nfs_d_automount,
        .d_release      = nfs_d_release,
 };
+EXPORT_SYMBOL_GPL(nfs_dentry_operations);
 
 struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
 {
@@ -1263,8 +1266,9 @@ out:
        nfs_free_fhandle(fhandle);
        return res;
 }
+EXPORT_SYMBOL_GPL(nfs_lookup);
 
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 static int nfs4_lookup_revalidate(struct dentry *, unsigned int);
 
 const struct dentry_operations nfs4_dentry_operations = {
@@ -1274,6 +1278,7 @@ const struct dentry_operations nfs4_dentry_operations = {
        .d_automount    = nfs_d_automount,
        .d_release      = nfs_d_release,
 };
+EXPORT_SYMBOL_GPL(nfs4_dentry_operations);
 
 static fmode_t flags_to_mode(int flags)
 {
@@ -1416,6 +1421,7 @@ no_open:
 
        return finish_no_open(file, res);
 }
+EXPORT_SYMBOL_GPL(nfs_atomic_open);
 
 static int nfs4_lookup_revalidate(struct dentry *dentry, unsigned int flags)
 {
@@ -1508,6 +1514,7 @@ out_error:
        dput(parent);
        return error;
 }
+EXPORT_SYMBOL_GPL(nfs_instantiate);
 
 /*
  * Following a failed create operation, we drop the dentry rather
@@ -1536,6 +1543,7 @@ out_err:
        d_drop(dentry);
        return error;
 }
+EXPORT_SYMBOL_GPL(nfs_create);
 
 /*
  * See comments for nfs_proc_create regarding failed operations.
@@ -1563,6 +1571,7 @@ out_err:
        d_drop(dentry);
        return status;
 }
+EXPORT_SYMBOL_GPL(nfs_mknod);
 
 /*
  * See comments for nfs_proc_create regarding failed operations.
@@ -1586,6 +1595,7 @@ out_err:
        d_drop(dentry);
        return error;
 }
+EXPORT_SYMBOL_GPL(nfs_mkdir);
 
 static void nfs_dentry_handle_enoent(struct dentry *dentry)
 {
@@ -1609,6 +1619,7 @@ int nfs_rmdir(struct inode *dir, struct dentry *dentry)
 
        return error;
 }
+EXPORT_SYMBOL_GPL(nfs_rmdir);
 
 /*
  * Remove a file after making sure there are no pending writes,
@@ -1680,6 +1691,7 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry)
                d_rehash(dentry);
        return error;
 }
+EXPORT_SYMBOL_GPL(nfs_unlink);
 
 /*
  * To create a symbolic link, most file systems instantiate a new inode,
@@ -1750,6 +1762,7 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(nfs_symlink);
 
 int
 nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
@@ -1771,6 +1784,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
        }
        return error;
 }
+EXPORT_SYMBOL_GPL(nfs_link);
 
 /*
  * RENAME
@@ -1869,6 +1883,7 @@ out:
                dput(dentry);
        return error;
 }
+EXPORT_SYMBOL_GPL(nfs_rename);
 
 static DEFINE_SPINLOCK(nfs_access_lru_lock);
 static LIST_HEAD(nfs_access_lru_list);
@@ -1969,6 +1984,7 @@ void nfs_access_zap_cache(struct inode *inode)
        spin_unlock(&nfs_access_lru_lock);
        nfs_access_free_list(&head);
 }
+EXPORT_SYMBOL_GPL(nfs_access_zap_cache);
 
 static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, struct rpc_cred *cred)
 {
@@ -2129,6 +2145,7 @@ int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags)
 {
        return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags));
 }
+EXPORT_SYMBOL_GPL(nfs_may_open);
 
 int nfs_permission(struct inode *inode, int mask)
 {
@@ -2188,6 +2205,7 @@ out_notsup:
                res = generic_permission(inode, mask);
        goto out;
 }
+EXPORT_SYMBOL_GPL(nfs_permission);
 
 /*
  * Local variables:
index 42dce909ec70073509c33eabdf8b9784eda68faf..b7b4f80968b58679856ddd03625173805e3ac542 100644 (file)
@@ -460,7 +460,7 @@ static void nfs_inode_dio_write_done(struct inode *inode)
        inode_dio_done(inode);
 }
 
-#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
 static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
 {
        struct nfs_pageio_descriptor desc;
index b3924b8a600021e27c89fc6c9ff910a514aec9eb..31c26c4dcc238110de0fa7374f1a2ab51a1541cd 100644 (file)
@@ -8,6 +8,7 @@
 
 #ifdef CONFIG_NFS_USE_KERNEL_DNS
 
+#include <linux/module.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/dns_resolver.h>
 #include "dns_resolve.h"
@@ -27,9 +28,11 @@ ssize_t nfs_dns_resolve_name(struct net *net, char *name, size_t namelen,
        kfree(ip_addr);
        return ret;
 }
+EXPORT_SYMBOL_GPL(nfs_dns_resolve_name);
 
 #else
 
+#include <linux/module.h>
 #include <linux/hash.h>
 #include <linux/string.h>
 #include <linux/kmod.h>
@@ -345,6 +348,7 @@ ssize_t nfs_dns_resolve_name(struct net *net, char *name,
                ret = -ESRCH;
        return ret;
 }
+EXPORT_SYMBOL_GPL(nfs_dns_resolve_name);
 
 int nfs_dns_resolver_cache_init(struct net *net)
 {
index 70d124a61b98d4e6b7fa3487e148de56c57406fb..b039a17ee941acfb2ad7ff3fd937d6c91119bfd2 100644 (file)
@@ -16,6 +16,7 @@
  *  nfs regular file handling functions
  */
 
+#include <linux/module.h>
 #include <linux/time.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -52,6 +53,7 @@ int nfs_check_flags(int flags)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(nfs_check_flags);
 
 /*
  * Open file
@@ -84,6 +86,7 @@ nfs_file_release(struct inode *inode, struct file *filp)
        nfs_inc_stats(inode, NFSIOS_VFSRELEASE);
        return nfs_release(inode, filp);
 }
+EXPORT_SYMBOL_GPL(nfs_file_release);
 
 /**
  * nfs_revalidate_size - Revalidate the file size
@@ -137,6 +140,7 @@ loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
 
        return generic_file_llseek(filp, offset, origin);
 }
+EXPORT_SYMBOL_GPL(nfs_file_llseek);
 
 /*
  * Flush all dirty pages, and check for write errors.
@@ -165,6 +169,7 @@ nfs_file_flush(struct file *file, fl_owner_t id)
        /* Flush writes to the server and return any errors */
        return vfs_fsync(file, 0);
 }
+EXPORT_SYMBOL_GPL(nfs_file_flush);
 
 ssize_t
 nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
@@ -189,6 +194,7 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
        }
        return result;
 }
+EXPORT_SYMBOL_GPL(nfs_file_read);
 
 ssize_t
 nfs_file_splice_read(struct file *filp, loff_t *ppos,
@@ -211,6 +217,7 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos,
        }
        return res;
 }
+EXPORT_SYMBOL_GPL(nfs_file_splice_read);
 
 int
 nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
@@ -232,6 +239,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
        }
        return status;
 }
+EXPORT_SYMBOL_GPL(nfs_file_mmap);
 
 /*
  * Flush any dirty pages for this process, and check for write errors.
@@ -270,6 +278,7 @@ nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync)
                ret = status;
        return ret;
 }
+EXPORT_SYMBOL_GPL(nfs_file_fsync_commit);
 
 static int
 nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
@@ -447,8 +456,11 @@ static int nfs_release_page(struct page *page, gfp_t gfp)
 
        dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page);
 
-       /* Only do I/O if gfp is a superset of GFP_KERNEL */
-       if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL) {
+       /* Only do I/O if gfp is a superset of GFP_KERNEL, and we're not
+        * doing this memory reclaim for a fs-related allocation.
+        */
+       if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL &&
+           !(current->flags & PF_FSTRANS)) {
                int how = FLUSH_SYNC;
 
                /* Don't let kswapd deadlock waiting for OOM RPC calls */
@@ -611,6 +623,7 @@ out_swapfile:
        printk(KERN_INFO "NFS: attempt to write to active swap file!\n");
        goto out;
 }
+EXPORT_SYMBOL_GPL(nfs_file_write);
 
 ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
                              struct file *filp, loff_t *ppos,
@@ -642,6 +655,7 @@ ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
                nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, written);
        return ret;
 }
+EXPORT_SYMBOL_GPL(nfs_file_splice_write);
 
 static int
 do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
@@ -802,6 +816,7 @@ int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
 out_err:
        return ret;
 }
+EXPORT_SYMBOL_GPL(nfs_lock);
 
 /*
  * Lock a (portion of) a file
@@ -819,6 +834,15 @@ int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
        if (!(fl->fl_flags & FL_FLOCK))
                return -ENOLCK;
 
+       /*
+        * The NFSv4 protocol doesn't support LOCK_MAND, which is not part of
+        * any standard. In principle we might be able to support LOCK_MAND
+        * on NFSv2/3 since NLMv3/4 support DOS share modes, but for now the
+        * NFS code is not set up for it.
+        */
+       if (fl->fl_type & LOCK_MAND)
+               return -EINVAL;
+
        if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FLOCK)
                is_local = 1;
 
@@ -831,6 +855,7 @@ int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
                return do_unlk(filp, cmd, fl, is_local);
        return do_setlk(filp, cmd, fl, is_local);
 }
+EXPORT_SYMBOL_GPL(nfs_flock);
 
 /*
  * There is no protocol support for leases, so we have no way to implement
@@ -843,6 +868,7 @@ int nfs_setlease(struct file *file, long arg, struct file_lock **fl)
                        file->f_path.dentry->d_name.name, arg);
        return -EINVAL;
 }
+EXPORT_SYMBOL_GPL(nfs_setlease);
 
 const struct file_operations nfs_file_operations = {
        .llseek         = nfs_file_llseek,
@@ -862,3 +888,4 @@ const struct file_operations nfs_file_operations = {
        .check_flags    = nfs_check_flags,
        .setlease       = nfs_setlease,
 };
+EXPORT_SYMBOL_GPL(nfs_file_operations);
index 864c51e4b400e5c7248bdd93eaed19772c0f23f2..b701358c39c351d0613d1db29ebcf382ca8cb0a6 100644 (file)
@@ -52,8 +52,6 @@
 
 #define NFS_UINT_MAXLEN 11
 
-/* Default cache timeout is 10 minutes */
-unsigned int nfs_idmap_cache_timeout = 600;
 static const struct cred *id_resolver_cache;
 static struct key_type key_type_id_resolver_legacy;
 
@@ -205,12 +203,18 @@ static int nfs_idmap_init_keyring(void)
        if (ret < 0)
                goto failed_put_key;
 
+       ret = register_key_type(&key_type_id_resolver_legacy);
+       if (ret < 0)
+               goto failed_reg_legacy;
+
        set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
        cred->thread_keyring = keyring;
        cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
        id_resolver_cache = cred;
        return 0;
 
+failed_reg_legacy:
+       unregister_key_type(&key_type_id_resolver);
 failed_put_key:
        key_put(keyring);
 failed_put_cred:
@@ -222,6 +226,7 @@ static void nfs_idmap_quit_keyring(void)
 {
        key_revoke(id_resolver_cache->thread_keyring);
        unregister_key_type(&key_type_id_resolver);
+       unregister_key_type(&key_type_id_resolver_legacy);
        put_cred(id_resolver_cache);
 }
 
@@ -359,7 +364,6 @@ static int nfs_idmap_lookup_id(const char *name, size_t namelen, const char *typ
 }
 
 /* idmap classic begins here */
-module_param(nfs_idmap_cache_timeout, int, 0644);
 
 enum {
        Opt_find_uid, Opt_find_gid, Opt_find_user, Opt_find_group, Opt_find_err
@@ -385,7 +389,7 @@ static const struct rpc_pipe_ops idmap_upcall_ops = {
 };
 
 static struct key_type key_type_id_resolver_legacy = {
-       .name           = "id_resolver",
+       .name           = "id_legacy",
        .instantiate    = user_instantiate,
        .match          = user_match,
        .revoke         = user_revoke,
@@ -674,6 +678,7 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons,
        if (ret < 0)
                goto out2;
 
+       BUG_ON(idmap->idmap_key_cons != NULL);
        idmap->idmap_key_cons = cons;
 
        ret = rpc_queue_upcall(idmap->idmap_pipe, msg);
@@ -687,8 +692,7 @@ out2:
 out1:
        kfree(msg);
 out0:
-       key_revoke(cons->key);
-       key_revoke(cons->authkey);
+       complete_request_key(cons, ret);
        return ret;
 }
 
@@ -722,11 +726,18 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
 {
        struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode);
        struct idmap *idmap = (struct idmap *)rpci->private;
-       struct key_construction *cons = idmap->idmap_key_cons;
+       struct key_construction *cons;
        struct idmap_msg im;
        size_t namelen_in;
        int ret;
 
+       /* If instantiation is successful, anyone waiting for key construction
+        * will have been woken up and someone else may now have used
+        * idmap_key_cons - so after this point we may no longer touch it.
+        */
+       cons = ACCESS_ONCE(idmap->idmap_key_cons);
+       idmap->idmap_key_cons = NULL;
+
        if (mlen != sizeof(im)) {
                ret = -ENOSPC;
                goto out;
@@ -739,7 +750,7 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
 
        if (!(im.im_status & IDMAP_STATUS_SUCCESS)) {
                ret = mlen;
-               complete_request_key(idmap->idmap_key_cons, -ENOKEY);
+               complete_request_key(cons, -ENOKEY);
                goto out_incomplete;
        }
 
@@ -756,7 +767,7 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
        }
 
 out:
-       complete_request_key(idmap->idmap_key_cons, ret);
+       complete_request_key(cons, ret);
 out_incomplete:
        return ret;
 }
index 35f7e4bc680ed1205f4d846f8649c7f77b712c20..2ed6138f32ad16cc528f98e84a32fc41ec79bbd6 100644 (file)
@@ -50,6 +50,7 @@
 #include "fscache.h"
 #include "dns_resolve.h"
 #include "pnfs.h"
+#include "nfs.h"
 #include "netns.h"
 
 #define NFSDBG_FACILITY                NFSDBG_VFS
@@ -81,6 +82,7 @@ int nfs_wait_bit_killable(void *word)
        freezable_schedule();
        return 0;
 }
+EXPORT_SYMBOL_GPL(nfs_wait_bit_killable);
 
 /**
  * nfs_compat_user_ino64 - returns the user-visible inode number
@@ -105,7 +107,7 @@ u64 nfs_compat_user_ino64(u64 fileid)
        return ino;
 }
 
-static void nfs_clear_inode(struct inode *inode)
+void nfs_clear_inode(struct inode *inode)
 {
        /*
         * The following should never happen...
@@ -116,6 +118,7 @@ static void nfs_clear_inode(struct inode *inode)
        nfs_access_zap_cache(inode);
        nfs_fscache_release_inode_cookie(inode);
 }
+EXPORT_SYMBOL_GPL(nfs_clear_inode);
 
 void nfs_evict_inode(struct inode *inode)
 {
@@ -185,6 +188,7 @@ void nfs_zap_acl_cache(struct inode *inode)
        NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_ACL;
        spin_unlock(&inode->i_lock);
 }
+EXPORT_SYMBOL_GPL(nfs_zap_acl_cache);
 
 void nfs_invalidate_atime(struct inode *inode)
 {
@@ -192,6 +196,7 @@ void nfs_invalidate_atime(struct inode *inode)
        NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME;
        spin_unlock(&inode->i_lock);
 }
+EXPORT_SYMBOL_GPL(nfs_invalidate_atime);
 
 /*
  * Invalidate, but do not unhash, the inode.
@@ -390,6 +395,7 @@ out_no_inode:
        dprintk("nfs_fhget: iget failed with error %ld\n", PTR_ERR(inode));
        goto out;
 }
+EXPORT_SYMBOL_GPL(nfs_fhget);
 
 #define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE|ATTR_OPEN)
 
@@ -437,6 +443,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
 out:
        return error;
 }
+EXPORT_SYMBOL_GPL(nfs_setattr);
 
 /**
  * nfs_vmtruncate - unmap mappings "freed" by truncate() syscall
@@ -495,6 +502,7 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr)
                nfs_vmtruncate(inode, attr->ia_size);
        }
 }
+EXPORT_SYMBOL_GPL(nfs_setattr_update_inode);
 
 int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
@@ -534,6 +542,7 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 out:
        return err;
 }
+EXPORT_SYMBOL_GPL(nfs_getattr);
 
 static void nfs_init_lock_context(struct nfs_lock_context *l_ctx)
 {
@@ -622,6 +631,7 @@ void nfs_close_context(struct nfs_open_context *ctx, int is_sync)
                return;
        nfs_revalidate_inode(server, inode);
 }
+EXPORT_SYMBOL_GPL(nfs_close_context);
 
 struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, fmode_t f_mode)
 {
@@ -648,6 +658,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, fmode_t f
        ctx->mdsthreshold = NULL;
        return ctx;
 }
+EXPORT_SYMBOL_GPL(alloc_nfs_open_context);
 
 struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
 {
@@ -655,6 +666,7 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
                atomic_inc(&ctx->lock_context.count);
        return ctx;
 }
+EXPORT_SYMBOL_GPL(get_nfs_open_context);
 
 static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
 {
@@ -682,6 +694,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
 {
        __put_nfs_open_context(ctx, 0);
 }
+EXPORT_SYMBOL_GPL(put_nfs_open_context);
 
 /*
  * Ensure that mmap has a recent RPC credential for use when writing out
@@ -697,6 +710,7 @@ void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
        list_add(&ctx->list, &nfsi->open_files);
        spin_unlock(&inode->i_lock);
 }
+EXPORT_SYMBOL_GPL(nfs_file_set_open_context);
 
 /*
  * Given an inode, search for an open context with the desired characteristics
@@ -841,6 +855,7 @@ int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
                return NFS_STALE(inode) ? -ESTALE : 0;
        return __nfs_revalidate_inode(server, inode);
 }
+EXPORT_SYMBOL_GPL(nfs_revalidate_inode);
 
 static int nfs_invalidate_mapping(struct inode *inode, struct address_space *mapping)
 {
@@ -1027,6 +1042,7 @@ void nfs_fattr_init(struct nfs_fattr *fattr)
        fattr->owner_name = NULL;
        fattr->group_name = NULL;
 }
+EXPORT_SYMBOL_GPL(nfs_fattr_init);
 
 struct nfs_fattr *nfs_alloc_fattr(void)
 {
@@ -1037,6 +1053,7 @@ struct nfs_fattr *nfs_alloc_fattr(void)
                nfs_fattr_init(fattr);
        return fattr;
 }
+EXPORT_SYMBOL_GPL(nfs_alloc_fattr);
 
 struct nfs_fh *nfs_alloc_fhandle(void)
 {
@@ -1047,6 +1064,7 @@ struct nfs_fh *nfs_alloc_fhandle(void)
                fh->size = 0;
        return fh;
 }
+EXPORT_SYMBOL_GPL(nfs_alloc_fhandle);
 
 #ifdef NFS_DEBUG
 /*
@@ -1167,6 +1185,7 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
 
        return status;
 }
+EXPORT_SYMBOL_GPL(nfs_refresh_inode);
 
 static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr *fattr)
 {
@@ -1203,6 +1222,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr)
        spin_unlock(&inode->i_lock);
        return status;
 }
+EXPORT_SYMBOL_GPL(nfs_post_op_update_inode);
 
 /**
  * nfs_post_op_update_inode_force_wcc - try to update the inode attribute cache
@@ -1254,6 +1274,7 @@ out_noforce:
        spin_unlock(&inode->i_lock);
        return status;
 }
+EXPORT_SYMBOL_GPL(nfs_post_op_update_inode_force_wcc);
 
 /*
  * Many nfs protocol calls return the new file attributes after
@@ -1471,27 +1492,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
        return -ESTALE;
 }
 
-
-#ifdef CONFIG_NFS_V4
-
-/*
- * Clean out any remaining NFSv4 state that might be left over due
- * to open() calls that passed nfs_atomic_lookup, but failed to call
- * nfs_open().
- */
-void nfs4_evict_inode(struct inode *inode)
-{
-       truncate_inode_pages(&inode->i_data, 0);
-       clear_inode(inode);
-       pnfs_return_layout(inode);
-       pnfs_destroy_layout(NFS_I(inode));
-       /* If we are holding a delegation, return it! */
-       nfs_inode_return_delegation_noreclaim(inode);
-       /* First call standard NFS clear_inode() code */
-       nfs_clear_inode(inode);
-}
-#endif
-
 struct inode *nfs_alloc_inode(struct super_block *sb)
 {
        struct nfs_inode *nfsi;
@@ -1504,11 +1504,12 @@ struct inode *nfs_alloc_inode(struct super_block *sb)
        nfsi->acl_access = ERR_PTR(-EAGAIN);
        nfsi->acl_default = ERR_PTR(-EAGAIN);
 #endif
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
        nfsi->nfs4_acl = NULL;
 #endif /* CONFIG_NFS_V4 */
        return &nfsi->vfs_inode;
 }
+EXPORT_SYMBOL_GPL(nfs_alloc_inode);
 
 static void nfs_i_callback(struct rcu_head *head)
 {
@@ -1520,10 +1521,11 @@ void nfs_destroy_inode(struct inode *inode)
 {
        call_rcu(&inode->i_rcu, nfs_i_callback);
 }
+EXPORT_SYMBOL_GPL(nfs_destroy_inode);
 
 static inline void nfs4_init_once(struct nfs_inode *nfsi)
 {
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
        INIT_LIST_HEAD(&nfsi->open_states);
        nfsi->delegation = NULL;
        nfsi->delegation_state = 0;
@@ -1569,6 +1571,7 @@ static void nfs_destroy_inodecache(void)
 }
 
 struct workqueue_struct *nfsiod_workqueue;
+EXPORT_SYMBOL_GPL(nfsiod_workqueue);
 
 /*
  * start up the nfsiod workqueue
@@ -1629,94 +1632,80 @@ static int __init init_nfs_fs(void)
 
        err = nfs_dns_resolver_init();
        if (err < 0)
-               goto out11;
+               goto out10;;
 
        err = register_pernet_subsys(&nfs_net_ops);
        if (err < 0)
-               goto out10;
+               goto out9;
 
        err = nfs_fscache_register();
        if (err < 0)
-               goto out9;
+               goto out8;
 
        err = nfsiod_start();
        if (err)
-               goto out8;
+               goto out7;
 
        err = nfs_fs_proc_init();
        if (err)
-               goto out7;
+               goto out6;
 
        err = nfs_init_nfspagecache();
        if (err)
-               goto out6;
+               goto out5;
 
        err = nfs_init_inodecache();
        if (err)
-               goto out5;
+               goto out4;
 
        err = nfs_init_readpagecache();
        if (err)
-               goto out4;
+               goto out3;
 
        err = nfs_init_writepagecache();
        if (err)
-               goto out3;
+               goto out2;
 
        err = nfs_init_directcache();
        if (err)
-               goto out2;
+               goto out1;
 
 #ifdef CONFIG_PROC_FS
        rpc_proc_register(&init_net, &nfs_rpcstat);
 #endif
-
-#ifdef CONFIG_NFS_V4
-       err = init_nfs_v4();
-       if (err)
-               goto out1;
-#endif
-
        if ((err = register_nfs_fs()) != 0)
                goto out0;
 
        return 0;
 out0:
-#ifdef CONFIG_NFS_V4
-       exit_nfs_v4();
-out1:
-#endif
 #ifdef CONFIG_PROC_FS
        rpc_proc_unregister(&init_net, "nfs");
 #endif
        nfs_destroy_directcache();
-out2:
+out1:
        nfs_destroy_writepagecache();
-out3:
+out2:
        nfs_destroy_readpagecache();
-out4:
+out3:
        nfs_destroy_inodecache();
-out5:
+out4:
        nfs_destroy_nfspagecache();
-out6:
+out5:
        nfs_fs_proc_exit();
-out7:
+out6:
        nfsiod_stop();
-out8:
+out7:
        nfs_fscache_unregister();
-out9:
+out8:
        unregister_pernet_subsys(&nfs_net_ops);
-out10:
+out9:
        nfs_dns_resolver_destroy();
-out11:
+out10:
        return err;
 }
 
 static void __exit exit_nfs_fs(void)
 {
-#ifdef CONFIG_NFS_V4
-       exit_nfs_v4();
-#endif
        nfs_destroy_directcache();
        nfs_destroy_writepagecache();
        nfs_destroy_readpagecache();
index cfafd13b6fe96ed4646c8ee7da9b89629d392029..8865538b26b64eab7d951fffdb545be4614649bf 100644 (file)
@@ -90,7 +90,7 @@ struct nfs_client_initdata {
        const char *hostname;
        const struct sockaddr *addr;
        size_t addrlen;
-       const struct nfs_rpc_ops *rpc_ops;
+       struct nfs_subversion *nfs_mod;
        int proto;
        u32 minorversion;
        struct net *net;
@@ -187,12 +187,11 @@ extern struct nfs_client *nfs4_find_client_ident(struct net *, int);
 extern struct nfs_client *
 nfs4_find_client_sessionid(struct net *, const struct sockaddr *,
                                struct nfs4_sessionid *);
-extern struct nfs_server *nfs_create_server(
-                                       const struct nfs_parsed_mount_data *,
-                                       struct nfs_fh *);
+extern struct nfs_server *nfs_create_server(struct nfs_mount_info *,
+                                       struct nfs_subversion *);
 extern struct nfs_server *nfs4_create_server(
-                                       const struct nfs_parsed_mount_data *,
-                                       struct nfs_fh *);
+                                       struct nfs_mount_info *,
+                                       struct nfs_subversion *);
 extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *,
                                                      struct nfs_fh *);
 extern void nfs_free_server(struct nfs_server *server);
@@ -224,6 +223,13 @@ static inline void nfs_fs_proc_exit(void)
 int nfs_sockaddr_match_ipaddr(const struct sockaddr *, const struct sockaddr *);
 #endif
 
+/* nfs3client.c */
+#if IS_ENABLED(CONFIG_NFS_V3)
+struct nfs_server *nfs3_create_server(struct nfs_mount_info *, struct nfs_subversion *);
+struct nfs_server *nfs3_clone_server(struct nfs_server *, struct nfs_fh *,
+                                    struct nfs_fattr *, rpc_authflavor_t);
+#endif
+
 /* callback_xdr.c */
 extern struct svc_version nfs4_callback_version1;
 extern struct svc_version nfs4_callback_version4;
@@ -256,7 +262,7 @@ extern int nfs3_decode_dirent(struct xdr_stream *,
                                struct nfs_entry *, int);
 
 /* nfs4xdr.c */
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 extern int nfs4_decode_dirent(struct xdr_stream *,
                                struct nfs_entry *, int);
 #endif
@@ -266,7 +272,7 @@ extern const u32 nfs41_maxwrite_overhead;
 #endif
 
 /* nfs4proc.c */
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 extern struct rpc_procinfo nfs4_procedures[];
 #endif
 
@@ -313,24 +319,26 @@ extern struct workqueue_struct *nfsiod_workqueue;
 extern struct inode *nfs_alloc_inode(struct super_block *sb);
 extern void nfs_destroy_inode(struct inode *);
 extern int nfs_write_inode(struct inode *, struct writeback_control *);
+extern void nfs_clear_inode(struct inode *);
 extern void nfs_evict_inode(struct inode *);
-#ifdef CONFIG_NFS_V4
-extern void nfs4_evict_inode(struct inode *);
-#endif
 void nfs_zap_acl_cache(struct inode *inode);
 extern int nfs_wait_bit_killable(void *word);
 
 /* super.c */
+extern const struct super_operations nfs_sops;
+extern struct file_system_type nfs_fs_type;
 extern struct file_system_type nfs_xdev_fs_type;
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 extern struct file_system_type nfs4_xdev_fs_type;
 extern struct file_system_type nfs4_referral_fs_type;
 #endif
+struct dentry *nfs_try_mount(int, const char *, struct nfs_mount_info *,
+                       struct nfs_subversion *);
 void nfs_initialise_sb(struct super_block *);
 int nfs_set_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *);
 int nfs_clone_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *);
-struct dentry *nfs_fs_mount_common(struct file_system_type *, struct nfs_server *,
-                                  int, const char *, struct nfs_mount_info *);
+struct dentry *nfs_fs_mount_common(struct nfs_server *, int, const char *,
+                                  struct nfs_mount_info *, struct nfs_subversion *);
 struct dentry *nfs_fs_mount(struct file_system_type *, int, const char *, void *);
 struct dentry * nfs_xdev_mount_common(struct file_system_type *, int,
                const char *, struct nfs_mount_info *);
@@ -356,7 +364,7 @@ struct vfsmount *nfs_do_submount(struct dentry *, struct nfs_fh *,
 /* getroot.c */
 extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *,
                                   const char *);
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *,
                                    const char *);
 
index 08b9c93675da512e0ef8174a25e1e048f282b527..655925373b9161c6a6c64ad157002d10cf8064e2 100644 (file)
@@ -7,6 +7,7 @@
  * NFS namespace
  */
 
+#include <linux/module.h>
 #include <linux/dcache.h>
 #include <linux/gfp.h>
 #include <linux/mount.h>
@@ -112,6 +113,7 @@ Elong_unlock:
 Elong:
        return ERR_PTR(-ENAMETOOLONG);
 }
+EXPORT_SYMBOL_GPL(nfs_path);
 
 /*
  * nfs_d_automount - Handle crossing a mountpoint on the server
@@ -195,20 +197,7 @@ static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server,
                                           const char *devname,
                                           struct nfs_clone_mount *mountdata)
 {
-#ifdef CONFIG_NFS_V4
-       struct vfsmount *mnt = ERR_PTR(-EINVAL);
-       switch (server->nfs_client->rpc_ops->version) {
-               case 2:
-               case 3:
-                       mnt = vfs_kern_mount(&nfs_xdev_fs_type, 0, devname, mountdata);
-                       break;
-               case 4:
-                       mnt = vfs_kern_mount(&nfs4_xdev_fs_type, 0, devname, mountdata);
-       }
-       return mnt;
-#else
        return vfs_kern_mount(&nfs_xdev_fs_type, 0, devname, mountdata);
-#endif
 }
 
 /**
@@ -253,6 +242,7 @@ out:
        dprintk("<-- nfs_do_submount() = %p\n", mnt);
        return mnt;
 }
+EXPORT_SYMBOL_GPL(nfs_do_submount);
 
 struct vfsmount *nfs_submount(struct nfs_server *server, struct dentry *dentry,
                              struct nfs_fh *fh, struct nfs_fattr *fattr)
@@ -268,3 +258,4 @@ struct vfsmount *nfs_submount(struct nfs_server *server, struct dentry *dentry,
 
        return nfs_do_submount(dentry, fh, fattr, server->client->cl_auth->au_flavor);
 }
+EXPORT_SYMBOL_GPL(nfs_submount);
index 8a6394edb8b015375eb26016594a09e7b275261f..0539de1b8d1fe3477500b400ff2b9b6d5781b984 100644 (file)
@@ -20,7 +20,7 @@ struct nfs_net {
        wait_queue_head_t bl_wq;
        struct list_head nfs_client_list;
        struct list_head nfs_volume_list;
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
        struct idr cb_ident_idr; /* Protected by nfs_client_lock */
 #endif
        spinlock_t nfs_client_lock;
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
new file mode 100644 (file)
index 0000000..43679df
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012 Netapp, Inc. All rights reserved.
+ *
+ * Function and structures exported by the NFS module
+ * for use by NFS version-specific modules.
+ */
+#ifndef __LINUX_INTERNAL_NFS_H
+#define __LINUX_INTERNAL_NFS_H
+
+#include <linux/fs.h>
+#include <linux/sunrpc/sched.h>
+#include <linux/nfs_xdr.h>
+
+struct nfs_subversion {
+       struct module *owner;   /* THIS_MODULE pointer */
+       struct file_system_type *nfs_fs;        /* NFS filesystem type */
+       const struct rpc_version *rpc_vers;     /* NFS version information */
+       const struct nfs_rpc_ops *rpc_ops;      /* NFS operations */
+       const struct super_operations *sops;    /* NFS Super operations */
+       const struct xattr_handler **xattr;     /* NFS xattr handlers */
+       struct list_head list;          /* List of NFS versions */
+};
+
+struct nfs_subversion *get_nfs_version(unsigned int);
+void put_nfs_version(struct nfs_subversion *);
+void register_nfs_version(struct nfs_subversion *);
+void unregister_nfs_version(struct nfs_subversion *);
+
+#endif /* __LINUX_INTERNAL_NFS_H */
diff --git a/fs/nfs/nfs2super.c b/fs/nfs/nfs2super.c
new file mode 100644 (file)
index 0000000..0a9782c
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012 Netapp, Inc. All rights reserved.
+ */
+#include <linux/module.h>
+#include <linux/nfs_fs.h>
+#include "internal.h"
+#include "nfs.h"
+
+static struct nfs_subversion nfs_v2 = {
+       .owner = THIS_MODULE,
+       .nfs_fs   = &nfs_fs_type,
+       .rpc_vers = &nfs_version2,
+       .rpc_ops  = &nfs_v2_clientops,
+       .sops     = &nfs_sops,
+};
+
+static int __init init_nfs_v2(void)
+{
+       register_nfs_version(&nfs_v2);
+       return 0;
+}
+
+static void __exit exit_nfs_v2(void)
+{
+       unregister_nfs_version(&nfs_v2);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_nfs_v2);
+module_exit(exit_nfs_v2);
diff --git a/fs/nfs/nfs3client.c b/fs/nfs/nfs3client.c
new file mode 100644 (file)
index 0000000..b3fc65e
--- /dev/null
@@ -0,0 +1,65 @@
+#include <linux/nfs_fs.h>
+#include <linux/nfs_mount.h>
+#include "internal.h"
+
+#ifdef CONFIG_NFS_V3_ACL
+static struct rpc_stat         nfsacl_rpcstat = { &nfsacl_program };
+static const struct rpc_version *nfsacl_version[] = {
+       [3]                     = &nfsacl_version3,
+};
+
+const struct rpc_program nfsacl_program = {
+       .name                   = "nfsacl",
+       .number                 = NFS_ACL_PROGRAM,
+       .nrvers                 = ARRAY_SIZE(nfsacl_version),
+       .version                = nfsacl_version,
+       .stats                  = &nfsacl_rpcstat,
+};
+
+/*
+ * Initialise an NFSv3 ACL client connection
+ */
+static void nfs_init_server_aclclient(struct nfs_server *server)
+{
+       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
+
+struct nfs_server *nfs3_create_server(struct nfs_mount_info *mount_info,
+                                     struct nfs_subversion *nfs_mod)
+{
+       struct nfs_server *server = nfs_create_server(mount_info, nfs_mod);
+       /* Create a client RPC handle for the NFS v3 ACL management interface */
+       if (!IS_ERR(server))
+               nfs_init_server_aclclient(server);
+       return server;
+}
+
+struct nfs_server *nfs3_clone_server(struct nfs_server *source,
+                                    struct nfs_fh *fh,
+                                    struct nfs_fattr *fattr,
+                                    rpc_authflavor_t flavor)
+{
+       struct nfs_server *server = nfs_clone_server(source, fh, fattr, flavor);
+       if (!IS_ERR(server) && !IS_ERR(source->client_acl))
+               nfs_init_server_aclclient(server);
+       return server;
+}
index 65d23eb92fe03650dee0dda65d3e81d6e30ae0b7..0952c791df36eb4f1aa58beb20732c9af67a3098 100644 (file)
@@ -925,6 +925,7 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
        .file_ops       = &nfs_file_operations,
        .getroot        = nfs3_proc_get_root,
        .submount       = nfs_submount,
+       .try_mount      = nfs_try_mount,
        .getattr        = nfs3_proc_getattr,
        .setattr        = nfs3_proc_setattr,
        .lookup         = nfs3_proc_lookup,
@@ -968,4 +969,6 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
        .alloc_client   = nfs_alloc_client,
        .init_client    = nfs_init_client,
        .free_client    = nfs_free_client,
+       .create_server  = nfs3_create_server,
+       .clone_server   = nfs3_clone_server,
 };
diff --git a/fs/nfs/nfs3super.c b/fs/nfs/nfs3super.c
new file mode 100644 (file)
index 0000000..cc471c7
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012 Netapp, Inc. All rights reserved.
+ */
+#include <linux/module.h>
+#include <linux/nfs_fs.h>
+#include "internal.h"
+#include "nfs.h"
+
+static struct nfs_subversion nfs_v3 = {
+       .owner = THIS_MODULE,
+       .nfs_fs   = &nfs_fs_type,
+       .rpc_vers = &nfs_version3,
+       .rpc_ops  = &nfs_v3_clientops,
+       .sops     = &nfs_sops,
+};
+
+static int __init init_nfs_v3(void)
+{
+       register_nfs_version(&nfs_v3);
+       return 0;
+}
+
+static void __exit exit_nfs_v3(void)
+{
+       unregister_nfs_version(&nfs_v3);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_nfs_v3);
+module_exit(exit_nfs_v3);
index 5511690de8a583aec9b6a79915eb049b8544ea49..3b950dd81e81f82b4fd32c5b508fde181d07b875 100644 (file)
@@ -9,7 +9,7 @@
 #ifndef __LINUX_FS_NFS_NFS4_FS_H
 #define __LINUX_FS_NFS_NFS4_FS_H
 
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 
 struct idmap;
 
@@ -205,9 +205,6 @@ extern const struct dentry_operations nfs4_dentry_operations;
 int nfs_atomic_open(struct inode *, struct dentry *, struct file *,
                    unsigned, umode_t, int *);
 
-/* write.c */
-int nfs4_write_inode(struct inode *, struct writeback_control *);
-
 /* nfs4namespace.c */
 rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *);
 struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *);
@@ -366,9 +363,11 @@ extern const nfs4_stateid zero_stateid;
 
 /* nfs4super.c */
 struct nfs_mount_info;
-struct dentry *nfs4_try_mount(int, const char *, struct nfs_mount_info *);
-int init_nfs_v4(void);
-void exit_nfs_v4(void);
+extern struct nfs_subversion nfs_v4;
+struct dentry *nfs4_try_mount(int, const char *, struct nfs_mount_info *, struct nfs_subversion *);
+extern bool nfs4_disable_idmapping;
+extern unsigned short max_session_slots;
+extern unsigned short send_implementation_id;
 
 /* nfs4sysctl.c */
 #ifdef CONFIG_SYSCTL
index 1c3f13c8e4728a2de799cc405f49da62858e763a..cbcdfaf325054e215159f2d1c1797994eff050ac 100644 (file)
 
 #define NFSDBG_FACILITY                NFSDBG_CLIENT
 
-/*
- * Turn off NFSv4 uid/gid mapping when using AUTH_SYS
- */
-static bool nfs4_disable_idmapping = true;
-
 /*
  * Get a unique NFSv4.0 callback identifier which will be used
  * by the V4.0 callback service to lookup the nfs_client struct
@@ -357,7 +352,7 @@ static int nfs4_set_client(struct nfs_server *server,
                .hostname = hostname,
                .addr = addr,
                .addrlen = addrlen,
-               .rpc_ops = &nfs_v4_clientops,
+               .nfs_mod = &nfs_v4,
                .proto = proto,
                .minorversion = minorversion,
                .net = net,
@@ -411,7 +406,7 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
        struct nfs_client_initdata cl_init = {
                .addr = ds_addr,
                .addrlen = ds_addrlen,
-               .rpc_ops = &nfs_v4_clientops,
+               .nfs_mod = &nfs_v4,
                .proto = ds_proto,
                .minorversion = mds_clp->cl_minorversion,
                .net = mds_clp->cl_net,
@@ -574,8 +569,10 @@ 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 *nfs4_create_server(const struct nfs_parsed_mount_data *data,
+                                     struct nfs_fh *mntfh)*/
+struct nfs_server *nfs4_create_server(struct nfs_mount_info *mount_info,
+                                     struct nfs_subversion *nfs_mod)
 {
        struct nfs_server *server;
        int error;
@@ -587,11 +584,11 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
                return ERR_PTR(-ENOMEM);
 
        /* set up the general RPC client */
-       error = nfs4_init_server(server, data);
+       error = nfs4_init_server(server, mount_info->parsed);
        if (error < 0)
                goto error;
 
-       error = nfs4_server_common_setup(server, mntfh);
+       error = nfs4_server_common_setup(server, mount_info->mntfh);
        if (error < 0)
                goto error;
 
@@ -657,7 +654,3 @@ error:
        dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
        return ERR_PTR(error);
 }
-
-module_param(nfs4_disable_idmapping, bool, 0644);
-MODULE_PARM_DESC(nfs4_disable_idmapping,
-               "Turn off NFSv4 idmapping when using 'sec=sys'");
index 6843e0a37de8eb900421ae118d76c889afe041ef..a99a8d94872131610ab543d5a06d9f4f541cc2dc 100644 (file)
@@ -72,8 +72,6 @@
 
 #define NFS4_MAX_LOOP_ON_RECOVER (10)
 
-static unsigned short max_session_slots = NFS4_DEF_SLOT_TABLE_SIZE;
-
 struct nfs4_opendata;
 static int _nfs4_proc_open(struct nfs4_opendata *data);
 static int _nfs4_recover_proc_open(struct nfs4_opendata *data);
@@ -6870,6 +6868,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
        .file_ops       = &nfs4_file_operations,
        .getroot        = nfs4_proc_get_root,
        .submount       = nfs4_submount,
+       .try_mount      = nfs4_try_mount,
        .getattr        = nfs4_proc_getattr,
        .setattr        = nfs4_proc_setattr,
        .lookup         = nfs4_proc_lookup,
@@ -6915,6 +6914,8 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
        .alloc_client   = nfs4_alloc_client,
        .init_client    = nfs4_init_client,
        .free_client    = nfs4_free_client,
+       .create_server  = nfs4_create_server,
+       .clone_server   = nfs_clone_server,
 };
 
 static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {
@@ -6929,10 +6930,6 @@ const struct xattr_handler *nfs4_xattr_handlers[] = {
        NULL
 };
 
-module_param(max_session_slots, ushort, 0644);
-MODULE_PARM_DESC(max_session_slots, "Maximum number of outstanding NFSv4.1 "
-               "requests the client will negotiate");
-
 /*
  * Local variables:
  *  c-basic-offset: 8
index 59264fb335c81a13bc3f7975b6325a982e06603a..12a31a9dbcddc562e7f55e65ae4952810dccb3f7 100644 (file)
@@ -6,15 +6,18 @@
 #include <linux/nfs_idmap.h>
 #include <linux/nfs4_mount.h>
 #include <linux/nfs_fs.h>
+#include "delegation.h"
 #include "internal.h"
 #include "nfs4_fs.h"
+#include "pnfs.h"
+#include "nfs.h"
 
 #define NFSDBG_FACILITY                NFSDBG_VFS
 
+static int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc);
+static void nfs4_evict_inode(struct inode *inode);
 static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *raw_data);
-static struct dentry *nfs4_xdev_mount(struct file_system_type *fs_type,
-       int flags, const char *dev_name, void *raw_data);
 static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *raw_data);
 static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type,
@@ -36,14 +39,6 @@ static struct file_system_type nfs4_remote_fs_type = {
        .fs_flags       = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
 };
 
-struct file_system_type nfs4_xdev_fs_type = {
-       .owner          = THIS_MODULE,
-       .name           = "nfs4",
-       .mount          = nfs4_xdev_mount,
-       .kill_sb        = nfs_kill_super,
-       .fs_flags       = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
-};
-
 static struct file_system_type nfs4_remote_referral_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "nfs4",
@@ -75,21 +70,48 @@ static const struct super_operations nfs4_sops = {
        .remount_fs     = nfs_remount,
 };
 
+struct nfs_subversion nfs_v4 = {
+       .owner = THIS_MODULE,
+       .nfs_fs   = &nfs4_fs_type,
+       .rpc_vers = &nfs_version4,
+       .rpc_ops  = &nfs_v4_clientops,
+       .sops     = &nfs4_sops,
+       .xattr    = nfs4_xattr_handlers,
+};
+
+static int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc)
+{
+       int ret = nfs_write_inode(inode, wbc);
+
+       if (ret >= 0 && test_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags)) {
+               int status;
+               bool sync = true;
+
+               if (wbc->sync_mode == WB_SYNC_NONE)
+                       sync = false;
+
+               status = pnfs_layoutcommit_inode(inode, sync);
+               if (status < 0)
+                       return status;
+       }
+       return ret;
+}
+
 /*
- * Set up an NFS4 superblock
+ * Clean out any remaining NFSv4 state that might be left over due
+ * to open() calls that passed nfs_atomic_lookup, but failed to call
+ * nfs_open().
  */
-static void nfs4_fill_super(struct super_block *sb,
-                           struct nfs_mount_info *mount_info)
+static void nfs4_evict_inode(struct inode *inode)
 {
-       sb->s_time_gran = 1;
-       sb->s_op = &nfs4_sops;
-       /*
-        * The VFS shouldn't apply the umask to mode bits. We will do
-        * so ourselves when necessary.
-        */
-       sb->s_flags  |= MS_POSIXACL;
-       sb->s_xattr = nfs4_xattr_handlers;
-       nfs_initialise_sb(sb);
+       truncate_inode_pages(&inode->i_data, 0);
+       clear_inode(inode);
+       pnfs_return_layout(inode);
+       pnfs_destroy_layout(NFS_I(inode));
+       /* If we are holding a delegation, return it! */
+       nfs_inode_return_delegation_noreclaim(inode);
+       /* First call standard NFS clear_inode() code */
+       nfs_clear_inode(inode);
 }
 
 /*
@@ -103,17 +125,16 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags,
        struct nfs_server *server;
        struct dentry *mntroot = ERR_PTR(-ENOMEM);
 
-       mount_info->fill_super = nfs4_fill_super;
        mount_info->set_security = nfs_set_sb_security;
 
        /* Get a volume representation */
-       server = nfs4_create_server(mount_info->parsed, mount_info->mntfh);
+       server = nfs4_create_server(mount_info, &nfs_v4);
        if (IS_ERR(server)) {
                mntroot = ERR_CAST(server);
                goto out;
        }
 
-       mntroot = nfs_fs_mount_common(fs_type, server, flags, dev_name, mount_info);
+       mntroot = nfs_fs_mount_common(server, flags, dev_name, mount_info, &nfs_v4);
 
 out:
        return mntroot;
@@ -228,7 +249,8 @@ static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,
 }
 
 struct dentry *nfs4_try_mount(int flags, const char *dev_name,
-                        struct nfs_mount_info *mount_info)
+                             struct nfs_mount_info *mount_info,
+                             struct nfs_subversion *nfs_mod)
 {
        char *export_path;
        struct vfsmount *root_mnt;
@@ -237,8 +259,6 @@ struct dentry *nfs4_try_mount(int flags, const char *dev_name,
 
        dfprintk(MOUNT, "--> nfs4_try_mount()\n");
 
-       mount_info->fill_super = nfs4_fill_super;
-
        export_path = data->nfs_server.export_path;
        data->nfs_server.export_path = "/";
        root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, mount_info,
@@ -253,27 +273,12 @@ struct dentry *nfs4_try_mount(int flags, const char *dev_name,
        return res;
 }
 
-/*
- * Clone an NFS4 server record on xdev traversal (FSID-change)
- */
-static struct dentry *
-nfs4_xdev_mount(struct file_system_type *fs_type, int flags,
-                const char *dev_name, void *raw_data)
-{
-       struct nfs_mount_info mount_info = {
-               .fill_super = nfs_clone_super,
-               .set_security = nfs_clone_sb_security,
-               .cloned = raw_data,
-       };
-       return nfs_xdev_mount_common(&nfs4_fs_type, flags, dev_name, &mount_info);
-}
-
 static struct dentry *
 nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
                           const char *dev_name, void *raw_data)
 {
        struct nfs_mount_info mount_info = {
-               .fill_super = nfs4_fill_super,
+               .fill_super = nfs_fill_super,
                .set_security = nfs_clone_sb_security,
                .cloned = raw_data,
        };
@@ -293,7 +298,7 @@ nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
                goto out;
        }
 
-       mntroot = nfs_fs_mount_common(&nfs4_fs_type, server, flags, dev_name, &mount_info);
+       mntroot = nfs_fs_mount_common(server, flags, dev_name, &mount_info, &nfs_v4);
 out:
        nfs_free_fhandle(mount_info.mntfh);
        return mntroot;
@@ -327,7 +332,7 @@ static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
 }
 
 
-int __init init_nfs_v4(void)
+static int __init init_nfs_v4(void)
 {
        int err;
 
@@ -343,6 +348,7 @@ int __init init_nfs_v4(void)
        if (err < 0)
                goto out2;
 
+       register_nfs_version(&nfs_v4);
        return 0;
 out2:
        nfs4_unregister_sysctl();
@@ -352,9 +358,15 @@ out:
        return err;
 }
 
-void exit_nfs_v4(void)
+static void __exit exit_nfs_v4(void)
 {
+       unregister_nfs_version(&nfs_v4);
        unregister_filesystem(&nfs4_fs_type);
        nfs4_unregister_sysctl();
        nfs_idmap_quit();
 }
+
+MODULE_LICENSE("GPL");
+
+module_init(init_nfs_v4);
+module_exit(exit_nfs_v4);
index 6cbd602e26d5c1c04b809143d1600914564881a6..ca13483edd60aee67c8e1673b18250959187f8a4 100644 (file)
@@ -852,12 +852,6 @@ const u32 nfs41_maxread_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
                                    XDR_UNIT);
 #endif /* CONFIG_NFS_V4_1 */
 
-static unsigned short send_implementation_id = 1;
-
-module_param(send_implementation_id, ushort, 0644);
-MODULE_PARM_DESC(send_implementation_id,
-               "Send implementation ID with NFSv4.1 exchange_id");
-
 static const umode_t nfs_type2fmt[] = {
        [NF4BAD] = 0,
        [NF4REG] = S_IFREG,
index aed913c833f422bbf6a88e2726be5eec6d9bbc40..1e7d8879dae6289b94d206071d95d49a780c7699 100644 (file)
@@ -54,6 +54,7 @@ void nfs_pgheader_init(struct nfs_pageio_descriptor *desc,
        if (hdr->completion_ops->init_hdr)
                hdr->completion_ops->init_hdr(hdr);
 }
+EXPORT_SYMBOL_GPL(nfs_pgheader_init);
 
 void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos)
 {
@@ -268,6 +269,7 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
        desc->pg_lseg = NULL;
        desc->pg_dreq = NULL;
 }
+EXPORT_SYMBOL_GPL(nfs_pageio_init);
 
 /**
  * nfs_can_coalesce_requests - test two requests for compatibility
@@ -409,6 +411,7 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
        } while (ret);
        return ret;
 }
+EXPORT_SYMBOL_GPL(nfs_pageio_add_request);
 
 /**
  * nfs_pageio_complete - Complete I/O on an nfs_pageio_descriptor
@@ -424,6 +427,7 @@ void nfs_pageio_complete(struct nfs_pageio_descriptor *desc)
                        break;
        }
 }
+EXPORT_SYMBOL_GPL(nfs_pageio_complete);
 
 /**
  * nfs_pageio_cond_complete - Conditional I/O completion
index 7fbd25afe418af4b749a78febb78b125cdf1fe07..76875bfcf19ceda4a54cb0dde14466a304191cf9 100644 (file)
@@ -1407,6 +1407,7 @@ static void pnfs_writehdr_free(struct nfs_pgio_header *hdr)
        put_lseg(hdr->lseg);
        nfs_writehdr_free(hdr);
 }
+EXPORT_SYMBOL_GPL(pnfs_writehdr_free);
 
 int
 pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
@@ -1561,6 +1562,7 @@ static void pnfs_readhdr_free(struct nfs_pgio_header *hdr)
        put_lseg(hdr->lseg);
        nfs_readhdr_free(hdr);
 }
+EXPORT_SYMBOL_GPL(pnfs_readhdr_free);
 
 int
 pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
index 4d3356af330975b38491d89e6ea32bb37cda5523..50a88c3546ed9eebdee4c4755ca5b7f6d35489f0 100644 (file)
@@ -774,6 +774,7 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
        .file_ops       = &nfs_file_operations,
        .getroot        = nfs_proc_get_root,
        .submount       = nfs_submount,
+       .try_mount      = nfs_try_mount,
        .getattr        = nfs_proc_getattr,
        .setattr        = nfs_proc_setattr,
        .lookup         = nfs_proc_lookup,
@@ -816,4 +817,6 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
        .alloc_client   = nfs_alloc_client,
        .init_client    = nfs_init_client,
        .free_client    = nfs_free_client,
+       .create_server  = nfs_create_server,
+       .clone_server   = nfs_clone_server,
 };
index 6267b873bbcbc8f4b13ec887a29d5e5cdbae06d6..6935e401ad76972436b894e12f2ca45932c9c694 100644 (file)
@@ -48,6 +48,7 @@ struct nfs_read_header *nfs_readhdr_alloc(void)
        }
        return rhdr;
 }
+EXPORT_SYMBOL_GPL(nfs_readhdr_alloc);
 
 static struct nfs_read_data *nfs_readdata_alloc(struct nfs_pgio_header *hdr,
                                                unsigned int pagecount)
@@ -80,6 +81,7 @@ void nfs_readhdr_free(struct nfs_pgio_header *hdr)
 
        kmem_cache_free(nfs_rdata_cachep, rhdr);
 }
+EXPORT_SYMBOL_GPL(nfs_readhdr_free);
 
 void nfs_readdata_release(struct nfs_read_data *rdata)
 {
@@ -96,6 +98,7 @@ void nfs_readdata_release(struct nfs_read_data *rdata)
        if (atomic_dec_and_test(&hdr->refcnt))
                hdr->completion_ops->completion(hdr);
 }
+EXPORT_SYMBOL_GPL(nfs_readdata_release);
 
 static
 int nfs_return_empty_page(struct page *page)
@@ -113,6 +116,7 @@ void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
        nfs_pageio_init(pgio, inode, &nfs_pageio_read_ops, compl_ops,
                        NFS_SERVER(inode)->rsize, 0);
 }
+EXPORT_SYMBOL_GPL(nfs_pageio_init_read);
 
 void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio)
 {
@@ -397,6 +401,7 @@ int nfs_generic_pagein(struct nfs_pageio_descriptor *desc,
                return nfs_pagein_multi(desc, hdr);
        return nfs_pagein_one(desc, hdr);
 }
+EXPORT_SYMBOL_GPL(nfs_generic_pagein);
 
 static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
 {
index 95866a8c21bb5e651e7ba9c01e9d45c9dcb92c79..ac6a3c55dce408afbd5348a2f9af42a7f78e660e 100644 (file)
 #include "internal.h"
 #include "fscache.h"
 #include "pnfs.h"
+#include "nfs.h"
 
 #define NFSDBG_FACILITY                NFSDBG_VFS
 #define NFS_TEXT_DATA          1
 
-#ifdef CONFIG_NFS_V3
+#if IS_ENABLED(CONFIG_NFS_V3)
 #define NFS_DEFAULT_VERSION 3
 #else
 #define NFS_DEFAULT_VERSION 2
@@ -281,13 +282,14 @@ static match_table_t nfs_vers_tokens = {
 static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type,
                int flags, const char *dev_name, void *raw_data);
 
-static struct file_system_type nfs_fs_type = {
+struct file_system_type nfs_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "nfs",
        .mount          = nfs_fs_mount,
        .kill_sb        = nfs_kill_super,
        .fs_flags       = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
 };
+EXPORT_SYMBOL_GPL(nfs_fs_type);
 
 struct file_system_type nfs_xdev_fs_type = {
        .owner          = THIS_MODULE,
@@ -297,7 +299,7 @@ struct file_system_type nfs_xdev_fs_type = {
        .fs_flags       = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
 };
 
-static const struct super_operations nfs_sops = {
+const struct super_operations nfs_sops = {
        .alloc_inode    = nfs_alloc_inode,
        .destroy_inode  = nfs_destroy_inode,
        .write_inode    = nfs_write_inode,
@@ -311,8 +313,9 @@ static const struct super_operations nfs_sops = {
        .show_stats     = nfs_show_stats,
        .remount_fs     = nfs_remount,
 };
+EXPORT_SYMBOL_GPL(nfs_sops);
 
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *);
 static int nfs4_validate_mount_data(void *options,
        struct nfs_parsed_mount_data *args, const char *dev_name);
@@ -363,6 +366,7 @@ void nfs_sb_active(struct super_block *sb)
        if (atomic_inc_return(&server->active) == 1)
                atomic_inc(&sb->s_active);
 }
+EXPORT_SYMBOL_GPL(nfs_sb_active);
 
 void nfs_sb_deactive(struct super_block *sb)
 {
@@ -371,6 +375,7 @@ void nfs_sb_deactive(struct super_block *sb)
        if (atomic_dec_and_test(&server->active))
                deactivate_super(sb);
 }
+EXPORT_SYMBOL_GPL(nfs_sb_deactive);
 
 /*
  * Deliver file system statistics to userspace
@@ -436,6 +441,7 @@ int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
        dprintk("%s: statfs error = %d\n", __func__, -error);
        return error;
 }
+EXPORT_SYMBOL_GPL(nfs_statfs);
 
 /*
  * Map the security flavour number to a name
@@ -541,7 +547,7 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
        nfs_show_mountd_netid(m, nfss, showdefaults);
 }
 
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss,
                                    int showdefaults)
 {
@@ -672,8 +678,9 @@ int nfs_show_options(struct seq_file *m, struct dentry *root)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(nfs_show_options);
 
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 #ifdef CONFIG_NFS_V4_1
 static void show_sessions(struct seq_file *m, struct nfs_server *server)
 {
@@ -706,7 +713,7 @@ static void show_implementation_id(struct seq_file *m, struct nfs_server *nfss)
        }
 }
 #else
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 static void show_pnfs(struct seq_file *m, struct nfs_server *server)
 {
 }
@@ -731,12 +738,14 @@ int nfs_show_devname(struct seq_file *m, struct dentry *root)
        free_page((unsigned long)page);
        return err;
 }
+EXPORT_SYMBOL_GPL(nfs_show_devname);
 
 int nfs_show_path(struct seq_file *m, struct dentry *dentry)
 {
        seq_puts(m, "/");
        return 0;
 }
+EXPORT_SYMBOL_GPL(nfs_show_path);
 
 /*
  * Present statistical information for this VFS mountpoint
@@ -771,7 +780,7 @@ int nfs_show_stats(struct seq_file *m, struct dentry *root)
        seq_printf(m, ",bsize=%u", nfss->bsize);
        seq_printf(m, ",namlen=%u", nfss->namelen);
 
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
        if (nfss->nfs_client->rpc_ops->version == 4) {
                seq_printf(m, "\n\tnfsv4:\t");
                seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]);
@@ -829,6 +838,7 @@ int nfs_show_stats(struct seq_file *m, struct dentry *root)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(nfs_show_stats);
 
 /*
  * Begin unmount by attempting to remove all automounted mountpoints we added
@@ -848,6 +858,7 @@ void nfs_umount_begin(struct super_block *sb)
        if (!IS_ERR(rpc))
                rpc_killall_tasks(rpc);
 }
+EXPORT_SYMBOL_GPL(nfs_umount_begin);
 
 static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(void)
 {
@@ -1649,8 +1660,9 @@ static int nfs_request_mount(struct nfs_parsed_mount_data *args,
        return nfs_walk_authlist(args, &request);
 }
 
-static struct dentry *nfs_try_mount(int flags, const char *dev_name,
-                                   struct nfs_mount_info *mount_info)
+struct dentry *nfs_try_mount(int flags, const char *dev_name,
+                            struct nfs_mount_info *mount_info,
+                            struct nfs_subversion *nfs_mod)
 {
        int status;
        struct nfs_server *server;
@@ -1662,12 +1674,13 @@ static struct dentry *nfs_try_mount(int flags, const char *dev_name,
        }
 
        /* Get a volume representation */
-       server = nfs_create_server(mount_info->parsed, mount_info->mntfh);
+       server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod);
        if (IS_ERR(server))
                return ERR_CAST(server);
 
-       return nfs_fs_mount_common(&nfs_fs_type, server, flags, dev_name, mount_info);
+       return nfs_fs_mount_common(server, flags, dev_name, mount_info, nfs_mod);
 }
+EXPORT_SYMBOL_GPL(nfs_try_mount);
 
 /*
  * Split "dev_name" into "hostname:export_path".
@@ -1871,7 +1884,7 @@ static int nfs23_validate_mount_data(void *options,
                return NFS_TEXT_DATA;
        }
 
-#ifndef CONFIG_NFS_V3
+#if !IS_ENABLED(CONFIG_NFS_V3)
        if (args->version == 3)
                goto out_v3_not_compiled;
 #endif /* !CONFIG_NFS_V3 */
@@ -1891,7 +1904,7 @@ out_no_sec:
        dfprintk(MOUNT, "NFS: nfs_mount_data version supports only AUTH_SYS\n");
        return -EINVAL;
 
-#ifndef CONFIG_NFS_V3
+#if !IS_ENABLED(CONFIG_NFS_V3)
 out_v3_not_compiled:
        dfprintk(MOUNT, "NFS: NFSv3 is not compiled into kernel\n");
        return -EPROTONOSUPPORT;
@@ -1910,7 +1923,7 @@ out_invalid_fh:
        return -EINVAL;
 }
 
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 static int nfs_validate_mount_data(struct file_system_type *fs_type,
                                   void *options,
                                   struct nfs_parsed_mount_data *args,
@@ -1948,7 +1961,7 @@ static int nfs_validate_text_mount_data(void *options,
                goto out_no_address;
 
        if (args->version == 4) {
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
                port = NFS_PORT;
                max_namelen = NFS4_MAXNAMLEN;
                max_pathlen = NFS4_MAXPATHLEN;
@@ -1971,7 +1984,7 @@ static int nfs_validate_text_mount_data(void *options,
                                   &args->nfs_server.export_path,
                                   max_pathlen);
 
-#ifndef CONFIG_NFS_V4
+#if !IS_ENABLED(CONFIG_NFS_V4)
 out_v4_not_compiled:
        dfprintk(MOUNT, "NFS: NFSv4 is not compiled into kernel\n");
        return -EPROTONOSUPPORT;
@@ -2070,6 +2083,7 @@ out:
        kfree(data);
        return error;
 }
+EXPORT_SYMBOL_GPL(nfs_remount);
 
 /*
  * Initialise the common bits of the superblock
@@ -2103,10 +2117,12 @@ void nfs_fill_super(struct super_block *sb, struct nfs_mount_info *mount_info)
 
        sb->s_blocksize_bits = 0;
        sb->s_blocksize = 0;
-       if (data->bsize)
+       sb->s_xattr = server->nfs_client->cl_nfs_mod->xattr;
+       sb->s_op = server->nfs_client->cl_nfs_mod->sops;
+       if (data && data->bsize)
                sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits);
 
-       if (server->nfs_client->rpc_ops->version == 3) {
+       if (server->nfs_client->rpc_ops->version != 2) {
                /* The VFS shouldn't apply the umask to mode bits. We will do
                 * so ourselves when necessary.
                 */
@@ -2114,9 +2130,9 @@ void nfs_fill_super(struct super_block *sb, struct nfs_mount_info *mount_info)
                sb->s_time_gran = 1;
        }
 
-       sb->s_op = &nfs_sops;
        nfs_initialise_sb(sb);
 }
+EXPORT_SYMBOL_GPL(nfs_fill_super);
 
 /*
  * Finish setting up a cloned NFS2/3/4 superblock
@@ -2286,6 +2302,7 @@ int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot,
 {
        return security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts);
 }
+EXPORT_SYMBOL_GPL(nfs_set_sb_security);
 
 int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot,
                          struct nfs_mount_info *mount_info)
@@ -2296,11 +2313,12 @@ int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot,
                return -ESTALE;
        return 0;
 }
+EXPORT_SYMBOL_GPL(nfs_clone_sb_security);
 
-struct dentry *nfs_fs_mount_common(struct file_system_type *fs_type,
-                                  struct nfs_server *server,
+struct dentry *nfs_fs_mount_common(struct nfs_server *server,
                                   int flags, const char *dev_name,
-                                  struct nfs_mount_info *mount_info)
+                                  struct nfs_mount_info *mount_info,
+                                  struct nfs_subversion *nfs_mod)
 {
        struct super_block *s;
        struct dentry *mntroot = ERR_PTR(-ENOMEM);
@@ -2319,7 +2337,7 @@ struct dentry *nfs_fs_mount_common(struct file_system_type *fs_type,
                sb_mntdata.mntflags |= MS_SYNCHRONOUS;
 
        /* Get a superblock - note that we may end up sharing one that already exists */
-       s = sget(fs_type, compare_super, nfs_set_super, flags, &sb_mntdata);
+       s = sget(nfs_mod->nfs_fs, compare_super, nfs_set_super, flags, &sb_mntdata);
        if (IS_ERR(s)) {
                mntroot = ERR_CAST(s);
                goto out_err_nosb;
@@ -2369,6 +2387,7 @@ error_splat_bdi:
        deactivate_locked_super(s);
        goto out;
 }
+EXPORT_SYMBOL_GPL(nfs_fs_mount_common);
 
 struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *raw_data)
@@ -2378,6 +2397,7 @@ struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
                .set_security = nfs_set_sb_security,
        };
        struct dentry *mntroot = ERR_PTR(-ENOMEM);
+       struct nfs_subversion *nfs_mod;
        int error;
 
        mount_info.parsed = nfs_alloc_parsed_mount_data();
@@ -2394,18 +2414,21 @@ struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
                goto out;
        }
 
-#ifdef CONFIG_NFS_V4
-       if (mount_info.parsed->version == 4)
-               mntroot = nfs4_try_mount(flags, dev_name, &mount_info);
-       else
-#endif /* CONFIG_NFS_V4 */
-               mntroot = nfs_try_mount(flags, dev_name, &mount_info);
+       nfs_mod = get_nfs_version(mount_info.parsed->version);
+       if (IS_ERR(nfs_mod)) {
+               mntroot = ERR_CAST(nfs_mod);
+               goto out;
+       }
 
+       mntroot = nfs_mod->rpc_ops->try_mount(flags, dev_name, &mount_info, nfs_mod);
+
+       put_nfs_version(nfs_mod);
 out:
        nfs_free_parsed_mount_data(mount_info.parsed);
        nfs_free_fhandle(mount_info.mntfh);
        return mntroot;
 }
+EXPORT_SYMBOL_GPL(nfs_fs_mount);
 
 /*
  * Ensure that we unregister the bdi before kill_anon_super
@@ -2417,6 +2440,7 @@ void nfs_put_super(struct super_block *s)
 
        bdi_unregister(&server->backing_dev_info);
 }
+EXPORT_SYMBOL_GPL(nfs_put_super);
 
 /*
  * Destroy an NFS2/3 superblock
@@ -2429,31 +2453,38 @@ void nfs_kill_super(struct super_block *s)
        nfs_fscache_release_super_cookie(s);
        nfs_free_server(server);
 }
+EXPORT_SYMBOL_GPL(nfs_kill_super);
 
 /*
  * Clone an NFS2/3/4 server record on xdev traversal (FSID-change)
  */
 struct dentry *
-nfs_xdev_mount_common(struct file_system_type *fs_type, int flags,
-               const char *dev_name, struct nfs_mount_info *mount_info)
+nfs_xdev_mount(struct file_system_type *fs_type, int flags,
+               const char *dev_name, void *raw_data)
 {
-       struct nfs_clone_mount *data = mount_info->cloned;
+       struct nfs_clone_mount *data = raw_data;
+       struct nfs_mount_info mount_info = {
+               .fill_super = nfs_clone_super,
+               .set_security = nfs_clone_sb_security,
+               .cloned = data,
+       };
        struct nfs_server *server;
        struct dentry *mntroot = ERR_PTR(-ENOMEM);
+       struct nfs_subversion *nfs_mod = NFS_SB(data->sb)->nfs_client->cl_nfs_mod;
        int error;
 
        dprintk("--> nfs_xdev_mount_common()\n");
 
-       mount_info->mntfh = data->fh;
+       mount_info.mntfh = mount_info.cloned->fh;
 
        /* create a new volume representation */
-       server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor);
+       server = nfs_mod->rpc_ops->clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor);
        if (IS_ERR(server)) {
                error = PTR_ERR(server);
                goto out_err;
        }
 
-       mntroot = nfs_fs_mount_common(fs_type, server, flags, dev_name, mount_info);
+       mntroot = nfs_fs_mount_common(server, flags, dev_name, &mount_info, nfs_mod);
        dprintk("<-- nfs_xdev_mount_common() = 0\n");
 out:
        return mntroot;
@@ -2463,22 +2494,7 @@ out_err:
        goto out;
 }
 
-/*
- * Clone an NFS2/3 server record on xdev traversal (FSID-change)
- */
-static struct dentry *
-nfs_xdev_mount(struct file_system_type *fs_type, int flags,
-               const char *dev_name, void *raw_data)
-{
-       struct nfs_mount_info mount_info = {
-               .fill_super = nfs_clone_super,
-               .set_security = nfs_clone_sb_security,
-               .cloned   = raw_data,
-       };
-       return nfs_xdev_mount_common(&nfs_fs_type, flags, dev_name, &mount_info);
-}
-
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 
 static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args)
 {
@@ -2577,4 +2593,56 @@ out_no_address:
        return -EINVAL;
 }
 
+/*
+ * NFS v4 module parameters need to stay in the
+ * NFS client for backwards compatibility
+ */
+unsigned int nfs_callback_set_tcpport;
+unsigned short nfs_callback_tcpport;
+/* Default cache timeout is 10 minutes */
+unsigned int nfs_idmap_cache_timeout = 600;
+/* Turn off NFSv4 uid/gid mapping when using AUTH_SYS */
+bool nfs4_disable_idmapping = true;
+unsigned short max_session_slots = NFS4_DEF_SLOT_TABLE_SIZE;
+unsigned short send_implementation_id = 1;
+
+EXPORT_SYMBOL_GPL(nfs_callback_set_tcpport);
+EXPORT_SYMBOL_GPL(nfs_callback_tcpport);
+EXPORT_SYMBOL_GPL(nfs_idmap_cache_timeout);
+EXPORT_SYMBOL_GPL(nfs4_disable_idmapping);
+EXPORT_SYMBOL_GPL(max_session_slots);
+EXPORT_SYMBOL_GPL(send_implementation_id);
+
+#define NFS_CALLBACK_MAXPORTNR (65535U)
+
+static int param_set_portnr(const char *val, const struct kernel_param *kp)
+{
+       unsigned long num;
+       int ret;
+
+       if (!val)
+               return -EINVAL;
+       ret = strict_strtoul(val, 0, &num);
+       if (ret == -EINVAL || num > NFS_CALLBACK_MAXPORTNR)
+               return -EINVAL;
+       *((unsigned int *)kp->arg) = num;
+       return 0;
+}
+static struct kernel_param_ops param_ops_portnr = {
+       .set = param_set_portnr,
+       .get = param_get_uint,
+};
+#define param_check_portnr(name, p) __param_check(name, p, unsigned int);
+
+module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644);
+module_param(nfs_idmap_cache_timeout, int, 0644);
+module_param(nfs4_disable_idmapping, bool, 0644);
+MODULE_PARM_DESC(nfs4_disable_idmapping,
+               "Turn off NFSv4 idmapping when using 'sec=sys'");
+module_param(max_session_slots, ushort, 0644);
+MODULE_PARM_DESC(max_session_slots, "Maximum number of outstanding NFSv4.1 "
+               "requests the client will negotiate");
+module_param(send_implementation_id, ushort, 0644);
+MODULE_PARM_DESC(send_implementation_id,
+               "Send implementation ID with NFSv4.1 exchange_id");
 #endif /* CONFIG_NFS_V4 */
index f312860c15d0e7ce5e9b9e8b2254ce41387edbf3..e4a2ad2059bddd636f011e863a13f55a322dbb8c 100644 (file)
@@ -84,6 +84,7 @@ struct nfs_write_header *nfs_writehdr_alloc(void)
        }
        return p;
 }
+EXPORT_SYMBOL_GPL(nfs_writehdr_alloc);
 
 static struct nfs_write_data *nfs_writedata_alloc(struct nfs_pgio_header *hdr,
                                                  unsigned int pagecount)
@@ -115,6 +116,7 @@ void nfs_writehdr_free(struct nfs_pgio_header *hdr)
        struct nfs_write_header *whdr = container_of(hdr, struct nfs_write_header, header);
        mempool_free(whdr, nfs_wdata_mempool);
 }
+EXPORT_SYMBOL_GPL(nfs_writehdr_free);
 
 void nfs_writedata_release(struct nfs_write_data *wdata)
 {
@@ -131,6 +133,7 @@ void nfs_writedata_release(struct nfs_write_data *wdata)
        if (atomic_dec_and_test(&hdr->refcnt))
                hdr->completion_ops->completion(hdr);
 }
+EXPORT_SYMBOL_GPL(nfs_writedata_release);
 
 static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error)
 {
@@ -446,7 +449,7 @@ nfs_mark_request_dirty(struct nfs_page *req)
        __set_page_dirty_nobuffers(req->wb_page);
 }
 
-#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
 /**
  * nfs_request_add_commit_list - add request to a commit list
  * @req: pointer to a struct nfs_page
@@ -636,7 +639,7 @@ out:
        hdr->release(hdr);
 }
 
-#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+#if  IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
 static unsigned long
 nfs_reqs_to_commit(struct nfs_commit_info *cinfo)
 {
@@ -1173,6 +1176,7 @@ int nfs_generic_flush(struct nfs_pageio_descriptor *desc,
                return nfs_flush_multi(desc, hdr);
        return nfs_flush_one(desc, hdr);
 }
+EXPORT_SYMBOL_GPL(nfs_generic_flush);
 
 static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
 {
@@ -1210,6 +1214,7 @@ void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
        nfs_pageio_init(pgio, inode, &nfs_pageio_write_ops, compl_ops,
                                NFS_SERVER(inode)->wsize, ioflags);
 }
+EXPORT_SYMBOL_GPL(nfs_pageio_init_write);
 
 void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio)
 {
@@ -1297,7 +1302,7 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
                return;
        nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, resp->count);
 
-#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
        if (resp->verf->committed < argp->stable && task->tk_status >= 0) {
                /* We tried a write call, but the server did not
                 * commit data to stable storage even though we
@@ -1357,7 +1362,7 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
 }
 
 
-#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
 static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait)
 {
        int ret;
@@ -1673,26 +1678,7 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
        return nfs_commit_unstable_pages(inode, wbc);
 }
-
-#ifdef CONFIG_NFS_V4
-int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc)
-{
-       int ret = nfs_write_inode(inode, wbc);
-
-       if (ret >= 0 && test_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags)) {
-               int status;
-               bool sync = true;
-
-               if (wbc->sync_mode == WB_SYNC_NONE)
-                       sync = false;
-
-               status = pnfs_layoutcommit_inode(inode, sync);
-               if (status < 0)
-                       return status;
-       }
-       return ret;
-}
-#endif
+EXPORT_SYMBOL_GPL(nfs_write_inode);
 
 /*
  * flush the inode to disk.
@@ -1708,6 +1694,7 @@ int nfs_wb_all(struct inode *inode)
 
        return sync_inode(inode, &wbc);
 }
+EXPORT_SYMBOL_GPL(nfs_wb_all);
 
 int nfs_wb_page_cancel(struct inode *inode, struct page *page)
 {
index 4b6043c20f7745be854b6fd95ba3fbd8fc450ec3..2889877318bca10ddec8beb9407cb6634278210b 100644 (file)
@@ -191,7 +191,7 @@ struct nfs_inode {
        struct hlist_head       silly_list;
        wait_queue_head_t       waitqueue;
 
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
        struct nfs4_cached_acl  *nfs4_acl;
         /* NFSv4 state */
        struct list_head        open_states;
@@ -428,7 +428,7 @@ extern __be32 root_nfs_parse_addr(char *name); /*__init*/
  * linux/fs/nfs/file.c
  */
 extern const struct file_operations nfs_file_operations;
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 extern const struct file_operations nfs4_file_operations;
 #endif /* CONFIG_NFS_V4 */
 extern const struct address_space_operations nfs_file_aops;
@@ -538,7 +538,7 @@ extern void nfs_writeback_done(struct rpc_task *, struct nfs_write_data *);
 extern int nfs_wb_all(struct inode *inode);
 extern int nfs_wb_page(struct inode *inode, struct page* page);
 extern int nfs_wb_page_cancel(struct inode *inode, struct page* page);
-#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
 extern int  nfs_commit_inode(struct inode *, int);
 extern struct nfs_commit_data *nfs_commitdata_alloc(void);
 extern void nfs_commit_free(struct nfs_commit_data *data);
index 65327652c61a7941d043c5fe1058cba160299d1c..310c63c8ab2cd374ff4d78c526359241cb4758cc 100644 (file)
@@ -48,11 +48,12 @@ struct nfs_client {
        struct rpc_clnt *       cl_rpcclient;
        const struct nfs_rpc_ops *rpc_ops;      /* NFS protocol vector */
        int                     cl_proto;       /* Network transport protocol */
+       struct nfs_subversion * cl_nfs_mod;     /* pointer to nfs version module */
 
        u32                     cl_minorversion;/* NFSv4 minorversion */
        struct rpc_cred         *cl_machine_cred;
 
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
        u64                     cl_clientid;    /* constant */
        nfs4_verifier           cl_confirm;     /* Clientid verifier */
        unsigned long           cl_state;
@@ -137,7 +138,7 @@ struct nfs_server {
 #endif
 
        u32                     pnfs_blksize;   /* layout_blksize attr */
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
        u32                     attr_bitmask[3];/* V4 bitmask representing the set
                                                   of attributes supported on this
                                                   filesystem */
@@ -200,7 +201,7 @@ struct nfs_server {
 #define NFS4_MAX_SLOT_TABLE (256U)
 #define NFS4_NO_SLOT ((u32)-1)
 
-#if defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V4)
 
 /* Sessions */
 #define SLOT_TABLE_SZ DIV_ROUND_UP(NFS4_MAX_SLOT_TABLE, 8*sizeof(long))
index 7eed2012d288926a6317e53ead4eb7880796c7ca..ece91c57ad79d109c2c95c30d64f390201db0822 100644 (file)
@@ -69,7 +69,7 @@ struct nfs_server;
 struct nfs_fattr;
 struct nfs4_string;
 
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 int nfs_idmap_init(void);
 void nfs_idmap_quit(void);
 #else
index 0e181c2320b7796bc9ed41cb3ebfc4c56a885339..00485e084394d4ca1a5782b3cd54fc63e9b06acd 100644 (file)
@@ -824,7 +824,7 @@ struct nfs3_getaclres {
        struct posix_acl *      acl_default;
 };
 
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 
 typedef u64 clientid4;
 
@@ -1353,6 +1353,8 @@ struct nfs_renamedata {
 struct nfs_access_entry;
 struct nfs_client;
 struct rpc_timeout;
+struct nfs_subversion;
+struct nfs_mount_info;
 struct nfs_client_initdata;
 struct nfs_pageio_descriptor;
 
@@ -1370,6 +1372,8 @@ struct nfs_rpc_ops {
                            struct nfs_fsinfo *);
        struct vfsmount *(*submount) (struct nfs_server *, struct dentry *,
                                      struct nfs_fh *, struct nfs_fattr *);
+       struct dentry *(*try_mount) (int, const char *, struct nfs_mount_info *,
+                                    struct nfs_subversion *);
        int     (*getattr) (struct nfs_server *, struct nfs_fh *,
                            struct nfs_fattr *);
        int     (*setattr) (struct dentry *, struct nfs_fattr *,
@@ -1435,6 +1439,9 @@ struct nfs_rpc_ops {
                (*init_client) (struct nfs_client *, const struct rpc_timeout *,
                                const char *, rpc_authflavor_t);
        void    (*free_client) (struct nfs_client *);
+       struct nfs_server *(*create_server)(struct nfs_mount_info *, struct nfs_subversion *);
+       struct nfs_server *(*clone_server)(struct nfs_server *, struct nfs_fh *,
+                                          struct nfs_fattr *, rpc_authflavor_t);
 };
 
 /*
index 92509ffe15fcacce5de331cbb205a84c4f718a86..a70acae496e44d6c872ba7c93d4d9ce56c2f7f00 100644 (file)
@@ -251,7 +251,7 @@ static int rpcb_create_local_unix(struct net *net)
        if (IS_ERR(clnt)) {
                dprintk("RPC:       failed to create AF_LOCAL rpcbind "
                                "client (errno %ld).\n", PTR_ERR(clnt));
-               result = -PTR_ERR(clnt);
+               result = PTR_ERR(clnt);
                goto out;
        }
 
@@ -298,7 +298,7 @@ static int rpcb_create_local_net(struct net *net)
        if (IS_ERR(clnt)) {
                dprintk("RPC:       failed to create local rpcbind "
                                "client (errno %ld).\n", PTR_ERR(clnt));
-               result = -PTR_ERR(clnt);
+               result = PTR_ERR(clnt);
                goto out;
        }
 
index 994cfea2bad66f814432c2fcbb1227d0a321d34f..1f19aa15f89b988d0e0480156f1ef7708cfc11d2 100644 (file)
@@ -300,8 +300,9 @@ EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task);
 /*
  * Make an RPC task runnable.
  *
- * Note: If the task is ASYNC, this must be called with
- * the spinlock held to protect the wait queue operation.
+ * Note: If the task is ASYNC, and is being made runnable after sitting on an
+ * rpc_wait_queue, this must be called with the queue spinlock held to protect
+ * the wait queue operation.
  */
 static void rpc_make_runnable(struct rpc_task *task)
 {
@@ -790,7 +791,9 @@ void rpc_execute(struct rpc_task *task)
 
 static void rpc_async_schedule(struct work_struct *work)
 {
+       current->flags |= PF_FSTRANS;
        __rpc_execute(container_of(work, struct rpc_task, u.tk_work));
+       current->flags &= ~PF_FSTRANS;
 }
 
 /**
index b446e100286f7aca96f81ca10d6cb176471d55d5..06cdbff79e4af433d5a4ea3a2766d6d09a9b5a01 100644 (file)
@@ -200,6 +200,7 @@ xprt_rdma_connect_worker(struct work_struct *work)
        int rc = 0;
 
        if (!xprt->shutdown) {
+               current->flags |= PF_FSTRANS;
                xprt_clear_connected(xprt);
 
                dprintk("RPC:       %s: %sconnect\n", __func__,
@@ -212,10 +213,10 @@ xprt_rdma_connect_worker(struct work_struct *work)
 
 out:
        xprt_wake_pending_tasks(xprt, rc);
-
 out_clear:
        dprintk("RPC:       %s: exit\n", __func__);
        xprt_clear_connecting(xprt);
+       current->flags &= ~PF_FSTRANS;
 }
 
 /*
index 62d0dac8f7807f9fbfbe3fbc10315e5386197b89..926679459e7179758b91eaf6caf6bcfe5b3c0f98 100644 (file)
@@ -1892,6 +1892,8 @@ static void xs_local_setup_socket(struct work_struct *work)
        if (xprt->shutdown)
                goto out;
 
+       current->flags |= PF_FSTRANS;
+
        clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
        status = __sock_create(xprt->xprt_net, AF_LOCAL,
                                        SOCK_STREAM, 0, &sock, 1);
@@ -1925,6 +1927,7 @@ static void xs_local_setup_socket(struct work_struct *work)
 out:
        xprt_clear_connecting(xprt);
        xprt_wake_pending_tasks(xprt, status);
+       current->flags &= ~PF_FSTRANS;
 }
 
 static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
@@ -1967,6 +1970,8 @@ static void xs_udp_setup_socket(struct work_struct *work)
        if (xprt->shutdown)
                goto out;
 
+       current->flags |= PF_FSTRANS;
+
        /* Start by resetting any existing state */
        xs_reset_transport(transport);
        sock = xs_create_sock(xprt, transport,
@@ -1985,6 +1990,7 @@ static void xs_udp_setup_socket(struct work_struct *work)
 out:
        xprt_clear_connecting(xprt);
        xprt_wake_pending_tasks(xprt, status);
+       current->flags &= ~PF_FSTRANS;
 }
 
 /*
@@ -2110,6 +2116,8 @@ static void xs_tcp_setup_socket(struct work_struct *work)
        if (xprt->shutdown)
                goto out;
 
+       current->flags |= PF_FSTRANS;
+
        if (!sock) {
                clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
                sock = xs_create_sock(xprt, transport,
@@ -2159,6 +2167,7 @@ static void xs_tcp_setup_socket(struct work_struct *work)
        case -EINPROGRESS:
        case -EALREADY:
                xprt_clear_connecting(xprt);
+               current->flags &= ~PF_FSTRANS;
                return;
        case -EINVAL:
                /* Happens, for instance, if the user specified a link
@@ -2171,6 +2180,7 @@ out_eagain:
 out:
        xprt_clear_connecting(xprt);
        xprt_wake_pending_tasks(xprt, status);
+       current->flags &= ~PF_FSTRANS;
 }
 
 /**