2012-03-21 15:21:12

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 00/23] NFS: Create NFS Modules

From: Bryan Schumaker <[email protected]>

This patch series turns NFS v2, v3 and v4 into loadable kernel modules that
are requested before using. This should eventually help clean up all of
the NFS code by giving us a chance to remove most of the ifdefs that check
for CONFIG_NFS_V3 and CONFIG_NFS_V4.

I have tried to move as little code as possible while making these patches
since version specific code can be moved later once the basic framework has
been merged and tested. I still had to move a large chunk of code out of
super.c and into nfs4super.c, but the other files are mostly untouched.


Initial size (without v4.1):
584 nfs.ko (without v4.1)

Final sizes (without v4.1):
312 nfs.ko
44 nfs2.ko
68 nfs3.ko
264 nfs4.ko


Initial size (with v4.1):
708 nfs.ko

Final sizes (with v4.1):
316 nfs.ko
44 nfs2.ko
68 nfs3.ko
384 nfs4.ko


Patch Map
---------
- Patch 1 moves a function out of v2-specific code
- Patch 2 makes NFS v2 configurable
- Patch 3 adds the modules framework
- Patch 4 makes NFS v2 an optional kernel module
- Patches 5 - 9 make NFS v3 an optional kernel module
- Patches 10 - 24 make NFS v4 an optional kernel module

Changes in v4
-------------
- Use request_module to load modules
- Correct Makefile for $(CONFIG_NFS_V3_ACL)
- Various compiler errors found while changing CONFIG_NFS_* values
- Fix dependency cycle with NFS v4.1 enabled

Known bug
---------
I found that if 2 - 3 threads all try to mount NFS v4 at almost the exact
same time then try_then_request_module() will sometimes return success before
the nfs4.ko module is fully initialized. This leads to get_nfs_version()
returning -EPROTONOSUPPORT to one thread (the others are all able to use v4
without a problem). Doing schedule() then try_then_request_module() a second
time seems to fix the problem, but that feels more like a workaround than a
real fix.

I've left it out for now with hope that there is a better way to handle this.
For my own testing, I've started doing `modprobe nfs4` before mounting anything
using NFS 4.


Comments and suggestions are appreciated. Thanks!

- Bryan

Bryan Schumaker (23):
NFS: Relocate the stat_to_errno() function
NFS: Make v2 configurable
NFS: Add version registering framework
NFS: Convert v2 into a module
NFS: Break up the nfs_fs_mount function
NFS: Create a single nfs_clone_super() function
NFS: Version specific xdev mounting
NFS: Only initialize the ACL client in the v3 case
NFS: Convert v3 into a module
NFS: Initialize NFS v4 from nfs4super.c
NFS: Move lots of code from super.c
NFS: module-specific submount function
NFS: Custom alloc and free client functions for modules
NFS: Move nfs4_set_client() and support code to nfs4client.c
NFS: Move the nfs4_init_client() to nfs4client.c
NFS: Move the v4 getroot code to nfs4getroot.c
NFS: Deal with delegations
NFS: Create a v4-specific fsync function
NFS: Create custom NFS v4 write_inode() function
NFS: Create custom init_read() and init_write() functions
NFS: Give modules a custom set / unset layoutdriver functions
NFS: Use the IS_ENABLED macro for CONFIG_NFS_V4
NFS: Convert v4 into a module

fs/lockd/clnt4xdr.c | 2 +-
fs/lockd/clntxdr.c | 6 +-
fs/lockd/mon.c | 4 +-
fs/nfs/Kconfig | 13 +-
fs/nfs/Makefile | 25 +-
fs/nfs/callback.h | 2 +-
fs/nfs/client.c | 799 ++++++++-----------------------
fs/nfs/delegation.c | 8 +-
fs/nfs/delegation.h | 11 +-
fs/nfs/dir.c | 77 ++-
fs/nfs/direct.c | 2 +-
fs/nfs/dns_resolve.c | 3 +
fs/nfs/file.c | 114 ++---
fs/nfs/fscache.c | 3 +
fs/nfs/getroot.c | 136 +-----
fs/nfs/inode.c | 72 +--
fs/nfs/internal.h | 19 +-
fs/nfs/mount_clnt.c | 6 +-
fs/nfs/namespace.c | 59 +--
fs/nfs/netns.h | 2 +-
fs/nfs/nfs.h | 147 ++++++
fs/nfs/nfs2super.c | 92 ++++
fs/nfs/nfs2xdr.c | 66 +--
fs/nfs/nfs3client.c | 75 +++
fs/nfs/nfs3super.c | 123 +++++
fs/nfs/nfs3xdr.c | 4 +-
fs/nfs/nfs4_fs.h | 24 +-
fs/nfs/nfs4client.c | 543 +++++++++++++++++++++
fs/nfs/nfs4file.c | 57 +++
fs/nfs/nfs4getroot.c | 135 ++++++
fs/nfs/nfs4namespace.c | 11 +
fs/nfs/nfs4proc.c | 8 +-
fs/nfs/nfs4super.c | 703 +++++++++++++++++++++++++++
fs/nfs/{sysctl.c => nfs4sysctl.c} | 43 +-
fs/nfs/nfs4xdr.c | 2 +-
fs/nfs/pagelist.c | 3 +
fs/nfs/pnfs.c | 16 +-
fs/nfs/pnfs.h | 13 +-
fs/nfs/read.c | 8 +-
fs/nfs/super.c | 938 ++++++-------------------------------
fs/nfs/sysctl.c | 26 -
fs/nfs/unlink.c | 3 +-
fs/nfs/write.c | 36 +-
fs/nfsd/nfs4callback.c | 2 +-
include/linux/lockd/xdr4.h | 2 +-
include/linux/nfs_fs.h | 10 +-
include/linux/nfs_fs_sb.h | 6 +-
include/linux/nfs_idmap.h | 2 +-
include/linux/nfs_xdr.h | 12 +-
include/linux/sunrpc/clnt.h | 2 +-
net/sunrpc/rpcb_clnt.c | 8 +-
51 files changed, 2530 insertions(+), 1953 deletions(-)
create mode 100644 fs/nfs/dangling.txt
create mode 100644 fs/nfs/nfs.h
create mode 100644 fs/nfs/nfs2super.c
create mode 100644 fs/nfs/nfs3client.c
create mode 100644 fs/nfs/nfs3super.c
create mode 100644 fs/nfs/nfs4client.c
create mode 100644 fs/nfs/nfs4file.c
create mode 100644 fs/nfs/nfs4getroot.c
create mode 100644 fs/nfs/nfs4super.c
copy fs/nfs/{sysctl.c => nfs4sysctl.c} (51%)

--
1.7.9.4



2012-03-21 15:21:12

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 01/23] NFS: Relocate the stat_to_errno() function

From: Bryan Schumaker <[email protected]>

This was located in a file belonging to NFS v2, but it is also used by
v3. I moved it to a generic NFS client file to keep it from
disappearing once v2 becomes a module.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/nfs/nfs2xdr.c | 64 ----------------------------------------------------
2 files changed, 66 insertions(+), 64 deletions(-)

diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 2f37848..08e7f24 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -2072,6 +2072,72 @@ void nfs_fs_proc_exit(void)

#endif /* CONFIG_PROC_FS */

+/* Mapping from NFS error code to "errno" error code. */
+#define errno_NFSERR_IO EIO
+
+/*
+ * We need to translate between nfs status return values and
+ * the local errno values which may not be the same.
+ */
+static const struct {
+ int stat;
+ int errno;
+} nfs_errtbl[] = {
+ { NFS_OK, 0 },
+ { NFSERR_PERM, -EPERM },
+ { NFSERR_NOENT, -ENOENT },
+ { NFSERR_IO, -errno_NFSERR_IO},
+ { NFSERR_NXIO, -ENXIO },
+/* { NFSERR_EAGAIN, -EAGAIN }, */
+ { NFSERR_ACCES, -EACCES },
+ { NFSERR_EXIST, -EEXIST },
+ { NFSERR_XDEV, -EXDEV },
+ { NFSERR_NODEV, -ENODEV },
+ { NFSERR_NOTDIR, -ENOTDIR },
+ { NFSERR_ISDIR, -EISDIR },
+ { NFSERR_INVAL, -EINVAL },
+ { NFSERR_FBIG, -EFBIG },
+ { NFSERR_NOSPC, -ENOSPC },
+ { NFSERR_ROFS, -EROFS },
+ { NFSERR_MLINK, -EMLINK },
+ { NFSERR_NAMETOOLONG, -ENAMETOOLONG },
+ { NFSERR_NOTEMPTY, -ENOTEMPTY },
+ { NFSERR_DQUOT, -EDQUOT },
+ { NFSERR_STALE, -ESTALE },
+ { NFSERR_REMOTE, -EREMOTE },
+#ifdef EWFLUSH
+ { NFSERR_WFLUSH, -EWFLUSH },
+#endif
+ { NFSERR_BADHANDLE, -EBADHANDLE },
+ { NFSERR_NOT_SYNC, -ENOTSYNC },
+ { NFSERR_BAD_COOKIE, -EBADCOOKIE },
+ { NFSERR_NOTSUPP, -ENOTSUPP },
+ { NFSERR_TOOSMALL, -ETOOSMALL },
+ { NFSERR_SERVERFAULT, -EREMOTEIO },
+ { NFSERR_BADTYPE, -EBADTYPE },
+ { NFSERR_JUKEBOX, -EJUKEBOX },
+ { -1, -EIO }
+};
+
+/**
+ * nfs_stat_to_errno - convert an NFS status code to a local errno
+ * @status: NFS status code to convert
+ *
+ * Returns a local errno value, or -EIO if the NFS status code is
+ * not recognized. This function is used jointly by NFSv2 and NFSv3.
+ */
+int nfs_stat_to_errno(enum nfs_stat status)
+{
+ int i;
+
+ for (i = 0; nfs_errtbl[i].stat != -1; i++) {
+ if (nfs_errtbl[i].stat == (int)status)
+ return nfs_errtbl[i].errno;
+ }
+ dprintk("NFS: Unrecognized nfs status value: %u\n", status);
+ return nfs_errtbl[i].errno;
+}
+
module_param(nfs4_disable_idmapping, bool, 0644);
MODULE_PARM_DESC(nfs4_disable_idmapping,
"Turn off NFSv4 idmapping when using 'sec=sys'");
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index 1f56000..a01084d 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -1057,70 +1057,6 @@ out_default:
return nfs_stat_to_errno(status);
}

-
-/*
- * We need to translate between nfs status return values and
- * the local errno values which may not be the same.
- */
-static const struct {
- int stat;
- int errno;
-} nfs_errtbl[] = {
- { NFS_OK, 0 },
- { NFSERR_PERM, -EPERM },
- { NFSERR_NOENT, -ENOENT },
- { NFSERR_IO, -errno_NFSERR_IO},
- { NFSERR_NXIO, -ENXIO },
-/* { NFSERR_EAGAIN, -EAGAIN }, */
- { NFSERR_ACCES, -EACCES },
- { NFSERR_EXIST, -EEXIST },
- { NFSERR_XDEV, -EXDEV },
- { NFSERR_NODEV, -ENODEV },
- { NFSERR_NOTDIR, -ENOTDIR },
- { NFSERR_ISDIR, -EISDIR },
- { NFSERR_INVAL, -EINVAL },
- { NFSERR_FBIG, -EFBIG },
- { NFSERR_NOSPC, -ENOSPC },
- { NFSERR_ROFS, -EROFS },
- { NFSERR_MLINK, -EMLINK },
- { NFSERR_NAMETOOLONG, -ENAMETOOLONG },
- { NFSERR_NOTEMPTY, -ENOTEMPTY },
- { NFSERR_DQUOT, -EDQUOT },
- { NFSERR_STALE, -ESTALE },
- { NFSERR_REMOTE, -EREMOTE },
-#ifdef EWFLUSH
- { NFSERR_WFLUSH, -EWFLUSH },
-#endif
- { NFSERR_BADHANDLE, -EBADHANDLE },
- { NFSERR_NOT_SYNC, -ENOTSYNC },
- { NFSERR_BAD_COOKIE, -EBADCOOKIE },
- { NFSERR_NOTSUPP, -ENOTSUPP },
- { NFSERR_TOOSMALL, -ETOOSMALL },
- { NFSERR_SERVERFAULT, -EREMOTEIO },
- { NFSERR_BADTYPE, -EBADTYPE },
- { NFSERR_JUKEBOX, -EJUKEBOX },
- { -1, -EIO }
-};
-
-/**
- * nfs_stat_to_errno - convert an NFS status code to a local errno
- * @status: NFS status code to convert
- *
- * Returns a local errno value, or -EIO if the NFS status code is
- * not recognized. This function is used jointly by NFSv2 and NFSv3.
- */
-int nfs_stat_to_errno(enum nfs_stat status)
-{
- int i;
-
- for (i = 0; nfs_errtbl[i].stat != -1; i++) {
- if (nfs_errtbl[i].stat == (int)status)
- return nfs_errtbl[i].errno;
- }
- dprintk("NFS: Unrecognized nfs status value: %u\n", status);
- return nfs_errtbl[i].errno;
-}
-
#define PROC(proc, argtype, restype, timer) \
[NFSPROC_##proc] = { \
.p_proc = NFSPROC_##proc, \
--
1.7.9.4


2012-03-21 15:21:20

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 15/23] NFS: Move the nfs4_init_client() to nfs4client.c

From: Bryan Schumaker <[email protected]>

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 135 ++-------------------------------------------------
fs/nfs/nfs.h | 2 +
fs/nfs/nfs4client.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 132 insertions(+), 131 deletions(-)

diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 38efcf4..32a9a54 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -30,20 +30,17 @@
#include <linux/lockd/bind.h>
#include <linux/seq_file.h>
#include <linux/mount.h>
-#include <linux/nfs_idmap.h>
#include <linux/vfs.h>
#include <linux/inet.h>
#include <linux/in6.h>
#include <linux/slab.h>
#include <net/ipv6.h>
#include <linux/nfs_xdr.h>
-#include <linux/sunrpc/bc_xprt.h>
#include <linux/nsproxy.h>
#include <linux/pid_namespace.h>

#include <asm/system.h>

-#include "callback.h"
#include "iostat.h"
#include "internal.h"
#include "fscache.h"
@@ -628,10 +625,10 @@ void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
/*
* Create an RPC client handle
*/
-static int nfs_create_rpc_client(struct nfs_client *clp,
- const struct rpc_timeout *timeparms,
- rpc_authflavor_t flavor,
- int discrtry, int noresvport)
+int nfs_create_rpc_client(struct nfs_client *clp,
+ const struct rpc_timeout *timeparms,
+ rpc_authflavor_t flavor,
+ int discrtry, int noresvport)
{
struct rpc_clnt *clnt = NULL;
struct rpc_create_args args = {
@@ -1226,130 +1223,6 @@ nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr,
}
#endif /* CONFIG_NFS_V4_1 */

-/*
- * Initialize the NFS4 callback service
- */
-static int nfs4_init_callback(struct nfs_client *clp)
-{
- int error;
-
- if (clp->rpc_ops->version == 4) {
- struct rpc_xprt *xprt;
-
- xprt = rcu_dereference_raw(clp->cl_rpcclient->cl_xprt);
-
- if (nfs4_has_session(clp)) {
- error = xprt_setup_backchannel(xprt,
- NFS41_BC_MIN_CALLBACKS);
- if (error < 0)
- return error;
- }
-
- error = nfs_callback_up(clp->cl_mvops->minor_version, xprt);
- if (error < 0) {
- dprintk("%s: failed to start callback. Error = %d\n",
- __func__, error);
- return error;
- }
- __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
- }
- return 0;
-}
-
-/*
- * Initialize the minor version specific parts of an NFS4 client record
- */
-static int nfs4_init_client_minor_version(struct nfs_client *clp)
-{
-#if defined(CONFIG_NFS_V4_1)
- if (clp->cl_mvops->minor_version) {
- struct nfs4_session *session = NULL;
- /*
- * Create the session and mark it expired.
- * When a SEQUENCE operation encounters the expired session
- * it will do session recovery to initialize it.
- */
- session = nfs4_alloc_session(clp);
- if (!session)
- return -ENOMEM;
-
- clp->cl_session = session;
- /*
- * The create session reply races with the server back
- * channel probe. Mark the client NFS_CS_SESSION_INITING
- * so that the client back channel can find the
- * nfs_client struct
- */
- clp->cl_cons_state = NFS_CS_SESSION_INITING;
- }
-#endif /* CONFIG_NFS_V4_1 */
-
- return nfs4_init_callback(clp);
-}
-
-/*
- * Initialise an NFS4 client record
- */
-int nfs4_init_client(struct nfs_client *clp,
- const struct rpc_timeout *timeparms,
- const char *ip_addr,
- rpc_authflavor_t authflavour,
- int noresvport)
-{
- char buf[INET6_ADDRSTRLEN + 1];
- int error;
-
- if (clp->cl_cons_state == NFS_CS_READY) {
- /* the client is initialised already */
- dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp);
- return 0;
- }
-
- /* Check NFS protocol revision and initialize RPC op vector */
- clp->rpc_ops = &nfs_v4_clientops;
-
- error = nfs_create_rpc_client(clp, timeparms, authflavour,
- 1, noresvport);
- if (error < 0)
- goto error;
-
- /* If no clientaddr= option was specified, find a usable cb address */
- if (ip_addr == NULL) {
- struct sockaddr_storage cb_addr;
- struct sockaddr *sap = (struct sockaddr *)&cb_addr;
-
- error = rpc_localaddr(clp->cl_rpcclient, sap, sizeof(cb_addr));
- if (error < 0)
- goto error;
- error = rpc_ntop(sap, buf, sizeof(buf));
- if (error < 0)
- goto error;
- ip_addr = (const char *)buf;
- }
- strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
-
- error = nfs_idmap_new(clp);
- if (error < 0) {
- dprintk("%s: failed to create idmapper. Error = %d\n",
- __func__, error);
- goto error;
- }
- __set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
-
- error = nfs4_init_client_minor_version(clp);
- if (error < 0)
- goto error;
-
- if (!nfs4_has_session(clp))
- nfs_mark_client_ready(clp, NFS_CS_READY);
- return 0;
-
-error:
- nfs_mark_client_ready(clp, error);
- dprintk("<-- nfs4_init_client() = xerror %d\n", error);
- return error;
-}
-
#endif /* CONFIG_NFS_V4 */

/*
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 3ed4b32..d53f350 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -62,6 +62,8 @@ struct nfs_client *nfs_get_client(const struct nfs_client_initdata *,
const struct rpc_timeout *, const char *,
rpc_authflavor_t, int);
void nfs_init_timeout_values(struct rpc_timeout *, int, unsigned int, unsigned int);
+int nfs_create_rpc_client(struct nfs_client *, const struct rpc_timeout *,
+ rpc_authflavor_t, int, int);
int nfs_init_server_rpcclient(struct nfs_server *, const struct rpc_timeout *,
rpc_authflavor_t);
int nfs_probe_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *);
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index 230d25e..fcdec76 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -9,6 +9,7 @@
#include <linux/nfs_fs.h>
#include <linux/nfs_fs_sb.h>
#include <linux/nfs_idmap.h>
+#include <linux/sunrpc/bc_xprt.h>
#include "internal.h"
#include "callback.h"
#include "pnfs.h"
@@ -412,6 +413,131 @@ error:
return ERR_PTR(error);
}

+/*
+ * Initialize the NFS4 callback service
+ */
+static int nfs4_init_callback(struct nfs_client *clp)
+{
+ int error;
+
+ if (clp->rpc_ops->version == 4) {
+ struct rpc_xprt *xprt;
+
+ xprt = rcu_dereference_raw(clp->cl_rpcclient->cl_xprt);
+
+ if (nfs4_has_session(clp)) {
+ error = xprt_setup_backchannel(xprt,
+ NFS41_BC_MIN_CALLBACKS);
+ if (error < 0)
+ return error;
+ }
+
+ error = nfs_callback_up(clp->cl_mvops->minor_version, xprt);
+ if (error < 0) {
+ dprintk("%s: failed to start callback. Error = %d\n",
+ __func__, error);
+ return error;
+ }
+ __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
+ }
+ return 0;
+}
+
+/*
+ * Initialize the minor version specific parts of an NFS4 client record
+ */
+static int nfs4_init_client_minor_version(struct nfs_client *clp)
+{
+#if defined(CONFIG_NFS_V4_1)
+ if (clp->cl_mvops->minor_version) {
+ struct nfs4_session *session = NULL;
+ /*
+ * Create the session and mark it expired.
+ * When a SEQUENCE operation encounters the expired session
+ * it will do session recovery to initialize it.
+ */
+ session = nfs4_alloc_session(clp);
+ if (!session)
+ return -ENOMEM;
+
+ clp->cl_session = session;
+ /*
+ * The create session reply races with the server back
+ * channel probe. Mark the client NFS_CS_SESSION_INITING
+ * so that the client back channel can find the
+ * nfs_client struct
+ */
+ clp->cl_cons_state = NFS_CS_SESSION_INITING;
+ }
+#endif /* CONFIG_NFS_V4_1 */
+
+ return nfs4_init_callback(clp);
+}
+
+/*
+ * Initialise an NFS4 client record
+ */
+int nfs4_init_client(struct nfs_client *clp,
+ const struct rpc_timeout *timeparms,
+ const char *ip_addr,
+ rpc_authflavor_t authflavour,
+ int noresvport)
+{
+ char buf[INET6_ADDRSTRLEN + 1];
+ int error;
+
+ if (clp->cl_cons_state == NFS_CS_READY) {
+ /* the client is initialised already */
+ dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp);
+ return 0;
+ }
+
+ /* Check NFS protocol revision and initialize RPC op vector */
+ clp->rpc_ops = &nfs_v4_clientops;
+
+ error = nfs_create_rpc_client(clp, timeparms, authflavour,
+ 1, noresvport);
+ if (error < 0)
+ goto error;
+
+ /* If no clientaddr= option was specified, find a usable cb address */
+ if (ip_addr == NULL) {
+ struct sockaddr_storage cb_addr;
+ struct sockaddr *sap = (struct sockaddr *)&cb_addr;
+
+ error = rpc_localaddr(clp->cl_rpcclient, sap, sizeof(cb_addr));
+ if (error < 0)
+ goto error;
+ error = rpc_ntop(sap, buf, sizeof(buf));
+ if (error < 0)
+ goto error;
+ ip_addr = (const char *)buf;
+ }
+
+ strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
+
+ error = nfs_idmap_new(clp);
+ if (error < 0) {
+ dprintk("%s: failed to create idmapper. Error = %d\n",
+ __func__, error);
+ goto error;
+ }
+ __set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
+
+ error = nfs4_init_client_minor_version(clp);
+ if (error < 0)
+ goto error;
+
+ if (!nfs4_has_session(clp))
+ nfs_mark_client_ready(clp, NFS_CS_READY);
+ return 0;
+
+error:
+ nfs_mark_client_ready(clp, error);
+ dprintk("<-- nfs4_init_client() = xerror %d\n", error);
+ return error;
+}
+
module_param(nfs4_disable_idmapping, bool, 0644);
MODULE_PARM_DESC(nfs4_disable_idmapping,
"Turn off NFSv4 idmapping when using 'sec=sys'");
--
1.7.9.4


2012-03-21 15:21:25

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 21/23] NFS: Give modules a custom set / unset layoutdriver functions

From: Bryan Schumaker <[email protected]>

Used to set or clear the pnfs layoutdriver when pnfs is in use.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 6 ++++--
fs/nfs/nfs.h | 2 ++
fs/nfs/nfs2super.c | 12 ++++++++++++
fs/nfs/nfs3super.c | 12 ++++++++++++
fs/nfs/nfs4super.c | 2 ++
5 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 32a9a54..96de872 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -877,6 +877,7 @@ static void nfs_server_set_fsinfo(struct nfs_server *server,
struct nfs_fsinfo *fsinfo)
{
unsigned long max_rpc_payload;
+ struct nfs_subversion *nfs_mod = get_nfs_server_version(server);

/* Work out a lot of parameters */
if (server->rsize == 0)
@@ -905,7 +906,7 @@ static void nfs_server_set_fsinfo(struct nfs_server *server,
server->wsize = NFS_MAX_FILE_IO_SIZE;
server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
server->pnfs_blksize = fsinfo->blksize;
- set_pnfs_layoutdriver(server, mntfh, fsinfo->layouttype);
+ nfs_mod->set_layoutdriver(server, mntfh, fsinfo->layouttype);

server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL);

@@ -1065,10 +1066,11 @@ struct nfs_server *nfs_alloc_server(void)
*/
void nfs_free_server(struct nfs_server *server)
{
+ struct nfs_subversion *nfs_mod = get_nfs_server_version(server);
dprintk("--> nfs_free_server()\n");

nfs_server_remove_lists(server);
- unset_pnfs_layoutdriver(server);
+ nfs_mod->unset_layoutdriver(server);

if (server->destroy != NULL)
server->destroy(server);
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 21bc52b..fe8152f 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -43,6 +43,8 @@ struct nfs_subversion {
int (*return_delegation)(struct inode *);
void (*init_read)(struct nfs_pageio_descriptor *, struct inode *);
void (*init_write)(struct nfs_pageio_descriptor *, struct inode *, int);
+ void (*set_layoutdriver)(struct nfs_server *, const struct nfs_fh *, u32);
+ void (*unset_layoutdriver)(struct nfs_server *);
};

struct nfs_sb_mountdata {
diff --git a/fs/nfs/nfs2super.c b/fs/nfs/nfs2super.c
index a9a1a0b..88d772d 100644
--- a/fs/nfs/nfs2super.c
+++ b/fs/nfs/nfs2super.c
@@ -47,6 +47,16 @@ static struct vfsmount *nfs2_do_submount(struct dentry *dentry,
return _nfs_do_submount(&nfs_xdev_fs_type, dentry, fh, fattr, authflavor);
}

+static void nfs2_set_layoutdriver(struct nfs_server *server,
+ const struct nfs_fh *mntfh,
+ u32 id)
+{
+}
+
+static void nfs2_unset_layoutdriver(struct nfs_server *server)
+{
+}
+
static struct nfs_subversion nfs_v2 = {
.version = 2,
.rpc_vers = &nfs_version2,
@@ -61,6 +71,8 @@ static struct nfs_subversion nfs_v2 = {
.submount = nfs2_do_submount,
.init_read = nfs_pageio_init_read_mds,
.init_write = nfs_pageio_init_write_mds,
+ .set_layoutdriver = nfs2_set_layoutdriver,
+ .unset_layoutdriver = nfs2_unset_layoutdriver,
};

static int __init init_nfs_v2(void)
diff --git a/fs/nfs/nfs3super.c b/fs/nfs/nfs3super.c
index c84ffe3..28f56e7 100644
--- a/fs/nfs/nfs3super.c
+++ b/fs/nfs/nfs3super.c
@@ -49,6 +49,16 @@ static struct vfsmount *nfs3_do_submount(struct dentry *dentry,
return _nfs_do_submount(&nfs_xdev_fs_type, dentry, fh, fattr, authflavor);
}

+static void nfs3_set_layoutdriver(struct nfs_server *server,
+ const struct nfs_fh *mntfh,
+ u32 id)
+{
+}
+
+static void nfs3_unset_layoutdriver(struct nfs_server *server)
+{
+}
+
const struct inode_operations nfs3_file_inode_operations = {
.permission = nfs_permission,
.getattr = nfs_getattr,
@@ -92,6 +102,8 @@ static struct nfs_subversion nfs_v3 = {
.submount = nfs3_do_submount,
.init_read = nfs_pageio_init_read_mds,
.init_write = nfs_pageio_init_write_mds,
+ .set_layoutdriver = nfs3_set_layoutdriver,
+ .unset_layoutdriver = nfs3_unset_layoutdriver,
};

static int __init init_nfs_v3(void)
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 6bf44e3..7b8e79b 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -658,6 +658,8 @@ static struct nfs_subversion nfs_v4 = {
.submount = nfs4_do_submount,
.init_read = pnfs_pageio_init_read,
.init_write = pnfs_pageio_init_write,
+ .set_layoutdriver = set_pnfs_layoutdriver,
+ .unset_layoutdriver = unset_pnfs_layoutdriver,
};

int __init init_nfs_v4(void)
--
1.7.9.4


2012-03-21 15:21:21

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 17/23] NFS: Deal with delegations

From: Bryan Schumaker <[email protected]>

Modules can implement their own have_delegation and return_delegation
functions. If not, then a default value is returned. I also moved over
the nfs4_evict_inode() function so it can find the
return_delegation_noreclaim function.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/delegation.c | 8 ++++----
fs/nfs/delegation.h | 9 +++++----
fs/nfs/inode.c | 39 +++++++++++++++++----------------------
fs/nfs/internal.h | 3 ---
fs/nfs/nfs.h | 7 +++++++
fs/nfs/nfs4proc.c | 8 ++++----
fs/nfs/nfs4super.c | 18 ++++++++++++++++++
fs/nfs/unlink.c | 2 +-
fs/nfs/write.c | 2 +-
9 files changed, 57 insertions(+), 39 deletions(-)

diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 89af1d2..b950630 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -41,13 +41,13 @@ void nfs_mark_delegation_referenced(struct nfs_delegation *delegation)
}

/**
- * nfs_have_delegation - check if inode has a delegation
+ * nfs4_have_delegation - check if inode has a delegation
* @inode: inode to check
* @flags: delegation types to check for
*
* Returns one if inode has the indicated delegation, otherwise zero.
*/
-int nfs_have_delegation(struct inode *inode, fmode_t flags)
+int nfs4_have_delegation(struct inode *inode, fmode_t flags)
{
struct nfs_delegation *delegation;
int ret = 0;
@@ -377,12 +377,12 @@ void nfs_inode_return_delegation_noreclaim(struct inode *inode)
}

/**
- * nfs_inode_return_delegation - synchronously return a delegation
+ * nfs4_inode_return_delegation - synchronously return a delegation
* @inode: inode to process
*
* Returns zero on success, or a negative errno value.
*/
-int nfs_inode_return_delegation(struct inode *inode)
+int nfs4_inode_return_delegation(struct inode *inode)
{
struct nfs_server *server = NFS_SERVER(inode);
struct nfs_inode *nfsi = NFS_I(inode);
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index cd6a7a8..26f77ca 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -8,6 +8,7 @@
#ifndef FS_NFS_DELEGATION_H
#define FS_NFS_DELEGATION_H

+#include "nfs.h"
#if defined(CONFIG_NFS_V4)
/*
* NFSv4 delegation
@@ -33,7 +34,7 @@ enum {

int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
-int nfs_inode_return_delegation(struct inode *inode);
+int nfs4_inode_return_delegation(struct inode *inode);
int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid);
void nfs_inode_return_delegation_noreclaim(struct inode *inode);

@@ -56,15 +57,15 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl);
bool nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode, fmode_t flags);

void nfs_mark_delegation_referenced(struct nfs_delegation *delegation);
-int nfs_have_delegation(struct inode *inode, fmode_t flags);
+int nfs4_have_delegation(struct inode *inode, fmode_t flags);

#else
-static inline int nfs_have_delegation(struct inode *inode, fmode_t flags)
+static inline int nfs4_have_delegation(struct inode *inode, fmode_t flags)
{
return 0;
}

-static inline int nfs_inode_return_delegation(struct inode *inode)
+static inline int nfs4_inode_return_delegation(struct inode *inode)
{
return 0;
}
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 30c7103..35f4175 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -108,7 +108,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...
@@ -208,6 +208,22 @@ static void nfs_invalidate_inode(struct inode *inode)
nfs_zap_caches_locked(inode);
}

+int nfs_have_delegation(struct inode *inode, fmode_t flags)
+{
+ struct nfs_subversion *nfs_mod = get_nfs_server_version(NFS_SERVER(inode));
+ if (!nfs_mod->have_delegation)
+ return 0;
+ return nfs_mod->have_delegation(inode, flags);
+}
+
+int nfs_inode_return_delegation(struct inode *inode)
+{
+ struct nfs_subversion *nfs_mod = get_nfs_server_version(NFS_SERVER(inode));
+ if (!nfs_mod->return_delegation)
+ return 0;
+ return nfs_mod->return_delegation(inode);
+}
+
struct nfs_find_desc {
struct nfs_fh *fh;
struct nfs_fattr *fattr;
@@ -1504,27 +1520,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
goto out_err;
}

-
-#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);
- end_writeback(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;
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 2476dc6..bd335bb 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -256,9 +256,6 @@ 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_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);

diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 877ca24..fa0b531 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -38,6 +38,8 @@ struct nfs_subversion {
struct nfs_fh *, struct nfs_parsed_mount_data *);
struct dentry *(*xdev_mount)(int, const char *, struct nfs_clone_mount *);
struct vfsmount *(*submount)(struct dentry *, struct nfs_fh *, struct nfs_fattr *, rpc_authflavor_t);
+ int (*have_delegation)(struct inode *, fmode_t);
+ int (*return_delegation)(struct inode *);
};

struct nfs_sb_mountdata {
@@ -86,6 +88,11 @@ int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *)
/* Exported in getroot.c */
int nfs_superblock_set_dummy_root(struct super_block *, struct inode *);

+/* inode.c */
+void nfs_clear_inode(struct inode *);
+int nfs_have_delegation(struct inode *, fmode_t);
+int nfs_inode_return_delegation(struct inode *);
+
/* Exported in namespace.c */
struct vfsmount *_nfs_do_submount(struct file_system_type *, struct dentry *,
struct nfs_fh *, struct nfs_fattr *, rpc_authflavor_t);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index b76dd0e..cc3fd43 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -270,8 +270,8 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
case 0:
return 0;
case -NFS4ERR_OPENMODE:
- if (nfs_have_delegation(inode, FMODE_READ)) {
- nfs_inode_return_delegation(inode);
+ if (nfs4_have_delegation(inode, FMODE_READ)) {
+ nfs4_inode_return_delegation(inode);
exception->retry = 1;
return 0;
}
@@ -1044,7 +1044,7 @@ static void nfs4_return_incompatible_delegation(struct inode *inode, fmode_t fmo
return;
}
rcu_read_unlock();
- nfs_inode_return_delegation(inode);
+ nfs4_inode_return_delegation(inode);
}

static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
@@ -3779,7 +3779,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
if (i < 0)
return i;
- nfs_inode_return_delegation(inode);
+ nfs4_inode_return_delegation(inode);
ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);

/*
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index b0beba9..f463a2c 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -10,6 +10,7 @@
#include "delegation.h"
#include "fscache.h"
#include "nfs4_fs.h"
+#include "pnfs.h"
#include "nfs.h"

#define NFSDBG_FACILITY NFSDBG_VFS
@@ -26,6 +27,23 @@ static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_typ
int flags, const char *dev_name, void *raw_data);
static void nfs4_kill_super(struct super_block *sb);

+/*
+ * 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);
+ end_writeback(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);
+}
+
struct file_system_type nfs4_fs_type = {
.owner = THIS_MODULE,
.name = "nfs4",
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 3210a03..05abd34 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -18,7 +18,7 @@
#include "internal.h"
#include "nfs4_fs.h"
#include "iostat.h"
-#include "delegation.h"
+#include "nfs.h"

/**
* nfs_free_unlinkdata - release data from a sillydelete operation.
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 0f28bd2..5e30b57 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -24,12 +24,12 @@

#include <asm/uaccess.h>

-#include "delegation.h"
#include "internal.h"
#include "iostat.h"
#include "nfs4_fs.h"
#include "fscache.h"
#include "pnfs.h"
+#include "nfs.h"

#define NFSDBG_FACILITY NFSDBG_PAGECACHE

--
1.7.9.4


2012-03-21 15:21:14

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 03/23] NFS: Add version registering framework

From: Bryan Schumaker <[email protected]>

This patch adds in the code to track multiple versions of the NFS
protocol. I created default structures for v2, v3 and v4 so that each
version can continue to work while I convert them into kernel modules.
I also removed the const parameter from the rpc_version array so that I
can change it at runtime.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/lockd/clnt4xdr.c | 2 +-
fs/lockd/clntxdr.c | 6 +--
fs/lockd/mon.c | 4 +-
fs/nfs/Makefile | 6 +--
fs/nfs/client.c | 111 ++++++++++++++++++++++++++++++++++---------
fs/nfs/inode.c | 2 +
fs/nfs/mount_clnt.c | 6 +--
fs/nfs/nfs.h | 35 ++++++++++++++
fs/nfs/nfs2super.c | 31 ++++++++++++
fs/nfs/nfs2xdr.c | 2 +-
fs/nfs/nfs3super.c | 31 ++++++++++++
fs/nfs/nfs3xdr.c | 4 +-
fs/nfs/nfs4super.c | 31 ++++++++++++
fs/nfs/nfs4xdr.c | 2 +-
fs/nfs/super.c | 48 ++++++++++++++-----
fs/nfsd/nfs4callback.c | 2 +-
include/linux/lockd/xdr4.h | 2 +-
include/linux/nfs_xdr.h | 8 ++--
include/linux/sunrpc/clnt.h | 2 +-
net/sunrpc/rpcb_clnt.c | 8 ++--
20 files changed, 280 insertions(+), 63 deletions(-)
create mode 100644 fs/nfs/nfs.h
create mode 100644 fs/nfs/nfs2super.c
create mode 100644 fs/nfs/nfs3super.c
create mode 100644 fs/nfs/nfs4super.c

diff --git a/fs/lockd/clnt4xdr.c b/fs/lockd/clnt4xdr.c
index 3ddcbb1..580dbe2 100644
--- a/fs/lockd/clnt4xdr.c
+++ b/fs/lockd/clnt4xdr.c
@@ -598,7 +598,7 @@ static struct rpc_procinfo nlm4_procedures[] = {
PROC(GRANTED_RES, res, norep),
};

-const struct rpc_version nlm_version4 = {
+struct rpc_version nlm_version4 = {
.number = 4,
.nrprocs = ARRAY_SIZE(nlm4_procedures),
.procs = nlm4_procedures,
diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c
index 3d35e3e..78e80c4 100644
--- a/fs/lockd/clntxdr.c
+++ b/fs/lockd/clntxdr.c
@@ -596,19 +596,19 @@ static struct rpc_procinfo nlm_procedures[] = {
PROC(GRANTED_RES, res, norep),
};

-static const struct rpc_version nlm_version1 = {
+static struct rpc_version nlm_version1 = {
.number = 1,
.nrprocs = ARRAY_SIZE(nlm_procedures),
.procs = nlm_procedures,
};

-static const struct rpc_version nlm_version3 = {
+static struct rpc_version nlm_version3 = {
.number = 3,
.nrprocs = ARRAY_SIZE(nlm_procedures),
.procs = nlm_procedures,
};

-static const struct rpc_version *nlm_versions[] = {
+static struct rpc_version *nlm_versions[] = {
[1] = &nlm_version1,
[3] = &nlm_version3,
#ifdef CONFIG_LOCKD_V4
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 7ef14b3..888d1ef 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -535,13 +535,13 @@ static struct rpc_procinfo nsm_procedures[] = {
},
};

-static const struct rpc_version nsm_version1 = {
+static struct rpc_version nsm_version1 = {
.number = 1,
.nrprocs = ARRAY_SIZE(nsm_procedures),
.procs = nsm_procedures
};

-static const struct rpc_version *nsm_version[] = {
+static struct rpc_version *nsm_version[] = {
[1] = &nsm_version1,
};

diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 7ddd45d..c6e7844 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -9,11 +9,11 @@ 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_V2) += nfs2super.o proc.o nfs2xdr.o
+nfs-$(CONFIG_NFS_V3) += nfs3super.o nfs3proc.o nfs3xdr.o
nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
- delegation.o idmap.o \
+ nfs4super.o delegation.o idmap.o \
callback.o callback_xdr.o callback_proc.o \
nfs4namespace.o
nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 4d793b2..0fafedd 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -51,11 +51,14 @@
#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 LIST_HEAD(nfs_versions);
#ifdef CONFIG_NFS_V4

/*
@@ -89,16 +92,10 @@ static bool nfs4_disable_idmapping = true;
/*
* 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
+static struct rpc_version *nfs_version[5] = {
+ [2] = NULL,
+ [3] = NULL,
+ [4] = NULL,
};

const struct rpc_program nfs_program = {
@@ -114,10 +111,9 @@ struct rpc_stat nfs_rpcstat = {
.program = &nfs_program
};

-
#ifdef CONFIG_NFS_V3_ACL
static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program };
-static const struct rpc_version *nfsacl_version[] = {
+static struct rpc_version *nfsacl_version[] = {
[3] = &nfsacl_version3,
};

@@ -140,6 +136,81 @@ struct nfs_client_initdata {
struct net *net;
};

+static int find_nfs_version(struct nfs_subversion **nfs, unsigned int version)
+{
+ struct nfs_subversion *tmp;
+ spin_lock(&nfs_version_lock);
+
+ list_for_each_entry_safe((*nfs), tmp, &nfs_versions, list) {
+ if ((*nfs)->version == version) {
+ spin_unlock(&nfs_version_lock);
+ return 1;
+ }
+ };
+
+ spin_unlock(&nfs_version_lock);
+ return 0;
+}
+
+struct nfs_subversion *get_nfs_version(unsigned int version)
+{
+ struct nfs_subversion *nfs;
+
+ if (try_then_request_module(find_nfs_version(&nfs, version), "nfs%d", version))
+ return nfs;
+ return ERR_PTR(-EPROTONOSUPPORT);
+}
+
+inline struct nfs_subversion *get_nfs_client_version(struct nfs_client *clp)
+{
+ return get_nfs_version(clp->rpc_ops->version);
+}
+
+inline struct nfs_subversion *get_nfs_server_version(struct nfs_server *srv)
+{
+ return get_nfs_client_version(srv->nfs_client);
+}
+
+void register_nfs_version(struct nfs_subversion *nfs)
+{
+ spin_lock(&nfs_version_lock);
+
+ list_add(&nfs->list, &nfs_versions);
+ nfs_version[nfs->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->version] = NULL;
+ list_del(&nfs->list);
+
+ spin_unlock(&nfs_version_lock);
+}
+EXPORT_SYMBOL_GPL(unregister_nfs_version);
+
+/*
+ * Preload all configured NFS versions during module init.
+ * This function should be edited after each protocol is converted,
+ * and eventually removed.
+ */
+void __init nfs_register_versions(void)
+{
+#ifdef CONFIG_NFS_V2
+ init_nfs_v2();
+#endif
+#ifdef CONFIG_NFS_V3
+ init_nfs_v3();
+#endif
+#ifdef CONFIG_NFS_V4
+ init_nfs_v4();
+#endif
+}
+
/*
* Allocate a shared client record
*
@@ -855,21 +926,15 @@ static int nfs_init_server(struct nfs_server *server,
};
struct rpc_timeout timeparms;
struct nfs_client *clp;
+ struct nfs_subversion *nfs_mod;
int error;

dprintk("--> nfs_init_server()\n");

-
-#ifdef CONFIG_NFS_V2
- if (data->version == 2)
- cl_init.rpc_ops = &nfs_v2_clientops;
-#endif
-#ifdef CONFIG_NFS_V3
- if (data->version == 3)
- cl_init.rpc_ops = &nfs_v3_clientops;
-#endif
- if (cl_init.rpc_ops == NULL)
- return -EPROTONOSUPPORT;
+ nfs_mod = get_nfs_version(data->version);
+ if (IS_ERR(nfs_mod))
+ return PTR_ERR(nfs_mod);
+ cl_init.rpc_ops = nfs_mod->rpc_ops;

nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
data->timeo, data->retrans);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 7bb4d13..02a1c43 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -52,6 +52,7 @@
#include "fscache.h"
#include "dns_resolve.h"
#include "pnfs.h"
+#include "nfs.h"
#include "netns.h"

#define NFSDBG_FACILITY NFSDBG_VFS
@@ -1695,6 +1696,7 @@ static int __init init_nfs_fs(void)
#endif
if ((err = register_nfs_fs()) != 0)
goto out;
+ nfs_register_versions();
return 0;
out:
#ifdef CONFIG_PROC_FS
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index 8e65c7f..ddc7d19 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -488,19 +488,19 @@ static struct rpc_procinfo mnt3_procedures[] = {
};


-static const struct rpc_version mnt_version1 = {
+static struct rpc_version mnt_version1 = {
.number = 1,
.nrprocs = ARRAY_SIZE(mnt_procedures),
.procs = mnt_procedures,
};

-static const struct rpc_version mnt_version3 = {
+static struct rpc_version mnt_version3 = {
.number = 3,
.nrprocs = ARRAY_SIZE(mnt3_procedures),
.procs = mnt3_procedures,
};

-static const struct rpc_version *mnt_version[] = {
+static struct rpc_version *mnt_version[] = {
NULL,
&mnt_version1,
NULL,
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
new file mode 100644
index 0000000..05f6849
--- /dev/null
+++ b/fs/nfs/nfs.h
@@ -0,0 +1,35 @@
+/*
+ * 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 {
+ unsigned int version; /* Protocol number */
+ struct rpc_version *rpc_vers; /* NFS version information */
+ const struct nfs_rpc_ops *rpc_ops; /* NFS operations */
+ struct list_head list; /* List of NFS versions */
+
+ void (*reference)(void); /* For reference counting */
+ void (*unreference)(void); /* Also for reference counting */
+};
+
+void nfs_register_versions(void);
+int init_nfs_v2(void);
+int init_nfs_v3(void);
+int init_nfs_v4(void);
+
+struct nfs_subversion *get_nfs_version(unsigned int);
+struct nfs_subversion *get_nfs_client_version(struct nfs_client *);
+struct nfs_subversion *get_nfs_server_version(struct nfs_server *);
+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
index 0000000..12fa906
--- /dev/null
+++ b/fs/nfs/nfs2super.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012 Netapp, Inc. All rights reserved.
+ */
+#include <linux/module.h>
+#include <linux/nfs_fs.h>
+#include "nfs.h"
+
+static void nfs2_reference(void)
+{
+ try_module_get(THIS_MODULE);
+}
+
+static void nfs2_unreference(void)
+{
+ module_put(THIS_MODULE);
+}
+
+static struct nfs_subversion nfs_v2 = {
+ .version = 2,
+ .rpc_vers = &nfs_version2,
+ .rpc_ops = &nfs_v2_clientops,
+
+ .reference = nfs2_reference,
+ .unreference = nfs2_unreference,
+};
+
+int __init init_nfs_v2(void)
+{
+ register_nfs_version(&nfs_v2);
+ return 0;
+}
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index a01084d..5d9ec8b 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -1086,7 +1086,7 @@ struct rpc_procinfo nfs_procedures[] = {
PROC(STATFS, fhandle, statfsres, 0),
};

-const struct rpc_version nfs_version2 = {
+struct rpc_version nfs_version2 = {
.number = 2,
.nrprocs = ARRAY_SIZE(nfs_procedures),
.procs = nfs_procedures
diff --git a/fs/nfs/nfs3super.c b/fs/nfs/nfs3super.c
new file mode 100644
index 0000000..a02c815
--- /dev/null
+++ b/fs/nfs/nfs3super.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012 Netapp, Inc. All rights reserved.
+ */
+#include <linux/module.h>
+#include <linux/nfs_fs.h>
+#include "nfs.h"
+
+static void nfs3_reference(void)
+{
+ try_module_get(THIS_MODULE);
+}
+
+static void nfs3_unreference(void)
+{
+ module_put(THIS_MODULE);
+}
+
+static struct nfs_subversion nfs_v3 = {
+ .version = 3,
+ .rpc_vers = &nfs_version3,
+ .rpc_ops = &nfs_v3_clientops,
+
+ .reference = nfs3_reference,
+ .unreference = nfs3_unreference,
+};
+
+int __init init_nfs_v3(void)
+{
+ register_nfs_version(&nfs_v3);
+ return 0;
+}
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index a77cc9a..5f9aabd 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -2461,7 +2461,7 @@ struct rpc_procinfo nfs3_procedures[] = {
PROC(COMMIT, commit, commit, 5),
};

-const struct rpc_version nfs_version3 = {
+struct rpc_version nfs_version3 = {
.number = 3,
.nrprocs = ARRAY_SIZE(nfs3_procedures),
.procs = nfs3_procedures
@@ -2489,7 +2489,7 @@ static struct rpc_procinfo nfs3_acl_procedures[] = {
},
};

-const struct rpc_version nfsacl_version3 = {
+struct rpc_version nfsacl_version3 = {
.number = 3,
.nrprocs = sizeof(nfs3_acl_procedures)/
sizeof(nfs3_acl_procedures[0]),
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
new file mode 100644
index 0000000..9b2a679
--- /dev/null
+++ b/fs/nfs/nfs4super.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012 Netapp, Inc. All rights reserved.
+ */
+#include <linux/module.h>
+#include <linux/nfs_fs.h>
+#include "nfs.h"
+
+static void nfs4_reference(void)
+{
+ try_module_get(THIS_MODULE);
+}
+
+static void nfs4_unreference(void)
+{
+ module_put(THIS_MODULE);
+}
+
+static struct nfs_subversion nfs_v4 = {
+ .version = 4,
+ .rpc_vers = &nfs_version4,
+ .rpc_ops = &nfs_v4_clientops,
+
+ .reference = nfs4_reference,
+ .unreference = nfs4_unreference,
+};
+
+int __init init_nfs_v4(void)
+{
+ register_nfs_version(&nfs_v4);
+ return 0;
+}
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index c74fdb1..cfd333c 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -7071,7 +7071,7 @@ struct rpc_procinfo nfs4_procedures[] = {
#endif /* CONFIG_NFS_V4_1 */
};

-const struct rpc_version nfs_version4 = {
+struct rpc_version nfs_version4 = {
.number = 4,
.nrprocs = ARRAY_SIZE(nfs4_procedures),
.procs = nfs4_procedures
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index aac4030..5ab7c0d 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -65,6 +65,7 @@
#include "internal.h"
#include "fscache.h"
#include "pnfs.h"
+#include "nfs.h"

#define NFSDBG_FACILITY NFSDBG_VFS

@@ -2284,6 +2285,22 @@ static int nfs_bdi_register(struct nfs_server *server)
return bdi_register_dev(&server->backing_dev_info, server->s_dev);
}

+static int nfs_register(struct nfs_server *server)
+{
+ struct nfs_subversion *nfs_mod = get_nfs_server_version(server);
+ int err = nfs_bdi_register(server);
+ if (!err)
+ nfs_mod->reference();
+ return err;
+}
+
+static void nfs_unregister(struct nfs_server *server)
+{
+ struct nfs_subversion *nfs_mod = get_nfs_server_version(server);
+ bdi_unregister(&server->backing_dev_info);
+ nfs_mod->unreference();
+}
+
static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data)
{
@@ -2296,6 +2313,7 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
struct nfs_sb_mountdata sb_mntdata = {
.mntflags = flags,
};
+ struct nfs_subversion *nfs_mod;
int error;

data = nfs_alloc_parsed_mount_data(NFS_DEFAULT_VERSION);
@@ -2310,6 +2328,12 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
goto out;
}

+ nfs_mod = get_nfs_version(data->version);
+ if (IS_ERR(nfs_mod)) {
+ mntroot = (struct dentry *)nfs_mod;
+ goto out;
+ }
+
#ifdef CONFIG_NFS_V4
if (data->version == 4) {
mntroot = nfs4_try_mount(flags, dev_name, data);
@@ -2343,7 +2367,7 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
nfs_free_server(server);
server = NULL;
} else {
- error = nfs_bdi_register(server);
+ error = nfs_register(server);
if (error) {
mntroot = ERR_PTR(error);
goto error_splat_bdi;
@@ -2380,7 +2404,7 @@ error_splat_root:
mntroot = ERR_PTR(error);
error_splat_super:
if (server && !s->s_root)
- bdi_unregister(&server->backing_dev_info);
+ nfs_unregister(server);
error_splat_bdi:
deactivate_locked_super(s);
goto out;
@@ -2392,9 +2416,7 @@ error_splat_bdi:
*/
static void nfs_put_super(struct super_block *s)
{
- struct nfs_server *server = NFS_SB(s);
-
- bdi_unregister(&server->backing_dev_info);
+ nfs_unregister(NFS_SB(s));
}

/*
@@ -2454,7 +2476,7 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,
nfs_free_server(server);
server = NULL;
} else {
- error = nfs_bdi_register(server);
+ error = nfs_register(server);
if (error)
goto error_splat_bdi;
}
@@ -2492,7 +2514,7 @@ out_err_noserver:

error_splat_super:
if (server && !s->s_root)
- bdi_unregister(&server->backing_dev_info);
+ nfs_unregister(server);
error_splat_bdi:
deactivate_locked_super(s);
dprintk("<-- nfs_xdev_mount() = %d [splat]\n", error);
@@ -2717,7 +2739,7 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags,
nfs_free_server(server);
server = NULL;
} else {
- error = nfs_bdi_register(server);
+ error = nfs_register(server);
if (error)
goto error_splat_bdi;
}
@@ -2755,7 +2777,7 @@ error_splat_root:
dput(mntroot);
error_splat_super:
if (server && !s->s_root)
- bdi_unregister(&server->backing_dev_info);
+ nfs_unregister(server);
error_splat_bdi:
deactivate_locked_super(s);
goto out;
@@ -2977,7 +2999,7 @@ nfs4_xdev_mount(struct file_system_type *fs_type, int flags,
nfs_free_server(server);
server = NULL;
} else {
- error = nfs_bdi_register(server);
+ error = nfs_register(server);
if (error)
goto error_splat_bdi;
}
@@ -3014,7 +3036,7 @@ out_err_noserver:

error_splat_super:
if (server && !s->s_root)
- bdi_unregister(&server->backing_dev_info);
+ nfs_unregister(server);
error_splat_bdi:
deactivate_locked_super(s);
dprintk("<-- nfs4_xdev_mount() = %d [splat]\n", error);
@@ -3068,7 +3090,7 @@ nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
nfs_free_server(server);
server = NULL;
} else {
- error = nfs_bdi_register(server);
+ error = nfs_register(server);
if (error)
goto error_splat_bdi;
}
@@ -3108,7 +3130,7 @@ out_err_nofh:

error_splat_super:
if (server && !s->s_root)
- bdi_unregister(&server->backing_dev_info);
+ nfs_unregister(server);
error_splat_bdi:
deactivate_locked_super(s);
nfs_free_fhandle(mntfh);
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 0e262f3..74d19d4 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -605,7 +605,7 @@ static struct rpc_version nfs_cb_version4 = {
.procs = nfs4_cb_procedures
};

-static const struct rpc_version *nfs_cb_version[] = {
+static struct rpc_version *nfs_cb_version[] = {
&nfs_cb_version4,
};

diff --git a/include/linux/lockd/xdr4.h b/include/linux/lockd/xdr4.h
index e58c88b..7353821 100644
--- a/include/linux/lockd/xdr4.h
+++ b/include/linux/lockd/xdr4.h
@@ -42,6 +42,6 @@ int nlmclt_encode_lockargs(struct rpc_rqst *, u32 *, struct nlm_args *);
int nlmclt_encode_cancargs(struct rpc_rqst *, u32 *, struct nlm_args *);
int nlmclt_encode_unlockargs(struct rpc_rqst *, u32 *, struct nlm_args *);
*/
-extern const struct rpc_version nlm_version4;
+extern struct rpc_version nlm_version4;

#endif /* LOCKD_XDR4_H */
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index bfd0d1b..a52ddd5 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1300,11 +1300,11 @@ struct nfs_rpc_ops {
extern const struct nfs_rpc_ops nfs_v2_clientops;
extern const struct nfs_rpc_ops nfs_v3_clientops;
extern const struct nfs_rpc_ops nfs_v4_clientops;
-extern const struct rpc_version nfs_version2;
-extern const struct rpc_version nfs_version3;
-extern const struct rpc_version nfs_version4;
+extern struct rpc_version nfs_version2;
+extern struct rpc_version nfs_version3;
+extern struct rpc_version nfs_version4;

-extern const struct rpc_version nfsacl_version3;
+extern struct rpc_version nfsacl_version3;
extern const struct rpc_program nfsacl_program;

#endif
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 523547e..624d8e3 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -72,7 +72,7 @@ struct rpc_program {
const char * name; /* protocol name */
u32 number; /* program number */
unsigned int nrvers; /* number of versions */
- const struct rpc_version ** version; /* version array */
+ struct rpc_version ** version; /* version array */
struct rpc_stat * stats; /* statistics */
const char * pipe_dir_name; /* path to rpc_pipefs dir */
};
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 207a746..227b5fb 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -1081,25 +1081,25 @@ static const struct rpcb_info rpcb_next_version6[] = {
},
};

-static const struct rpc_version rpcb_version2 = {
+static struct rpc_version rpcb_version2 = {
.number = RPCBVERS_2,
.nrprocs = ARRAY_SIZE(rpcb_procedures2),
.procs = rpcb_procedures2
};

-static const struct rpc_version rpcb_version3 = {
+static struct rpc_version rpcb_version3 = {
.number = RPCBVERS_3,
.nrprocs = ARRAY_SIZE(rpcb_procedures3),
.procs = rpcb_procedures3
};

-static const struct rpc_version rpcb_version4 = {
+static struct rpc_version rpcb_version4 = {
.number = RPCBVERS_4,
.nrprocs = ARRAY_SIZE(rpcb_procedures4),
.procs = rpcb_procedures4
};

-static const struct rpc_version *rpcb_version[] = {
+static struct rpc_version *rpcb_version[] = {
NULL,
NULL,
&rpcb_version2,
--
1.7.9.4


2012-03-21 16:38:02

by Anna Schumaker

[permalink] [raw]
Subject: Re: [PATCH v4 03/23] NFS: Add version registering framework

On 03/21/2012 12:03 PM, Myklebust, Trond wrote:

> On Wed, 2012-03-21 at 11:20 -0400, [email protected] wrote:
>>
>> +static int find_nfs_version(struct nfs_subversion **nfs, unsigned int version)
>> +{
>> + struct nfs_subversion *tmp;
>> + spin_lock(&nfs_version_lock);
>> +
>> + list_for_each_entry_safe((*nfs), tmp, &nfs_versions, list) {
>> + if ((*nfs)->version == version) {
>> + spin_unlock(&nfs_version_lock);
>> + return 1;
>> + }
>> + };
>> +
>
> BTW: The above function needs to call try_module_get() under the
> nfs_version_lock. Otherwise you will not be guaranteed that the module
> still exists and is live when you try to use the pointer '*nfs'.


Ah, I didn't think of that. I'll add in the try_module_get() call and put in a put_nfs_version() function to unreference the module, too.

- Bryan

>



2012-03-21 15:21:18

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 12/23] NFS: module-specific submount function

From: Bryan Schumaker <[email protected]>

This gives v4 the chance to check for referrals and allows each version
to pass their own xdev_fs_type structure.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/namespace.c | 55 +++++++++++++++++++-----------------------------
fs/nfs/nfs.h | 5 +++++
fs/nfs/nfs2super.c | 9 ++++++++
fs/nfs/nfs3super.c | 9 ++++++++
fs/nfs/nfs4_fs.h | 3 +++
fs/nfs/nfs4namespace.c | 11 ++++++++++
fs/nfs/nfs4super.c | 1 +
fs/nfs/super.c | 1 +
8 files changed, 61 insertions(+), 33 deletions(-)

diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 1807866..c071f54 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -7,6 +7,7 @@
* NFS namespace
*/

+#include <linux/module.h>
#include <linux/dcache.h>
#include <linux/gfp.h>
#include <linux/mount.h>
@@ -17,6 +18,7 @@
#include <linux/vfs.h>
#include <linux/sunrpc/gss_api.h>
#include "internal.h"
+#include "nfs.h"

#define NFSDBG_FACILITY NFSDBG_VFS

@@ -26,7 +28,8 @@ static LIST_HEAD(nfs_automount_list);
static DECLARE_DELAYED_WORK(nfs_automount_task, nfs_expire_automounts);
int nfs_mountpoint_expiry_timeout = 500 * HZ;

-static struct vfsmount *nfs_do_submount(struct dentry *dentry,
+static struct vfsmount *nfs_do_submount(struct nfs_server *server,
+ struct dentry *dentry,
struct nfs_fh *fh,
struct nfs_fattr *fattr,
rpc_authflavor_t authflavor);
@@ -260,10 +263,7 @@ struct vfsmount *nfs_d_automount(struct path *path)
goto out;
}

- if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)
- mnt = nfs_do_refmount(path->dentry);
- else
- mnt = nfs_do_submount(path->dentry, fh, fattr, flavor);
+ mnt = nfs_do_submount(server, path->dentry, fh, fattr, flavor);
if (IS_ERR(mnt))
goto out;

@@ -305,29 +305,6 @@ void nfs_release_automount_timer(void)
cancel_delayed_work(&nfs_automount_task);
}

-/*
- * Clone a mountpoint of the appropriate type
- */
-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
-}
-
/**
* nfs_do_submount - set up mountpoint when crossing a filesystem boundary
* @dentry - parent directory
@@ -336,10 +313,11 @@ static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server,
* @authflavor - security flavor to use when performing the mount
*
*/
-static struct vfsmount *nfs_do_submount(struct dentry *dentry,
- struct nfs_fh *fh,
- struct nfs_fattr *fattr,
- rpc_authflavor_t authflavor)
+struct vfsmount *_nfs_do_submount(struct file_system_type *xdev,
+ struct dentry *dentry,
+ struct nfs_fh *fh,
+ struct nfs_fattr *fattr,
+ rpc_authflavor_t authflavor)
{
struct nfs_clone_mount mountdata = {
.sb = dentry->d_sb,
@@ -363,7 +341,7 @@ static struct vfsmount *nfs_do_submount(struct dentry *dentry,
mnt = (struct vfsmount *)devname;
if (IS_ERR(devname))
goto free_page;
- mnt = nfs_do_clone_mount(NFS_SB(dentry->d_sb), devname, &mountdata);
+ mnt = vfs_kern_mount(xdev, 0, devname, &mountdata);
free_page:
free_page((unsigned long)page);
out:
@@ -372,3 +350,14 @@ out:
dprintk("<-- nfs_do_submount() = %p\n", mnt);
return mnt;
}
+EXPORT_SYMBOL_GPL(_nfs_do_submount);
+
+static struct vfsmount *nfs_do_submount(struct nfs_server *server,
+ struct dentry *dentry,
+ struct nfs_fh *fh,
+ struct nfs_fattr *fattr,
+ rpc_authflavor_t authflavor)
+{
+ struct nfs_subversion *nfs_mod = get_nfs_server_version(server);
+ return nfs_mod->submount(dentry, fh, fattr, authflavor);
+}
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index f298c17..9e632c2 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -25,6 +25,7 @@ struct nfs_subversion {
struct dentry *(*fs_mount)(struct file_system_type *, int, const char *,
struct nfs_fh *, struct nfs_parsed_mount_data *);
struct dentry *(*xdev_mount)(int, const char *, struct nfs_clone_mount *);
+ struct vfsmount *(*submount)(struct dentry *, struct nfs_fh *, struct nfs_fattr *, rpc_authflavor_t);
};

struct nfs_sb_mountdata {
@@ -55,6 +56,10 @@ int nfs_link(struct dentry *, struct inode *, struct dentry *);
int nfs_mknod(struct inode *, struct dentry *, umode_t, dev_t);
int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);

+/* Exported in namespace.c */
+struct vfsmount *_nfs_do_submount(struct file_system_type *, struct dentry *,
+ struct nfs_fh *, struct nfs_fattr *, rpc_authflavor_t);
+
/* Exported in super.c */
extern struct file_system_type nfs_fs_type;
struct dentry *_nfs_fs_mount(struct file_system_type *, struct nfs_server *,
diff --git a/fs/nfs/nfs2super.c b/fs/nfs/nfs2super.c
index ddcc4d1..6d2a1fd 100644
--- a/fs/nfs/nfs2super.c
+++ b/fs/nfs/nfs2super.c
@@ -39,6 +39,14 @@ static struct dentry *nfs2_xdev_mount(int flags, const char *dev_name,
return _nfs_xdev_mount(&nfs_fs_type, server, flags, dev_name, data, NFS_MOUNT_UNSHARED);
}

+static struct vfsmount *nfs2_do_submount(struct dentry *dentry,
+ struct nfs_fh *fh,
+ struct nfs_fattr *fattr,
+ rpc_authflavor_t authflavor)
+{
+ return _nfs_do_submount(&nfs_xdev_fs_type, dentry, fh, fattr, authflavor);
+}
+
static struct nfs_subversion nfs_v2 = {
.version = 2,
.rpc_vers = &nfs_version2,
@@ -48,6 +56,7 @@ static struct nfs_subversion nfs_v2 = {
.unreference = nfs2_unreference,
.fs_mount = nfs2_fs_mount,
.xdev_mount = nfs2_xdev_mount,
+ .submount = nfs2_do_submount,
};

static int __init init_nfs_v2(void)
diff --git a/fs/nfs/nfs3super.c b/fs/nfs/nfs3super.c
index 8cf7371..7142c03 100644
--- a/fs/nfs/nfs3super.c
+++ b/fs/nfs/nfs3super.c
@@ -41,6 +41,14 @@ static struct dentry *nfs3_xdev_mount(int flags, const char *dev_name,
return _nfs_xdev_mount(&nfs_fs_type, server, flags, dev_name, data, NFS_MOUNT_UNSHARED);
}

+static struct vfsmount *nfs3_do_submount(struct dentry *dentry,
+ struct nfs_fh *fh,
+ struct nfs_fattr *fattr,
+ rpc_authflavor_t authflavor)
+{
+ return _nfs_do_submount(&nfs_xdev_fs_type, dentry, fh, fattr, authflavor);
+}
+
const struct inode_operations nfs3_file_inode_operations = {
.permission = nfs_permission,
.getattr = nfs_getattr,
@@ -79,6 +87,7 @@ static struct nfs_subversion nfs_v3 = {
.unreference = nfs3_unreference,
.fs_mount = nfs3_fs_mount,
.xdev_mount = nfs3_xdev_mount,
+ .submount = nfs3_do_submount,
};

static int __init init_nfs_v3(void)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 0652352..b6bc89c 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -210,6 +210,9 @@ extern const struct inode_operations nfs4_dir_inode_operations;
extern struct file_system_type nfs4_fs_type;
struct dentry *nfs4_try_mount(int flags, const char *dev_name, struct nfs_parsed_mount_data *);

+/* nfs4namespace.c */
+struct vfsmount *nfs4_do_submount(struct dentry *, struct nfs_fh *, struct nfs_fattr *, rpc_authflavor_t);
+
/* nfs4proc.c */
extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *);
extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *);
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index 9c8eca3..f70c2bf 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -19,6 +19,7 @@
#include "internal.h"
#include "nfs4_fs.h"
#include "dns_resolve.h"
+#include "nfs.h"

#define NFSDBG_FACILITY NFSDBG_VFS

@@ -265,3 +266,13 @@ out:
dprintk("%s: done\n", __func__);
return mnt;
}
+
+struct vfsmount *nfs4_do_submount(struct dentry *dentry,
+ struct nfs_fh *fh,
+ struct nfs_fattr *fattr,
+ rpc_authflavor_t authflavor)
+{
+ if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)
+ return nfs_do_refmount(dentry);
+ return _nfs_do_submount(&nfs4_xdev_fs_type, dentry, fh, fattr, authflavor);
+}
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 91b4758..b384a81 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -617,6 +617,7 @@ static struct nfs_subversion nfs_v4 = {
.unreference = nfs4_unreference,
.fs_mount = nfs4_fs_mount,
.xdev_mount = nfs4_xdev_mount,
+ .submount = nfs4_do_submount,
};

int __init init_nfs_v4(void)
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index e2dd324..97f3ff0 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -294,6 +294,7 @@ struct file_system_type nfs_xdev_fs_type = {
.kill_sb = nfs_kill_super,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
};
+EXPORT_SYMBOL_GPL(nfs_xdev_fs_type);

static const struct super_operations nfs_sops = {
.alloc_inode = nfs_alloc_inode,
--
1.7.9.4


2012-03-21 15:57:47

by Myklebust, Trond

[permalink] [raw]
Subject: Re: [PATCH v4 03/23] NFS: Add version registering framework

T24gV2VkLCAyMDEyLTAzLTIxIGF0IDExOjIwIC0wNDAwLCBianNjaHVtYUBuZXRhcHAuY29tIHdy
b3RlOg0KPiBGcm9tOiBCcnlhbiBTY2h1bWFrZXIgPGJqc2NodW1hQG5ldGFwcC5jb20+DQo+IA0K
PiBUaGlzIHBhdGNoIGFkZHMgaW4gdGhlIGNvZGUgdG8gdHJhY2sgbXVsdGlwbGUgdmVyc2lvbnMg
b2YgdGhlIE5GUw0KPiBwcm90b2NvbC4gIEkgY3JlYXRlZCBkZWZhdWx0IHN0cnVjdHVyZXMgZm9y
IHYyLCB2MyBhbmQgdjQgc28gdGhhdCBlYWNoDQo+IHZlcnNpb24gY2FuIGNvbnRpbnVlIHRvIHdv
cmsgd2hpbGUgSSBjb252ZXJ0IHRoZW0gaW50byBrZXJuZWwgbW9kdWxlcy4NCj4gSSBhbHNvIHJl
bW92ZWQgdGhlIGNvbnN0IHBhcmFtZXRlciBmcm9tIHRoZSBycGNfdmVyc2lvbiBhcnJheSBzbyB0
aGF0IEkNCj4gY2FuIGNoYW5nZSBpdCBhdCBydW50aW1lLg0KPiANCj4gU2lnbmVkLW9mZi1ieTog
QnJ5YW4gU2NodW1ha2VyIDxianNjaHVtYUBuZXRhcHAuY29tPg0KPiAtLS0NCj4gIGZzL2xvY2tk
L2NsbnQ0eGRyLmMgICAgICAgICB8ICAgIDIgKy0NCj4gIGZzL2xvY2tkL2NsbnR4ZHIuYyAgICAg
ICAgICB8ICAgIDYgKy0tDQo+ICBmcy9sb2NrZC9tb24uYyAgICAgICAgICAgICAgfCAgICA0ICst
DQo+ICBmcy9uZnMvTWFrZWZpbGUgICAgICAgICAgICAgfCAgICA2ICstLQ0KPiAgZnMvbmZzL2Ns
aWVudC5jICAgICAgICAgICAgIHwgIDExMSArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr
KysrLS0tLS0tLS0tDQo+ICBmcy9uZnMvaW5vZGUuYyAgICAgICAgICAgICAgfCAgICAyICsNCj4g
IGZzL25mcy9tb3VudF9jbG50LmMgICAgICAgICB8ICAgIDYgKy0tDQo+ICBmcy9uZnMvbmZzLmgg
ICAgICAgICAgICAgICAgfCAgIDM1ICsrKysrKysrKysrKysrDQo+ICBmcy9uZnMvbmZzMnN1cGVy
LmMgICAgICAgICAgfCAgIDMxICsrKysrKysrKysrKw0KPiAgZnMvbmZzL25mczJ4ZHIuYyAgICAg
ICAgICAgIHwgICAgMiArLQ0KPiAgZnMvbmZzL25mczNzdXBlci5jICAgICAgICAgIHwgICAzMSAr
KysrKysrKysrKysNCj4gIGZzL25mcy9uZnMzeGRyLmMgICAgICAgICAgICB8ICAgIDQgKy0NCj4g
IGZzL25mcy9uZnM0c3VwZXIuYyAgICAgICAgICB8ICAgMzEgKysrKysrKysrKysrDQo+ICBmcy9u
ZnMvbmZzNHhkci5jICAgICAgICAgICAgfCAgICAyICstDQo+ICBmcy9uZnMvc3VwZXIuYyAgICAg
ICAgICAgICAgfCAgIDQ4ICsrKysrKysrKysrKysrLS0tLS0NCj4gIGZzL25mc2QvbmZzNGNhbGxi
YWNrLmMgICAgICB8ICAgIDIgKy0NCj4gIGluY2x1ZGUvbGludXgvbG9ja2QveGRyNC5oICB8ICAg
IDIgKy0NCj4gIGluY2x1ZGUvbGludXgvbmZzX3hkci5oICAgICB8ICAgIDggKystLQ0KPiAgaW5j
bHVkZS9saW51eC9zdW5ycGMvY2xudC5oIHwgICAgMiArLQ0KPiAgbmV0L3N1bnJwYy9ycGNiX2Ns
bnQuYyAgICAgIHwgICAgOCArKy0tDQo+ICAyMCBmaWxlcyBjaGFuZ2VkLCAyODAgaW5zZXJ0aW9u
cygrKSwgNjMgZGVsZXRpb25zKC0pDQo+ICBjcmVhdGUgbW9kZSAxMDA2NDQgZnMvbmZzL25mcy5o
DQo+ICBjcmVhdGUgbW9kZSAxMDA2NDQgZnMvbmZzL25mczJzdXBlci5jDQo+ICBjcmVhdGUgbW9k
ZSAxMDA2NDQgZnMvbmZzL25mczNzdXBlci5jDQo+ICBjcmVhdGUgbW9kZSAxMDA2NDQgZnMvbmZz
L25mczRzdXBlci5jDQo+IA0KPiBkaWZmIC0tZ2l0IGEvZnMvbG9ja2QvY2xudDR4ZHIuYyBiL2Zz
L2xvY2tkL2NsbnQ0eGRyLmMNCj4gaW5kZXggM2RkY2JiMS4uNTgwZGJlMiAxMDA2NDQNCj4gLS0t
IGEvZnMvbG9ja2QvY2xudDR4ZHIuYw0KPiArKysgYi9mcy9sb2NrZC9jbG50NHhkci5jDQo+IEBA
IC01OTgsNyArNTk4LDcgQEAgc3RhdGljIHN0cnVjdCBycGNfcHJvY2luZm8JbmxtNF9wcm9jZWR1
cmVzW10gPSB7DQo+ICAJUFJPQyhHUkFOVEVEX1JFUywJcmVzLAkJbm9yZXApLA0KPiAgfTsNCj4g
IA0KPiAtY29uc3Qgc3RydWN0IHJwY192ZXJzaW9uIG5sbV92ZXJzaW9uNCA9IHsNCj4gK3N0cnVj
dCBycGNfdmVyc2lvbiBubG1fdmVyc2lvbjQgPSB7DQo+ICAJLm51bWJlcgkJPSA0LA0KPiAgCS5u
cnByb2NzCT0gQVJSQVlfU0laRShubG00X3Byb2NlZHVyZXMpLA0KPiAgCS5wcm9jcwkJPSBubG00
X3Byb2NlZHVyZXMsDQo+IGRpZmYgLS1naXQgYS9mcy9sb2NrZC9jbG50eGRyLmMgYi9mcy9sb2Nr
ZC9jbG50eGRyLmMNCj4gaW5kZXggM2QzNWUzZS4uNzhlODBjNCAxMDA2NDQNCj4gLS0tIGEvZnMv
bG9ja2QvY2xudHhkci5jDQo+ICsrKyBiL2ZzL2xvY2tkL2NsbnR4ZHIuYw0KPiBAQCAtNTk2LDE5
ICs1OTYsMTkgQEAgc3RhdGljIHN0cnVjdCBycGNfcHJvY2luZm8JbmxtX3Byb2NlZHVyZXNbXSA9
IHsNCj4gIAlQUk9DKEdSQU5URURfUkVTLAlyZXMsCQlub3JlcCksDQo+ICB9Ow0KPiAgDQo+IC1z
dGF0aWMgY29uc3Qgc3RydWN0IHJwY192ZXJzaW9uCW5sbV92ZXJzaW9uMSA9IHsNCg0KV2h5IHNo
b3VsZG4ndCB0aGVzZSAoYW5kIHRoZSBtb3VudCBwcm90b2NvbCBlcXVpdmFsZW50cyBldGMpIHN0
aWxsIGJlDQpkZWNsYXJlZCBjb25zdGFudD8NCg0KPiArc3RhdGljIHN0cnVjdCBycGNfdmVyc2lv
bglubG1fdmVyc2lvbjEgPSB7DQo+ICAJCS5udW1iZXIJCT0gMSwNCj4gIAkJLm5ycHJvY3MJPSBB
UlJBWV9TSVpFKG5sbV9wcm9jZWR1cmVzKSwNCj4gIAkJLnByb2NzCQk9IG5sbV9wcm9jZWR1cmVz
LA0KPiAgfTsNCj4gIA0KPiAtc3RhdGljIGNvbnN0IHN0cnVjdCBycGNfdmVyc2lvbglubG1fdmVy
c2lvbjMgPSB7DQo+ICtzdGF0aWMgc3RydWN0IHJwY192ZXJzaW9uCW5sbV92ZXJzaW9uMyA9IHsN
Cj4gIAkJLm51bWJlcgkJPSAzLA0KPiAgCQkubnJwcm9jcwk9IEFSUkFZX1NJWkUobmxtX3Byb2Nl
ZHVyZXMpLA0KPiAgCQkucHJvY3MJCT0gbmxtX3Byb2NlZHVyZXMsDQo+ICB9Ow0KPiAgDQo+IC1z
dGF0aWMgY29uc3Qgc3RydWN0IHJwY192ZXJzaW9uCSpubG1fdmVyc2lvbnNbXSA9IHsNCj4gK3N0
YXRpYyBzdHJ1Y3QgcnBjX3ZlcnNpb24JKm5sbV92ZXJzaW9uc1tdID0gew0KPiAgCVsxXSA9ICZu
bG1fdmVyc2lvbjEsDQo+ICAJWzNdID0gJm5sbV92ZXJzaW9uMywNCj4gICNpZmRlZiBDT05GSUdf
TE9DS0RfVjQNCj4gZGlmZiAtLWdpdCBhL2ZzL2xvY2tkL21vbi5jIGIvZnMvbG9ja2QvbW9uLmMN
Cj4gaW5kZXggN2VmMTRiMy4uODg4ZDFlZiAxMDA2NDQNCj4gLS0tIGEvZnMvbG9ja2QvbW9uLmMN
Cj4gKysrIGIvZnMvbG9ja2QvbW9uLmMNCj4gQEAgLTUzNSwxMyArNTM1LDEzIEBAIHN0YXRpYyBz
dHJ1Y3QgcnBjX3Byb2NpbmZvCW5zbV9wcm9jZWR1cmVzW10gPSB7DQo+ICAJfSwNCj4gIH07DQo+
ICANCj4gLXN0YXRpYyBjb25zdCBzdHJ1Y3QgcnBjX3ZlcnNpb24gbnNtX3ZlcnNpb24xID0gew0K
PiArc3RhdGljIHN0cnVjdCBycGNfdmVyc2lvbiBuc21fdmVyc2lvbjEgPSB7DQo+ICAJCS5udW1i
ZXIJCT0gMSwNCj4gIAkJLm5ycHJvY3MJPSBBUlJBWV9TSVpFKG5zbV9wcm9jZWR1cmVzKSwNCj4g
IAkJLnByb2NzCQk9IG5zbV9wcm9jZWR1cmVzDQo+ICB9Ow0KPiAgDQo+IC1zdGF0aWMgY29uc3Qg
c3RydWN0IHJwY192ZXJzaW9uICpuc21fdmVyc2lvbltdID0gew0KPiArc3RhdGljIHN0cnVjdCBy
cGNfdmVyc2lvbiAqbnNtX3ZlcnNpb25bXSA9IHsNCj4gIAlbMV0gPSAmbnNtX3ZlcnNpb24xLA0K
PiAgfTsNCj4gIA0KPiBkaWZmIC0tZ2l0IGEvZnMvbmZzL01ha2VmaWxlIGIvZnMvbmZzL01ha2Vm
aWxlDQo+IGluZGV4IDdkZGQ0NWQuLmM2ZTc4NDQgMTAwNjQ0DQo+IC0tLSBhL2ZzL25mcy9NYWtl
ZmlsZQ0KPiArKysgYi9mcy9uZnMvTWFrZWZpbGUNCj4gQEAgLTksMTEgKzksMTEgQEAgbmZzLXkg
CQkJOj0gY2xpZW50Lm8gZGlyLm8gZmlsZS5vIGdldHJvb3QubyBpbm9kZS5vIHN1cGVyLm8gXA0K
PiAgCQkJICAgd3JpdGUubyBuYW1lc3BhY2UubyBtb3VudF9jbG50Lm8gXA0KPiAgCQkJICAgZG5z
X3Jlc29sdmUubyBjYWNoZV9saWIubw0KPiAgbmZzLSQoQ09ORklHX1JPT1RfTkZTKQkrPSBuZnNy
b290Lm8NCj4gLW5mcy0kKENPTkZJR19ORlNfVjIpCSs9IHByb2MubyBuZnMyeGRyLm8NCj4gLW5m
cy0kKENPTkZJR19ORlNfVjMpCSs9IG5mczNwcm9jLm8gbmZzM3hkci5vDQo+ICtuZnMtJChDT05G
SUdfTkZTX1YyKQkrPSBuZnMyc3VwZXIubyBwcm9jLm8gbmZzMnhkci5vDQo+ICtuZnMtJChDT05G
SUdfTkZTX1YzKQkrPSBuZnMzc3VwZXIubyBuZnMzcHJvYy5vIG5mczN4ZHIubw0KPiAgbmZzLSQo
Q09ORklHX05GU19WM19BQ0wpCSs9IG5mczNhY2wubw0KPiAgbmZzLSQoQ09ORklHX05GU19WNCkJ
Kz0gbmZzNHByb2MubyBuZnM0eGRyLm8gbmZzNHN0YXRlLm8gbmZzNHJlbmV3ZC5vIFwNCj4gLQkJ
CSAgIGRlbGVnYXRpb24ubyBpZG1hcC5vIFwNCj4gKwkJCSAgIG5mczRzdXBlci5vIGRlbGVnYXRp
b24ubyBpZG1hcC5vIFwNCj4gIAkJCSAgIGNhbGxiYWNrLm8gY2FsbGJhY2tfeGRyLm8gY2FsbGJh
Y2tfcHJvYy5vIFwNCj4gIAkJCSAgIG5mczRuYW1lc3BhY2Uubw0KPiAgbmZzLSQoQ09ORklHX05G
U19WNF8xKQkrPSBwbmZzLm8gcG5mc19kZXYubw0KPiBkaWZmIC0tZ2l0IGEvZnMvbmZzL2NsaWVu
dC5jIGIvZnMvbmZzL2NsaWVudC5jDQo+IGluZGV4IDRkNzkzYjIuLjBmYWZlZGQgMTAwNjQ0DQo+
IC0tLSBhL2ZzL25mcy9jbGllbnQuYw0KPiArKysgYi9mcy9uZnMvY2xpZW50LmMNCj4gQEAgLTUx
LDExICs1MSwxNCBAQA0KPiAgI2luY2x1ZGUgImludGVybmFsLmgiDQo+ICAjaW5jbHVkZSAiZnNj
YWNoZS5oIg0KPiAgI2luY2x1ZGUgInBuZnMuaCINCj4gKyNpbmNsdWRlICJuZnMuaCINCj4gICNp
bmNsdWRlICJuZXRucy5oIg0KPiAgDQo+ICAjZGVmaW5lIE5GU0RCR19GQUNJTElUWQkJTkZTREJH
X0NMSUVOVA0KPiAgDQo+ICBzdGF0aWMgREVDTEFSRV9XQUlUX1FVRVVFX0hFQUQobmZzX2NsaWVu
dF9hY3RpdmVfd3EpOw0KPiArc3RhdGljIERFRklORV9TUElOTE9DSyhuZnNfdmVyc2lvbl9sb2Nr
KTsNCj4gK3N0YXRpYyBMSVNUX0hFQUQobmZzX3ZlcnNpb25zKTsNCj4gICNpZmRlZiBDT05GSUdf
TkZTX1Y0DQo+ICANCj4gIC8qDQo+IEBAIC04OSwxNiArOTIsMTAgQEAgc3RhdGljIGJvb2wgbmZz
NF9kaXNhYmxlX2lkbWFwcGluZyA9IHRydWU7DQo+ICAvKg0KPiAgICogUlBDIGNydWZ0IGZvciBO
RlMNCj4gICAqLw0KPiAtc3RhdGljIGNvbnN0IHN0cnVjdCBycGNfdmVyc2lvbiAqbmZzX3ZlcnNp
b25bNV0gPSB7DQo+IC0jaWZkZWYgQ09ORklHX05GU19WMg0KPiAtCVsyXQkJCT0gJm5mc192ZXJz
aW9uMiwNCj4gLSNlbmRpZg0KPiAtI2lmZGVmIENPTkZJR19ORlNfVjMNCj4gLQlbM10JCQk9ICZu
ZnNfdmVyc2lvbjMsDQo+IC0jZW5kaWYNCj4gLSNpZmRlZiBDT05GSUdfTkZTX1Y0DQo+IC0JWzRd
CQkJPSAmbmZzX3ZlcnNpb240LA0KPiAtI2VuZGlmDQo+ICtzdGF0aWMgc3RydWN0IHJwY192ZXJz
aW9uICpuZnNfdmVyc2lvbls1XSA9IHsNCj4gKwlbMl0gPSBOVUxMLA0KPiArCVszXSA9IE5VTEws
DQo+ICsJWzRdID0gTlVMTCwNCj4gIH07DQo+ICANCj4gIGNvbnN0IHN0cnVjdCBycGNfcHJvZ3Jh
bSBuZnNfcHJvZ3JhbSA9IHsNCj4gQEAgLTExNCwxMCArMTExLDkgQEAgc3RydWN0IHJwY19zdGF0
IG5mc19ycGNzdGF0ID0gew0KPiAgCS5wcm9ncmFtCQk9ICZuZnNfcHJvZ3JhbQ0KPiAgfTsNCj4g
IA0KPiAtDQo+ICAjaWZkZWYgQ09ORklHX05GU19WM19BQ0wNCj4gIHN0YXRpYyBzdHJ1Y3QgcnBj
X3N0YXQJCW5mc2FjbF9ycGNzdGF0ID0geyAmbmZzYWNsX3Byb2dyYW0gfTsNCj4gLXN0YXRpYyBj
b25zdCBzdHJ1Y3QgcnBjX3ZlcnNpb24gKm5mc2FjbF92ZXJzaW9uW10gPSB7DQo+ICtzdGF0aWMg
c3RydWN0IHJwY192ZXJzaW9uICpuZnNhY2xfdmVyc2lvbltdID0gew0KPiAgCVszXQkJCT0gJm5m
c2FjbF92ZXJzaW9uMywNCj4gIH07DQo+ICANCj4gQEAgLTE0MCw2ICsxMzYsODEgQEAgc3RydWN0
IG5mc19jbGllbnRfaW5pdGRhdGEgew0KPiAgCXN0cnVjdCBuZXQgKm5ldDsNCj4gIH07DQo+ICAN
Cj4gK3N0YXRpYyBpbnQgZmluZF9uZnNfdmVyc2lvbihzdHJ1Y3QgbmZzX3N1YnZlcnNpb24gKipu
ZnMsIHVuc2lnbmVkIGludCB2ZXJzaW9uKQ0KPiArew0KPiArCXN0cnVjdCBuZnNfc3VidmVyc2lv
biAqdG1wOw0KPiArCXNwaW5fbG9jaygmbmZzX3ZlcnNpb25fbG9jayk7DQo+ICsNCj4gKwlsaXN0
X2Zvcl9lYWNoX2VudHJ5X3NhZmUoKCpuZnMpLCB0bXAsICZuZnNfdmVyc2lvbnMsIGxpc3QpIHsN
Cj4gKwkJaWYgKCgqbmZzKS0+dmVyc2lvbiA9PSB2ZXJzaW9uKSB7DQo+ICsJCQlzcGluX3VubG9j
aygmbmZzX3ZlcnNpb25fbG9jayk7DQo+ICsJCQlyZXR1cm4gMTsNCj4gKwkJfQ0KPiArCX07DQo+
ICsNCj4gKwlzcGluX3VubG9jaygmbmZzX3ZlcnNpb25fbG9jayk7DQo+ICsJcmV0dXJuIDA7DQo+
ICt9DQo+ICsNCj4gK3N0cnVjdCBuZnNfc3VidmVyc2lvbiAqZ2V0X25mc192ZXJzaW9uKHVuc2ln
bmVkIGludCB2ZXJzaW9uKQ0KPiArew0KPiArCXN0cnVjdCBuZnNfc3VidmVyc2lvbiAqbmZzOw0K
PiArDQo+ICsJaWYgKHRyeV90aGVuX3JlcXVlc3RfbW9kdWxlKGZpbmRfbmZzX3ZlcnNpb24oJm5m
cywgdmVyc2lvbiksICJuZnMlZCIsIHZlcnNpb24pKQ0KPiArCQlyZXR1cm4gbmZzOw0KPiArCXJl
dHVybiBFUlJfUFRSKC1FUFJPVE9OT1NVUFBPUlQpOw0KPiArfQ0KPiArDQo+ICtpbmxpbmUgc3Ry
dWN0IG5mc19zdWJ2ZXJzaW9uICpnZXRfbmZzX2NsaWVudF92ZXJzaW9uKHN0cnVjdCBuZnNfY2xp
ZW50ICpjbHApDQo+ICt7DQo+ICsJcmV0dXJuIGdldF9uZnNfdmVyc2lvbihjbHAtPnJwY19vcHMt
PnZlcnNpb24pOw0KPiArfQ0KPiArDQo+ICtpbmxpbmUgc3RydWN0IG5mc19zdWJ2ZXJzaW9uICpn
ZXRfbmZzX3NlcnZlcl92ZXJzaW9uKHN0cnVjdCBuZnNfc2VydmVyICpzcnYpDQo+ICt7DQo+ICsJ
cmV0dXJuIGdldF9uZnNfY2xpZW50X3ZlcnNpb24oc3J2LT5uZnNfY2xpZW50KTsNCj4gK30NCj4g
Kw0KPiArdm9pZCByZWdpc3Rlcl9uZnNfdmVyc2lvbihzdHJ1Y3QgbmZzX3N1YnZlcnNpb24gKm5m
cykNCj4gK3sNCj4gKwlzcGluX2xvY2soJm5mc192ZXJzaW9uX2xvY2spOw0KPiArDQo+ICsJbGlz
dF9hZGQoJm5mcy0+bGlzdCwgJm5mc192ZXJzaW9ucyk7DQo+ICsJbmZzX3ZlcnNpb25bbmZzLT52
ZXJzaW9uXSA9IG5mcy0+cnBjX3ZlcnM7DQo+ICsNCj4gKwlzcGluX3VubG9jaygmbmZzX3ZlcnNp
b25fbG9jayk7DQo+ICt9DQo+ICtFWFBPUlRfU1lNQk9MX0dQTChyZWdpc3Rlcl9uZnNfdmVyc2lv
bik7DQo+ICsNCj4gK3ZvaWQgdW5yZWdpc3Rlcl9uZnNfdmVyc2lvbihzdHJ1Y3QgbmZzX3N1YnZl
cnNpb24gKm5mcykNCj4gK3sNCj4gKwlzcGluX2xvY2soJm5mc192ZXJzaW9uX2xvY2spOw0KPiAr
DQo+ICsJbmZzX3ZlcnNpb25bbmZzLT52ZXJzaW9uXSA9IE5VTEw7DQo+ICsJbGlzdF9kZWwoJm5m
cy0+bGlzdCk7DQo+ICsNCj4gKwlzcGluX3VubG9jaygmbmZzX3ZlcnNpb25fbG9jayk7DQo+ICt9
DQo+ICtFWFBPUlRfU1lNQk9MX0dQTCh1bnJlZ2lzdGVyX25mc192ZXJzaW9uKTsNCj4gKw0KPiAr
LyoNCj4gKyAqIFByZWxvYWQgYWxsIGNvbmZpZ3VyZWQgTkZTIHZlcnNpb25zIGR1cmluZyBtb2R1
bGUgaW5pdC4NCj4gKyAqIFRoaXMgZnVuY3Rpb24gc2hvdWxkIGJlIGVkaXRlZCBhZnRlciBlYWNo
IHByb3RvY29sIGlzIGNvbnZlcnRlZCwNCj4gKyAqIGFuZCBldmVudHVhbGx5IHJlbW92ZWQuDQo+
ICsgKi8NCj4gK3ZvaWQgX19pbml0IG5mc19yZWdpc3Rlcl92ZXJzaW9ucyh2b2lkKQ0KPiArew0K
PiArI2lmZGVmIENPTkZJR19ORlNfVjINCj4gKwlpbml0X25mc192MigpOw0KPiArI2VuZGlmDQo+
ICsjaWZkZWYgQ09ORklHX05GU19WMw0KPiArCWluaXRfbmZzX3YzKCk7DQo+ICsjZW5kaWYNCj4g
KyNpZmRlZiBDT05GSUdfTkZTX1Y0DQo+ICsJaW5pdF9uZnNfdjQoKTsNCj4gKyNlbmRpZg0KPiAr
fQ0KPiArDQo+ICAvKg0KPiAgICogQWxsb2NhdGUgYSBzaGFyZWQgY2xpZW50IHJlY29yZA0KPiAg
ICoNCj4gQEAgLTg1NSwyMSArOTI2LDE1IEBAIHN0YXRpYyBpbnQgbmZzX2luaXRfc2VydmVyKHN0
cnVjdCBuZnNfc2VydmVyICpzZXJ2ZXIsDQo+ICAJfTsNCj4gIAlzdHJ1Y3QgcnBjX3RpbWVvdXQg
dGltZXBhcm1zOw0KPiAgCXN0cnVjdCBuZnNfY2xpZW50ICpjbHA7DQo+ICsJc3RydWN0IG5mc19z
dWJ2ZXJzaW9uICpuZnNfbW9kOw0KPiAgCWludCBlcnJvcjsNCj4gIA0KPiAgCWRwcmludGsoIi0t
PiBuZnNfaW5pdF9zZXJ2ZXIoKVxuIik7DQo+ICANCj4gLQ0KPiAtI2lmZGVmIENPTkZJR19ORlNf
VjINCj4gLQlpZiAoZGF0YS0+dmVyc2lvbiA9PSAyKQ0KPiAtCQljbF9pbml0LnJwY19vcHMgPSAm
bmZzX3YyX2NsaWVudG9wczsNCj4gLSNlbmRpZg0KPiAtI2lmZGVmIENPTkZJR19ORlNfVjMNCj4g
LQlpZiAoZGF0YS0+dmVyc2lvbiA9PSAzKQ0KPiAtCQljbF9pbml0LnJwY19vcHMgPSAmbmZzX3Yz
X2NsaWVudG9wczsNCj4gLSNlbmRpZg0KPiAtCWlmIChjbF9pbml0LnJwY19vcHMgPT0gTlVMTCkN
Cj4gLQkJcmV0dXJuIC1FUFJPVE9OT1NVUFBPUlQ7DQo+ICsJbmZzX21vZCA9IGdldF9uZnNfdmVy
c2lvbihkYXRhLT52ZXJzaW9uKTsNCj4gKwlpZiAoSVNfRVJSKG5mc19tb2QpKQ0KPiArCQlyZXR1
cm4gUFRSX0VSUihuZnNfbW9kKTsNCj4gKwljbF9pbml0LnJwY19vcHMgPSBuZnNfbW9kLT5ycGNf
b3BzOw0KPiAgDQo+ICAJbmZzX2luaXRfdGltZW91dF92YWx1ZXMoJnRpbWVwYXJtcywgZGF0YS0+
bmZzX3NlcnZlci5wcm90b2NvbCwNCj4gIAkJCWRhdGEtPnRpbWVvLCBkYXRhLT5yZXRyYW5zKTsN
Cj4gZGlmZiAtLWdpdCBhL2ZzL25mcy9pbm9kZS5jIGIvZnMvbmZzL2lub2RlLmMNCj4gaW5kZXgg
N2JiNGQxMy4uMDJhMWM0MyAxMDA2NDQNCj4gLS0tIGEvZnMvbmZzL2lub2RlLmMNCj4gKysrIGIv
ZnMvbmZzL2lub2RlLmMNCj4gQEAgLTUyLDYgKzUyLDcgQEANCj4gICNpbmNsdWRlICJmc2NhY2hl
LmgiDQo+ICAjaW5jbHVkZSAiZG5zX3Jlc29sdmUuaCINCj4gICNpbmNsdWRlICJwbmZzLmgiDQo+
ICsjaW5jbHVkZSAibmZzLmgiDQo+ICAjaW5jbHVkZSAibmV0bnMuaCINCj4gIA0KPiAgI2RlZmlu
ZSBORlNEQkdfRkFDSUxJVFkJCU5GU0RCR19WRlMNCj4gQEAgLTE2OTUsNiArMTY5Niw3IEBAIHN0
YXRpYyBpbnQgX19pbml0IGluaXRfbmZzX2ZzKHZvaWQpDQo+ICAjZW5kaWYNCj4gIAlpZiAoKGVy
ciA9IHJlZ2lzdGVyX25mc19mcygpKSAhPSAwKQ0KPiAgCQlnb3RvIG91dDsNCj4gKwluZnNfcmVn
aXN0ZXJfdmVyc2lvbnMoKTsNCj4gIAlyZXR1cm4gMDsNCj4gIG91dDoNCj4gICNpZmRlZiBDT05G
SUdfUFJPQ19GUw0KPiBkaWZmIC0tZ2l0IGEvZnMvbmZzL21vdW50X2NsbnQuYyBiL2ZzL25mcy9t
b3VudF9jbG50LmMNCj4gaW5kZXggOGU2NWM3Zi4uZGRjN2QxOSAxMDA2NDQNCj4gLS0tIGEvZnMv
bmZzL21vdW50X2NsbnQuYw0KPiArKysgYi9mcy9uZnMvbW91bnRfY2xudC5jDQo+IEBAIC00ODgs
MTkgKzQ4OCwxOSBAQCBzdGF0aWMgc3RydWN0IHJwY19wcm9jaW5mbyBtbnQzX3Byb2NlZHVyZXNb
XSA9IHsNCj4gIH07DQo+ICANCj4gDQo+IC1zdGF0aWMgY29uc3Qgc3RydWN0IHJwY192ZXJzaW9u
IG1udF92ZXJzaW9uMSA9IHsNCj4gK3N0YXRpYyBzdHJ1Y3QgcnBjX3ZlcnNpb24gbW50X3ZlcnNp
b24xID0gew0KPiAgCS5udW1iZXIJCT0gMSwNCj4gIAkubnJwcm9jcwk9IEFSUkFZX1NJWkUobW50
X3Byb2NlZHVyZXMpLA0KPiAgCS5wcm9jcwkJPSBtbnRfcHJvY2VkdXJlcywNCj4gIH07DQo+ICAN
Cj4gLXN0YXRpYyBjb25zdCBzdHJ1Y3QgcnBjX3ZlcnNpb24gbW50X3ZlcnNpb24zID0gew0KPiAr
c3RhdGljIHN0cnVjdCBycGNfdmVyc2lvbiBtbnRfdmVyc2lvbjMgPSB7DQo+ICAJLm51bWJlcgkJ
PSAzLA0KPiAgCS5ucnByb2NzCT0gQVJSQVlfU0laRShtbnQzX3Byb2NlZHVyZXMpLA0KPiAgCS5w
cm9jcwkJPSBtbnQzX3Byb2NlZHVyZXMsDQo+ICB9Ow0KPiAgDQo+IC1zdGF0aWMgY29uc3Qgc3Ry
dWN0IHJwY192ZXJzaW9uICptbnRfdmVyc2lvbltdID0gew0KPiArc3RhdGljIHN0cnVjdCBycGNf
dmVyc2lvbiAqbW50X3ZlcnNpb25bXSA9IHsNCj4gIAlOVUxMLA0KPiAgCSZtbnRfdmVyc2lvbjEs
DQo+ICAJTlVMTCwNCj4gZGlmZiAtLWdpdCBhL2ZzL25mcy9uZnMuaCBiL2ZzL25mcy9uZnMuaA0K
PiBuZXcgZmlsZSBtb2RlIDEwMDY0NA0KPiBpbmRleCAwMDAwMDAwLi4wNWY2ODQ5DQo+IC0tLSAv
ZGV2L251bGwNCj4gKysrIGIvZnMvbmZzL25mcy5oDQo+IEBAIC0wLDAgKzEsMzUgQEANCj4gKy8q
DQo+ICsgKiBDb3B5cmlnaHQgKGMpIDIwMTIgTmV0YXBwLCBJbmMuIEFsbCByaWdodHMgcmVzZXJ2
ZWQuDQo+ICsgKg0KPiArICogRnVuY3Rpb24gYW5kIHN0cnVjdHVyZXMgZXhwb3J0ZWQgYnkgdGhl
IE5GUyBtb2R1bGUNCj4gKyAqIGZvciB1c2UgYnkgTkZTIHZlcnNpb24tc3BlY2lmaWMgbW9kdWxl
cy4NCj4gKyAqLw0KPiArI2lmbmRlZiBfX0xJTlVYX0lOVEVSTkFMX05GU19IDQo+ICsjZGVmaW5l
IF9fTElOVVhfSU5URVJOQUxfTkZTX0gNCj4gKw0KPiArI2luY2x1ZGUgPGxpbnV4L2ZzLmg+DQo+
ICsjaW5jbHVkZSA8bGludXgvc3VucnBjL3NjaGVkLmg+DQo+ICsjaW5jbHVkZSA8bGludXgvbmZz
X3hkci5oPg0KPiArDQo+ICtzdHJ1Y3QgbmZzX3N1YnZlcnNpb24gew0KPiArCXVuc2lnbmVkIGlu
dCB2ZXJzaW9uOwkJLyogUHJvdG9jb2wgbnVtYmVyICovDQpXb24ndCB0aGlzIGJlIGEgZHVwbGlj
YXRlIG9mIHdoYXQgd2UgYWxyZWFkeSBoYXZlIGluIHRoZSBycGNfb3BzPw0KDQo+ICsJc3RydWN0
IHJwY192ZXJzaW9uICpycGNfdmVyczsJLyogTkZTIHZlcnNpb24gaW5mb3JtYXRpb24gKi8NCj4g
Kwljb25zdCBzdHJ1Y3QgbmZzX3JwY19vcHMgKnJwY19vcHM7CS8qIE5GUyBvcGVyYXRpb25zICov
DQo+ICsJc3RydWN0IGxpc3RfaGVhZCBsaXN0OwkJLyogTGlzdCBvZiBORlMgdmVyc2lvbnMgKi8N
Cj4gKw0KPiArCXZvaWQgKCpyZWZlcmVuY2UpKHZvaWQpOwkvKiBGb3IgcmVmZXJlbmNlIGNvdW50
aW5nICovDQo+ICsJdm9pZCAoKnVucmVmZXJlbmNlKSh2b2lkKTsJLyogQWxzbyBmb3IgcmVmZXJl
bmNlIGNvdW50aW5nICovDQoNCllvdSBhcmUgYWx3YXlzIGp1c3QgZ29pbmcgdG8gcGluIGFuZCB1
bnBpbiB0aGUgbW9kdWxlLCBzbyB3aHkgZG8gdGhleQ0KbmVlZCB0byBiZSBmdW5jdGlvbiBwb2lu
dGVycz8gSnVzdCBoYXZlIGVhY2ggbW9kdWxlIHN0b3JlIGEgcG9pbnRlciB0bw0KVEhJU19NT0RV
TEUgaW4gdGhlIGFib3ZlIHN0cnVjdHVyZSBpbnN0ZWFkLg0KDQo+ICt9Ow0KPiArDQo+ICt2b2lk
IG5mc19yZWdpc3Rlcl92ZXJzaW9ucyh2b2lkKTsNCj4gK2ludCBpbml0X25mc192Mih2b2lkKTsN
Cj4gK2ludCBpbml0X25mc192Myh2b2lkKTsNCj4gK2ludCBpbml0X25mc192NCh2b2lkKTsNCj4g
Kw0KPiArc3RydWN0IG5mc19zdWJ2ZXJzaW9uICpnZXRfbmZzX3ZlcnNpb24odW5zaWduZWQgaW50
KTsNCj4gK3N0cnVjdCBuZnNfc3VidmVyc2lvbiAqZ2V0X25mc19jbGllbnRfdmVyc2lvbihzdHJ1
Y3QgbmZzX2NsaWVudCAqKTsNCj4gK3N0cnVjdCBuZnNfc3VidmVyc2lvbiAqZ2V0X25mc19zZXJ2
ZXJfdmVyc2lvbihzdHJ1Y3QgbmZzX3NlcnZlciAqKTsNCj4gK3ZvaWQgcmVnaXN0ZXJfbmZzX3Zl
cnNpb24oc3RydWN0IG5mc19zdWJ2ZXJzaW9uICopOw0KPiArdm9pZCB1bnJlZ2lzdGVyX25mc192
ZXJzaW9uKHN0cnVjdCBuZnNfc3VidmVyc2lvbiAqKTsNCj4gKw0KPiArI2VuZGlmIC8qIF9fTElO
VVhfSU5URVJOQUxfTkZTX0ggKi8NCj4gZGlmZiAtLWdpdCBhL2ZzL25mcy9uZnMyc3VwZXIuYyBi
L2ZzL25mcy9uZnMyc3VwZXIuYw0KPiBuZXcgZmlsZSBtb2RlIDEwMDY0NA0KPiBpbmRleCAwMDAw
MDAwLi4xMmZhOTA2DQo+IC0tLSAvZGV2L251bGwNCj4gKysrIGIvZnMvbmZzL25mczJzdXBlci5j
DQo+IEBAIC0wLDAgKzEsMzEgQEANCj4gKy8qDQo+ICsgKiBDb3B5cmlnaHQgKGMpIDIwMTIgTmV0
YXBwLCBJbmMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQo+ICsgKi8NCj4gKyNpbmNsdWRlIDxsaW51
eC9tb2R1bGUuaD4NCj4gKyNpbmNsdWRlIDxsaW51eC9uZnNfZnMuaD4NCj4gKyNpbmNsdWRlICJu
ZnMuaCINCj4gKw0KPiArc3RhdGljIHZvaWQgbmZzMl9yZWZlcmVuY2Uodm9pZCkNCj4gK3sNCj4g
Kwl0cnlfbW9kdWxlX2dldChUSElTX01PRFVMRSk7DQo+ICt9DQo+ICsNCj4gK3N0YXRpYyB2b2lk
IG5mczJfdW5yZWZlcmVuY2Uodm9pZCkNCj4gK3sNCj4gKwltb2R1bGVfcHV0KFRISVNfTU9EVUxF
KTsNCj4gK30NCj4gKw0KPiArc3RhdGljIHN0cnVjdCBuZnNfc3VidmVyc2lvbiBuZnNfdjIgPSB7
DQo+ICsJLnZlcnNpb24gID0gMiwNCj4gKwkucnBjX3ZlcnMgPSAmbmZzX3ZlcnNpb24yLA0KPiAr
CS5ycGNfb3BzICA9ICZuZnNfdjJfY2xpZW50b3BzLA0KPiArDQo+ICsJLnJlZmVyZW5jZSA9IG5m
czJfcmVmZXJlbmNlLA0KPiArCS51bnJlZmVyZW5jZSA9IG5mczJfdW5yZWZlcmVuY2UsDQo+ICt9
Ow0KPiArDQo+ICtpbnQgX19pbml0IGluaXRfbmZzX3YyKHZvaWQpDQo+ICt7DQo+ICsJcmVnaXN0
ZXJfbmZzX3ZlcnNpb24oJm5mc192Mik7DQo+ICsJcmV0dXJuIDA7DQo+ICt9DQo+IGRpZmYgLS1n
aXQgYS9mcy9uZnMvbmZzMnhkci5jIGIvZnMvbmZzL25mczJ4ZHIuYw0KPiBpbmRleCBhMDEwODRk
Li41ZDllYzhiIDEwMDY0NA0KPiAtLS0gYS9mcy9uZnMvbmZzMnhkci5jDQo+ICsrKyBiL2ZzL25m
cy9uZnMyeGRyLmMNCj4gQEAgLTEwODYsNyArMTA4Niw3IEBAIHN0cnVjdCBycGNfcHJvY2luZm8J
bmZzX3Byb2NlZHVyZXNbXSA9IHsNCj4gIAlQUk9DKFNUQVRGUywJZmhhbmRsZSwJc3RhdGZzcmVz
LAkwKSwNCj4gIH07DQo+ICANCj4gLWNvbnN0IHN0cnVjdCBycGNfdmVyc2lvbiBuZnNfdmVyc2lv
bjIgPSB7DQo+ICtzdHJ1Y3QgcnBjX3ZlcnNpb24gbmZzX3ZlcnNpb24yID0gew0KPiAgCS5udW1i
ZXIJCQk9IDIsDQo+ICAJLm5ycHJvY3MJCT0gQVJSQVlfU0laRShuZnNfcHJvY2VkdXJlcyksDQo+
ICAJLnByb2NzCQkJPSBuZnNfcHJvY2VkdXJlcw0KPiBkaWZmIC0tZ2l0IGEvZnMvbmZzL25mczNz
dXBlci5jIGIvZnMvbmZzL25mczNzdXBlci5jDQo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0DQo+IGlu
ZGV4IDAwMDAwMDAuLmEwMmM4MTUNCj4gLS0tIC9kZXYvbnVsbA0KPiArKysgYi9mcy9uZnMvbmZz
M3N1cGVyLmMNCj4gQEAgLTAsMCArMSwzMSBAQA0KPiArLyoNCj4gKyAqIENvcHlyaWdodCAoYykg
MjAxMiBOZXRhcHAsIEluYy4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCj4gKyAqLw0KPiArI2luY2x1
ZGUgPGxpbnV4L21vZHVsZS5oPg0KPiArI2luY2x1ZGUgPGxpbnV4L25mc19mcy5oPg0KPiArI2lu
Y2x1ZGUgIm5mcy5oIg0KPiArDQo+ICtzdGF0aWMgdm9pZCBuZnMzX3JlZmVyZW5jZSh2b2lkKQ0K
PiArew0KPiArCXRyeV9tb2R1bGVfZ2V0KFRISVNfTU9EVUxFKTsNCj4gK30NCj4gKw0KPiArc3Rh
dGljIHZvaWQgbmZzM191bnJlZmVyZW5jZSh2b2lkKQ0KPiArew0KPiArCW1vZHVsZV9wdXQoVEhJ
U19NT0RVTEUpOw0KPiArfQ0KPiArDQo+ICtzdGF0aWMgc3RydWN0IG5mc19zdWJ2ZXJzaW9uIG5m
c192MyA9IHsNCj4gKwkudmVyc2lvbiAgPSAzLA0KPiArCS5ycGNfdmVycyA9ICZuZnNfdmVyc2lv
bjMsDQo+ICsJLnJwY19vcHMgID0gJm5mc192M19jbGllbnRvcHMsDQo+ICsNCj4gKwkucmVmZXJl
bmNlID0gbmZzM19yZWZlcmVuY2UsDQo+ICsJLnVucmVmZXJlbmNlID0gbmZzM191bnJlZmVyZW5j
ZSwNCj4gK307DQo+ICsNCj4gK2ludCBfX2luaXQgaW5pdF9uZnNfdjModm9pZCkNCj4gK3sNCj4g
KwlyZWdpc3Rlcl9uZnNfdmVyc2lvbigmbmZzX3YzKTsNCj4gKwlyZXR1cm4gMDsNCj4gK30NCj4g
ZGlmZiAtLWdpdCBhL2ZzL25mcy9uZnMzeGRyLmMgYi9mcy9uZnMvbmZzM3hkci5jDQo+IGluZGV4
IGE3N2NjOWEuLjVmOWFhYmQgMTAwNjQ0DQo+IC0tLSBhL2ZzL25mcy9uZnMzeGRyLmMNCj4gKysr
IGIvZnMvbmZzL25mczN4ZHIuYw0KPiBAQCAtMjQ2MSw3ICsyNDYxLDcgQEAgc3RydWN0IHJwY19w
cm9jaW5mbwluZnMzX3Byb2NlZHVyZXNbXSA9IHsNCj4gIAlQUk9DKENPTU1JVCwJCWNvbW1pdCwJ
CWNvbW1pdCwJCTUpLA0KPiAgfTsNCj4gIA0KPiAtY29uc3Qgc3RydWN0IHJwY192ZXJzaW9uIG5m
c192ZXJzaW9uMyA9IHsNCj4gK3N0cnVjdCBycGNfdmVyc2lvbiBuZnNfdmVyc2lvbjMgPSB7DQo+
ICAJLm51bWJlcgkJCT0gMywNCj4gIAkubnJwcm9jcwkJPSBBUlJBWV9TSVpFKG5mczNfcHJvY2Vk
dXJlcyksDQo+ICAJLnByb2NzCQkJPSBuZnMzX3Byb2NlZHVyZXMNCj4gQEAgLTI0ODksNyArMjQ4
OSw3IEBAIHN0YXRpYyBzdHJ1Y3QgcnBjX3Byb2NpbmZvCW5mczNfYWNsX3Byb2NlZHVyZXNbXSA9
IHsNCj4gIAl9LA0KPiAgfTsNCj4gIA0KPiAtY29uc3Qgc3RydWN0IHJwY192ZXJzaW9uIG5mc2Fj
bF92ZXJzaW9uMyA9IHsNCj4gK3N0cnVjdCBycGNfdmVyc2lvbiBuZnNhY2xfdmVyc2lvbjMgPSB7
DQo+ICAJLm51bWJlcgkJCT0gMywNCj4gIAkubnJwcm9jcwkJPSBzaXplb2YobmZzM19hY2xfcHJv
Y2VkdXJlcykvDQo+ICAJCQkJICBzaXplb2YobmZzM19hY2xfcHJvY2VkdXJlc1swXSksDQo+IGRp
ZmYgLS1naXQgYS9mcy9uZnMvbmZzNHN1cGVyLmMgYi9mcy9uZnMvbmZzNHN1cGVyLmMNCj4gbmV3
IGZpbGUgbW9kZSAxMDA2NDQNCj4gaW5kZXggMDAwMDAwMC4uOWIyYTY3OQ0KPiAtLS0gL2Rldi9u
dWxsDQo+ICsrKyBiL2ZzL25mcy9uZnM0c3VwZXIuYw0KPiBAQCAtMCwwICsxLDMxIEBADQo+ICsv
Kg0KPiArICogQ29weXJpZ2h0IChjKSAyMDEyIE5ldGFwcCwgSW5jLiBBbGwgcmlnaHRzIHJlc2Vy
dmVkLg0KPiArICovDQo+ICsjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+DQo+ICsjaW5jbHVkZSA8
bGludXgvbmZzX2ZzLmg+DQo+ICsjaW5jbHVkZSAibmZzLmgiDQo+ICsNCj4gK3N0YXRpYyB2b2lk
IG5mczRfcmVmZXJlbmNlKHZvaWQpDQo+ICt7DQo+ICsJdHJ5X21vZHVsZV9nZXQoVEhJU19NT0RV
TEUpOw0KPiArfQ0KPiArDQo+ICtzdGF0aWMgdm9pZCBuZnM0X3VucmVmZXJlbmNlKHZvaWQpDQo+
ICt7DQo+ICsJbW9kdWxlX3B1dChUSElTX01PRFVMRSk7DQo+ICt9DQo+ICsNCj4gK3N0YXRpYyBz
dHJ1Y3QgbmZzX3N1YnZlcnNpb24gbmZzX3Y0ID0gew0KPiArCS52ZXJzaW9uICA9IDQsDQo+ICsJ
LnJwY192ZXJzID0gJm5mc192ZXJzaW9uNCwNCj4gKwkucnBjX29wcyAgPSAmbmZzX3Y0X2NsaWVu
dG9wcywNCj4gKw0KPiArCS5yZWZlcmVuY2UgPSBuZnM0X3JlZmVyZW5jZSwNCj4gKwkudW5yZWZl
cmVuY2UgPSBuZnM0X3VucmVmZXJlbmNlLA0KPiArfTsNCj4gKw0KPiAraW50IF9faW5pdCBpbml0
X25mc192NCh2b2lkKQ0KPiArew0KPiArCXJlZ2lzdGVyX25mc192ZXJzaW9uKCZuZnNfdjQpOw0K
PiArCXJldHVybiAwOw0KPiArfQ0KPiBkaWZmIC0tZ2l0IGEvZnMvbmZzL25mczR4ZHIuYyBiL2Zz
L25mcy9uZnM0eGRyLmMNCj4gaW5kZXggYzc0ZmRiMS4uY2ZkMzMzYyAxMDA2NDQNCj4gLS0tIGEv
ZnMvbmZzL25mczR4ZHIuYw0KPiArKysgYi9mcy9uZnMvbmZzNHhkci5jDQo+IEBAIC03MDcxLDcg
KzcwNzEsNyBAQCBzdHJ1Y3QgcnBjX3Byb2NpbmZvCW5mczRfcHJvY2VkdXJlc1tdID0gew0KPiAg
I2VuZGlmIC8qIENPTkZJR19ORlNfVjRfMSAqLw0KPiAgfTsNCj4gIA0KPiAtY29uc3Qgc3RydWN0
IHJwY192ZXJzaW9uIG5mc192ZXJzaW9uNCA9IHsNCj4gK3N0cnVjdCBycGNfdmVyc2lvbiBuZnNf
dmVyc2lvbjQgPSB7DQo+ICAJLm51bWJlcgkJCT0gNCwNCj4gIAkubnJwcm9jcwkJPSBBUlJBWV9T
SVpFKG5mczRfcHJvY2VkdXJlcyksDQo+ICAJLnByb2NzCQkJPSBuZnM0X3Byb2NlZHVyZXMNCj4g
ZGlmZiAtLWdpdCBhL2ZzL25mcy9zdXBlci5jIGIvZnMvbmZzL3N1cGVyLmMNCj4gaW5kZXggYWFj
NDAzMC4uNWFiN2MwZCAxMDA2NDQNCj4gLS0tIGEvZnMvbmZzL3N1cGVyLmMNCj4gKysrIGIvZnMv
bmZzL3N1cGVyLmMNCj4gQEAgLTY1LDYgKzY1LDcgQEANCj4gICNpbmNsdWRlICJpbnRlcm5hbC5o
Ig0KPiAgI2luY2x1ZGUgImZzY2FjaGUuaCINCj4gICNpbmNsdWRlICJwbmZzLmgiDQo+ICsjaW5j
bHVkZSAibmZzLmgiDQo+ICANCj4gICNkZWZpbmUgTkZTREJHX0ZBQ0lMSVRZCQlORlNEQkdfVkZT
DQo+ICANCj4gQEAgLTIyODQsNiArMjI4NSwyMiBAQCBzdGF0aWMgaW50IG5mc19iZGlfcmVnaXN0
ZXIoc3RydWN0IG5mc19zZXJ2ZXIgKnNlcnZlcikNCj4gIAlyZXR1cm4gYmRpX3JlZ2lzdGVyX2Rl
digmc2VydmVyLT5iYWNraW5nX2Rldl9pbmZvLCBzZXJ2ZXItPnNfZGV2KTsNCj4gIH0NCj4gIA0K
PiArc3RhdGljIGludCBuZnNfcmVnaXN0ZXIoc3RydWN0IG5mc19zZXJ2ZXIgKnNlcnZlcikNCj4g
K3sNCj4gKwlzdHJ1Y3QgbmZzX3N1YnZlcnNpb24gKm5mc19tb2QgPSBnZXRfbmZzX3NlcnZlcl92
ZXJzaW9uKHNlcnZlcik7DQo+ICsJaW50IGVyciA9IG5mc19iZGlfcmVnaXN0ZXIoc2VydmVyKTsN
Cj4gKwlpZiAoIWVycikNCj4gKwkJbmZzX21vZC0+cmVmZXJlbmNlKCk7DQo+ICsJcmV0dXJuIGVy
cjsNCj4gK30NCj4gKw0KPiArc3RhdGljIHZvaWQgbmZzX3VucmVnaXN0ZXIoc3RydWN0IG5mc19z
ZXJ2ZXIgKnNlcnZlcikNCj4gK3sNCj4gKwlzdHJ1Y3QgbmZzX3N1YnZlcnNpb24gKm5mc19tb2Qg
PSBnZXRfbmZzX3NlcnZlcl92ZXJzaW9uKHNlcnZlcik7DQo+ICsJYmRpX3VucmVnaXN0ZXIoJnNl
cnZlci0+YmFja2luZ19kZXZfaW5mbyk7DQo+ICsJbmZzX21vZC0+dW5yZWZlcmVuY2UoKTsNCj4g
K30NCj4gKw0KPiAgc3RhdGljIHN0cnVjdCBkZW50cnkgKm5mc19mc19tb3VudChzdHJ1Y3QgZmls
ZV9zeXN0ZW1fdHlwZSAqZnNfdHlwZSwNCj4gIAlpbnQgZmxhZ3MsIGNvbnN0IGNoYXIgKmRldl9u
YW1lLCB2b2lkICpyYXdfZGF0YSkNCj4gIHsNCj4gQEAgLTIyOTYsNiArMjMxMyw3IEBAIHN0YXRp
YyBzdHJ1Y3QgZGVudHJ5ICpuZnNfZnNfbW91bnQoc3RydWN0IGZpbGVfc3lzdGVtX3R5cGUgKmZz
X3R5cGUsDQo+ICAJc3RydWN0IG5mc19zYl9tb3VudGRhdGEgc2JfbW50ZGF0YSA9IHsNCj4gIAkJ
Lm1udGZsYWdzID0gZmxhZ3MsDQo+ICAJfTsNCj4gKwlzdHJ1Y3QgbmZzX3N1YnZlcnNpb24gKm5m
c19tb2Q7DQo+ICAJaW50IGVycm9yOw0KPiAgDQo+ICAJZGF0YSA9IG5mc19hbGxvY19wYXJzZWRf
bW91bnRfZGF0YShORlNfREVGQVVMVF9WRVJTSU9OKTsNCj4gQEAgLTIzMTAsNiArMjMyOCwxMiBA
QCBzdGF0aWMgc3RydWN0IGRlbnRyeSAqbmZzX2ZzX21vdW50KHN0cnVjdCBmaWxlX3N5c3RlbV90
eXBlICpmc190eXBlLA0KPiAgCQlnb3RvIG91dDsNCj4gIAl9DQo+ICANCj4gKwluZnNfbW9kID0g
Z2V0X25mc192ZXJzaW9uKGRhdGEtPnZlcnNpb24pOw0KPiArCWlmIChJU19FUlIobmZzX21vZCkp
IHsNCj4gKwkJbW50cm9vdCA9IChzdHJ1Y3QgZGVudHJ5ICopbmZzX21vZDsNCj4gKwkJZ290byBv
dXQ7DQo+ICsJfQ0KPiArDQo+ICAjaWZkZWYgQ09ORklHX05GU19WNA0KPiAgCWlmIChkYXRhLT52
ZXJzaW9uID09IDQpIHsNCj4gIAkJbW50cm9vdCA9IG5mczRfdHJ5X21vdW50KGZsYWdzLCBkZXZf
bmFtZSwgZGF0YSk7DQo+IEBAIC0yMzQzLDcgKzIzNjcsNyBAQCBzdGF0aWMgc3RydWN0IGRlbnRy
eSAqbmZzX2ZzX21vdW50KHN0cnVjdCBmaWxlX3N5c3RlbV90eXBlICpmc190eXBlLA0KPiAgCQlu
ZnNfZnJlZV9zZXJ2ZXIoc2VydmVyKTsNCj4gIAkJc2VydmVyID0gTlVMTDsNCj4gIAl9IGVsc2Ug
ew0KPiAtCQllcnJvciA9IG5mc19iZGlfcmVnaXN0ZXIoc2VydmVyKTsNCj4gKwkJZXJyb3IgPSBu
ZnNfcmVnaXN0ZXIoc2VydmVyKTsNCj4gIAkJaWYgKGVycm9yKSB7DQo+ICAJCQltbnRyb290ID0g
RVJSX1BUUihlcnJvcik7DQo+ICAJCQlnb3RvIGVycm9yX3NwbGF0X2JkaTsNCj4gQEAgLTIzODAs
NyArMjQwNCw3IEBAIGVycm9yX3NwbGF0X3Jvb3Q6DQo+ICAJbW50cm9vdCA9IEVSUl9QVFIoZXJy
b3IpOw0KPiAgZXJyb3Jfc3BsYXRfc3VwZXI6DQo+ICAJaWYgKHNlcnZlciAmJiAhcy0+c19yb290
KQ0KPiAtCQliZGlfdW5yZWdpc3Rlcigmc2VydmVyLT5iYWNraW5nX2Rldl9pbmZvKTsNCj4gKwkJ
bmZzX3VucmVnaXN0ZXIoc2VydmVyKTsNCj4gIGVycm9yX3NwbGF0X2JkaToNCj4gIAlkZWFjdGl2
YXRlX2xvY2tlZF9zdXBlcihzKTsNCj4gIAlnb3RvIG91dDsNCj4gQEAgLTIzOTIsOSArMjQxNiw3
IEBAIGVycm9yX3NwbGF0X2JkaToNCj4gICAqLw0KPiAgc3RhdGljIHZvaWQgbmZzX3B1dF9zdXBl
cihzdHJ1Y3Qgc3VwZXJfYmxvY2sgKnMpDQo+ICB7DQo+IC0Jc3RydWN0IG5mc19zZXJ2ZXIgKnNl
cnZlciA9IE5GU19TQihzKTsNCj4gLQ0KPiAtCWJkaV91bnJlZ2lzdGVyKCZzZXJ2ZXItPmJhY2tp
bmdfZGV2X2luZm8pOw0KPiArCW5mc191bnJlZ2lzdGVyKE5GU19TQihzKSk7DQo+ICB9DQo+ICAN
Cj4gIC8qDQo+IEBAIC0yNDU0LDcgKzI0NzYsNyBAQCBuZnNfeGRldl9tb3VudChzdHJ1Y3QgZmls
ZV9zeXN0ZW1fdHlwZSAqZnNfdHlwZSwgaW50IGZsYWdzLA0KPiAgCQluZnNfZnJlZV9zZXJ2ZXIo
c2VydmVyKTsNCj4gIAkJc2VydmVyID0gTlVMTDsNCj4gIAl9IGVsc2Ugew0KPiAtCQllcnJvciA9
IG5mc19iZGlfcmVnaXN0ZXIoc2VydmVyKTsNCj4gKwkJZXJyb3IgPSBuZnNfcmVnaXN0ZXIoc2Vy
dmVyKTsNCj4gIAkJaWYgKGVycm9yKQ0KPiAgCQkJZ290byBlcnJvcl9zcGxhdF9iZGk7DQo+ICAJ
fQ0KPiBAQCAtMjQ5Miw3ICsyNTE0LDcgQEAgb3V0X2Vycl9ub3NlcnZlcjoNCj4gIA0KPiAgZXJy
b3Jfc3BsYXRfc3VwZXI6DQo+ICAJaWYgKHNlcnZlciAmJiAhcy0+c19yb290KQ0KPiAtCQliZGlf
dW5yZWdpc3Rlcigmc2VydmVyLT5iYWNraW5nX2Rldl9pbmZvKTsNCj4gKwkJbmZzX3VucmVnaXN0
ZXIoc2VydmVyKTsNCj4gIGVycm9yX3NwbGF0X2JkaToNCj4gIAlkZWFjdGl2YXRlX2xvY2tlZF9z
dXBlcihzKTsNCj4gIAlkcHJpbnRrKCI8LS0gbmZzX3hkZXZfbW91bnQoKSA9ICVkIFtzcGxhdF1c
biIsIGVycm9yKTsNCj4gQEAgLTI3MTcsNyArMjczOSw3IEBAIG5mczRfcmVtb3RlX21vdW50KHN0
cnVjdCBmaWxlX3N5c3RlbV90eXBlICpmc190eXBlLCBpbnQgZmxhZ3MsDQo+ICAJCW5mc19mcmVl
X3NlcnZlcihzZXJ2ZXIpOw0KPiAgCQlzZXJ2ZXIgPSBOVUxMOw0KPiAgCX0gZWxzZSB7DQo+IC0J
CWVycm9yID0gbmZzX2JkaV9yZWdpc3RlcihzZXJ2ZXIpOw0KPiArCQllcnJvciA9IG5mc19yZWdp
c3RlcihzZXJ2ZXIpOw0KPiAgCQlpZiAoZXJyb3IpDQo+ICAJCQlnb3RvIGVycm9yX3NwbGF0X2Jk
aTsNCj4gIAl9DQo+IEBAIC0yNzU1LDcgKzI3NzcsNyBAQCBlcnJvcl9zcGxhdF9yb290Og0KPiAg
CWRwdXQobW50cm9vdCk7DQo+ICBlcnJvcl9zcGxhdF9zdXBlcjoNCj4gIAlpZiAoc2VydmVyICYm
ICFzLT5zX3Jvb3QpDQo+IC0JCWJkaV91bnJlZ2lzdGVyKCZzZXJ2ZXItPmJhY2tpbmdfZGV2X2lu
Zm8pOw0KPiArCQluZnNfdW5yZWdpc3RlcihzZXJ2ZXIpOw0KPiAgZXJyb3Jfc3BsYXRfYmRpOg0K
PiAgCWRlYWN0aXZhdGVfbG9ja2VkX3N1cGVyKHMpOw0KPiAgCWdvdG8gb3V0Ow0KPiBAQCAtMjk3
Nyw3ICsyOTk5LDcgQEAgbmZzNF94ZGV2X21vdW50KHN0cnVjdCBmaWxlX3N5c3RlbV90eXBlICpm
c190eXBlLCBpbnQgZmxhZ3MsDQo+ICAJCW5mc19mcmVlX3NlcnZlcihzZXJ2ZXIpOw0KPiAgCQlz
ZXJ2ZXIgPSBOVUxMOw0KPiAgCX0gZWxzZSB7DQo+IC0JCWVycm9yID0gbmZzX2JkaV9yZWdpc3Rl
cihzZXJ2ZXIpOw0KPiArCQllcnJvciA9IG5mc19yZWdpc3RlcihzZXJ2ZXIpOw0KPiAgCQlpZiAo
ZXJyb3IpDQo+ICAJCQlnb3RvIGVycm9yX3NwbGF0X2JkaTsNCj4gIAl9DQo+IEBAIC0zMDE0LDcg
KzMwMzYsNyBAQCBvdXRfZXJyX25vc2VydmVyOg0KPiAgDQo+ICBlcnJvcl9zcGxhdF9zdXBlcjoN
Cj4gIAlpZiAoc2VydmVyICYmICFzLT5zX3Jvb3QpDQo+IC0JCWJkaV91bnJlZ2lzdGVyKCZzZXJ2
ZXItPmJhY2tpbmdfZGV2X2luZm8pOw0KPiArCQluZnNfdW5yZWdpc3RlcihzZXJ2ZXIpOw0KPiAg
ZXJyb3Jfc3BsYXRfYmRpOg0KPiAgCWRlYWN0aXZhdGVfbG9ja2VkX3N1cGVyKHMpOw0KPiAgCWRw
cmludGsoIjwtLSBuZnM0X3hkZXZfbW91bnQoKSA9ICVkIFtzcGxhdF1cbiIsIGVycm9yKTsNCj4g
QEAgLTMwNjgsNyArMzA5MCw3IEBAIG5mczRfcmVtb3RlX3JlZmVycmFsX21vdW50KHN0cnVjdCBm
aWxlX3N5c3RlbV90eXBlICpmc190eXBlLCBpbnQgZmxhZ3MsDQo+ICAJCW5mc19mcmVlX3NlcnZl
cihzZXJ2ZXIpOw0KPiAgCQlzZXJ2ZXIgPSBOVUxMOw0KPiAgCX0gZWxzZSB7DQo+IC0JCWVycm9y
ID0gbmZzX2JkaV9yZWdpc3RlcihzZXJ2ZXIpOw0KPiArCQllcnJvciA9IG5mc19yZWdpc3Rlcihz
ZXJ2ZXIpOw0KPiAgCQlpZiAoZXJyb3IpDQo+ICAJCQlnb3RvIGVycm9yX3NwbGF0X2JkaTsNCj4g
IAl9DQo+IEBAIC0zMTA4LDcgKzMxMzAsNyBAQCBvdXRfZXJyX25vZmg6DQo+ICANCj4gIGVycm9y
X3NwbGF0X3N1cGVyOg0KPiAgCWlmIChzZXJ2ZXIgJiYgIXMtPnNfcm9vdCkNCj4gLQkJYmRpX3Vu
cmVnaXN0ZXIoJnNlcnZlci0+YmFja2luZ19kZXZfaW5mbyk7DQo+ICsJCW5mc191bnJlZ2lzdGVy
KHNlcnZlcik7DQo+ICBlcnJvcl9zcGxhdF9iZGk6DQo+ICAJZGVhY3RpdmF0ZV9sb2NrZWRfc3Vw
ZXIocyk7DQo+ICAJbmZzX2ZyZWVfZmhhbmRsZShtbnRmaCk7DQo+IGRpZmYgLS1naXQgYS9mcy9u
ZnNkL25mczRjYWxsYmFjay5jIGIvZnMvbmZzZC9uZnM0Y2FsbGJhY2suYw0KPiBpbmRleCAwZTI2
MmYzLi43NGQxOWQ0IDEwMDY0NA0KPiAtLS0gYS9mcy9uZnNkL25mczRjYWxsYmFjay5jDQo+ICsr
KyBiL2ZzL25mc2QvbmZzNGNhbGxiYWNrLmMNCj4gQEAgLTYwNSw3ICs2MDUsNyBAQCBzdGF0aWMg
c3RydWN0IHJwY192ZXJzaW9uIG5mc19jYl92ZXJzaW9uNCA9IHsNCj4gIAkucHJvY3MJCQk9IG5m
czRfY2JfcHJvY2VkdXJlcw0KPiAgfTsNCj4gIA0KPiAtc3RhdGljIGNvbnN0IHN0cnVjdCBycGNf
dmVyc2lvbiAqbmZzX2NiX3ZlcnNpb25bXSA9IHsNCj4gK3N0YXRpYyBzdHJ1Y3QgcnBjX3ZlcnNp
b24gKm5mc19jYl92ZXJzaW9uW10gPSB7DQo+ICAJJm5mc19jYl92ZXJzaW9uNCwNCj4gIH07DQo+
ICANCj4gZGlmZiAtLWdpdCBhL2luY2x1ZGUvbGludXgvbG9ja2QveGRyNC5oIGIvaW5jbHVkZS9s
aW51eC9sb2NrZC94ZHI0LmgNCj4gaW5kZXggZTU4Yzg4Yi4uNzM1MzgyMSAxMDA2NDQNCj4gLS0t
IGEvaW5jbHVkZS9saW51eC9sb2NrZC94ZHI0LmgNCj4gKysrIGIvaW5jbHVkZS9saW51eC9sb2Nr
ZC94ZHI0LmgNCj4gQEAgLTQyLDYgKzQyLDYgQEAgaW50CW5sbWNsdF9lbmNvZGVfbG9ja2FyZ3Mo
c3RydWN0IHJwY19ycXN0ICosIHUzMiAqLCBzdHJ1Y3QgbmxtX2FyZ3MgKik7DQo+ICBpbnQJbmxt
Y2x0X2VuY29kZV9jYW5jYXJncyhzdHJ1Y3QgcnBjX3Jxc3QgKiwgdTMyICosIHN0cnVjdCBubG1f
YXJncyAqKTsNCj4gIGludAlubG1jbHRfZW5jb2RlX3VubG9ja2FyZ3Moc3RydWN0IHJwY19ycXN0
ICosIHUzMiAqLCBzdHJ1Y3QgbmxtX2FyZ3MgKik7DQo+ICAgKi8NCj4gLWV4dGVybiBjb25zdCBz
dHJ1Y3QgcnBjX3ZlcnNpb24gbmxtX3ZlcnNpb240Ow0KPiArZXh0ZXJuIHN0cnVjdCBycGNfdmVy
c2lvbiBubG1fdmVyc2lvbjQ7DQo+ICANCj4gICNlbmRpZiAvKiBMT0NLRF9YRFI0X0ggKi8NCj4g
ZGlmZiAtLWdpdCBhL2luY2x1ZGUvbGludXgvbmZzX3hkci5oIGIvaW5jbHVkZS9saW51eC9uZnNf
eGRyLmgNCj4gaW5kZXggYmZkMGQxYi4uYTUyZGRkNSAxMDA2NDQNCj4gLS0tIGEvaW5jbHVkZS9s
aW51eC9uZnNfeGRyLmgNCj4gKysrIGIvaW5jbHVkZS9saW51eC9uZnNfeGRyLmgNCj4gQEAgLTEz
MDAsMTEgKzEzMDAsMTEgQEAgc3RydWN0IG5mc19ycGNfb3BzIHsNCj4gIGV4dGVybiBjb25zdCBz
dHJ1Y3QgbmZzX3JwY19vcHMJbmZzX3YyX2NsaWVudG9wczsNCj4gIGV4dGVybiBjb25zdCBzdHJ1
Y3QgbmZzX3JwY19vcHMJbmZzX3YzX2NsaWVudG9wczsNCj4gIGV4dGVybiBjb25zdCBzdHJ1Y3Qg
bmZzX3JwY19vcHMJbmZzX3Y0X2NsaWVudG9wczsNCj4gLWV4dGVybiBjb25zdCBzdHJ1Y3QgcnBj
X3ZlcnNpb24gbmZzX3ZlcnNpb24yOw0KPiAtZXh0ZXJuIGNvbnN0IHN0cnVjdCBycGNfdmVyc2lv
biBuZnNfdmVyc2lvbjM7DQo+IC1leHRlcm4gY29uc3Qgc3RydWN0IHJwY192ZXJzaW9uIG5mc192
ZXJzaW9uNDsNCj4gK2V4dGVybiBzdHJ1Y3QgcnBjX3ZlcnNpb24gbmZzX3ZlcnNpb24yOw0KPiAr
ZXh0ZXJuIHN0cnVjdCBycGNfdmVyc2lvbiBuZnNfdmVyc2lvbjM7DQo+ICtleHRlcm4gc3RydWN0
IHJwY192ZXJzaW9uIG5mc192ZXJzaW9uNDsNCj4gIA0KPiAtZXh0ZXJuIGNvbnN0IHN0cnVjdCBy
cGNfdmVyc2lvbiBuZnNhY2xfdmVyc2lvbjM7DQo+ICtleHRlcm4gc3RydWN0IHJwY192ZXJzaW9u
IG5mc2FjbF92ZXJzaW9uMzsNCj4gIGV4dGVybiBjb25zdCBzdHJ1Y3QgcnBjX3Byb2dyYW0gbmZz
YWNsX3Byb2dyYW07DQo+ICANCj4gICNlbmRpZg0KPiBkaWZmIC0tZ2l0IGEvaW5jbHVkZS9saW51
eC9zdW5ycGMvY2xudC5oIGIvaW5jbHVkZS9saW51eC9zdW5ycGMvY2xudC5oDQo+IGluZGV4IDUy
MzU0N2UuLjYyNGQ4ZTMgMTAwNjQ0DQo+IC0tLSBhL2luY2x1ZGUvbGludXgvc3VucnBjL2NsbnQu
aA0KPiArKysgYi9pbmNsdWRlL2xpbnV4L3N1bnJwYy9jbG50LmgNCj4gQEAgLTcyLDcgKzcyLDcg
QEAgc3RydWN0IHJwY19wcm9ncmFtIHsNCj4gIAljb25zdCBjaGFyICoJCW5hbWU7CQkvKiBwcm90
b2NvbCBuYW1lICovDQo+ICAJdTMyCQkJbnVtYmVyOwkJLyogcHJvZ3JhbSBudW1iZXIgKi8NCj4g
IAl1bnNpZ25lZCBpbnQJCW5ydmVyczsJCS8qIG51bWJlciBvZiB2ZXJzaW9ucyAqLw0KPiAtCWNv
bnN0IHN0cnVjdCBycGNfdmVyc2lvbiAqKgl2ZXJzaW9uOwkvKiB2ZXJzaW9uIGFycmF5ICovDQo+
ICsJc3RydWN0IHJwY192ZXJzaW9uICoqCXZlcnNpb247CS8qIHZlcnNpb24gYXJyYXkgKi8NCg0K
VGhpcyBzaG91bGRuJ3QgYmUgbmVjZXNzYXJ5Lg0KDQo+ICAJc3RydWN0IHJwY19zdGF0ICoJc3Rh
dHM7CQkvKiBzdGF0aXN0aWNzICovDQo+ICAJY29uc3QgY2hhciAqCQlwaXBlX2Rpcl9uYW1lOwkv
KiBwYXRoIHRvIHJwY19waXBlZnMgZGlyICovDQo+ICB9Ow0KPiBkaWZmIC0tZ2l0IGEvbmV0L3N1
bnJwYy9ycGNiX2NsbnQuYyBiL25ldC9zdW5ycGMvcnBjYl9jbG50LmMNCj4gaW5kZXggMjA3YTc0
Ni4uMjI3YjVmYiAxMDA2NDQNCj4gLS0tIGEvbmV0L3N1bnJwYy9ycGNiX2NsbnQuYw0KPiArKysg
Yi9uZXQvc3VucnBjL3JwY2JfY2xudC5jDQo+IEBAIC0xMDgxLDI1ICsxMDgxLDI1IEBAIHN0YXRp
YyBjb25zdCBzdHJ1Y3QgcnBjYl9pbmZvIHJwY2JfbmV4dF92ZXJzaW9uNltdID0gew0KPiAgCX0s
DQo+ICB9Ow0KPiAgDQo+IC1zdGF0aWMgY29uc3Qgc3RydWN0IHJwY192ZXJzaW9uIHJwY2JfdmVy
c2lvbjIgPSB7DQo+ICtzdGF0aWMgc3RydWN0IHJwY192ZXJzaW9uIHJwY2JfdmVyc2lvbjIgPSB7
DQo+ICAJLm51bWJlcgkJPSBSUENCVkVSU18yLA0KPiAgCS5ucnByb2NzCT0gQVJSQVlfU0laRShy
cGNiX3Byb2NlZHVyZXMyKSwNCj4gIAkucHJvY3MJCT0gcnBjYl9wcm9jZWR1cmVzMg0KPiAgfTsN
Cj4gIA0KPiAtc3RhdGljIGNvbnN0IHN0cnVjdCBycGNfdmVyc2lvbiBycGNiX3ZlcnNpb24zID0g
ew0KPiArc3RhdGljIHN0cnVjdCBycGNfdmVyc2lvbiBycGNiX3ZlcnNpb24zID0gew0KPiAgCS5u
dW1iZXIJCT0gUlBDQlZFUlNfMywNCj4gIAkubnJwcm9jcwk9IEFSUkFZX1NJWkUocnBjYl9wcm9j
ZWR1cmVzMyksDQo+ICAJLnByb2NzCQk9IHJwY2JfcHJvY2VkdXJlczMNCj4gIH07DQo+ICANCj4g
LXN0YXRpYyBjb25zdCBzdHJ1Y3QgcnBjX3ZlcnNpb24gcnBjYl92ZXJzaW9uNCA9IHsNCj4gK3N0
YXRpYyBzdHJ1Y3QgcnBjX3ZlcnNpb24gcnBjYl92ZXJzaW9uNCA9IHsNCj4gIAkubnVtYmVyCQk9
IFJQQ0JWRVJTXzQsDQo+ICAJLm5ycHJvY3MJPSBBUlJBWV9TSVpFKHJwY2JfcHJvY2VkdXJlczQp
LA0KPiAgCS5wcm9jcwkJPSBycGNiX3Byb2NlZHVyZXM0DQo+ICB9Ow0KPiAgDQo+IC1zdGF0aWMg
Y29uc3Qgc3RydWN0IHJwY192ZXJzaW9uICpycGNiX3ZlcnNpb25bXSA9IHsNCj4gK3N0YXRpYyBz
dHJ1Y3QgcnBjX3ZlcnNpb24gKnJwY2JfdmVyc2lvbltdID0gew0KPiAgCU5VTEwsDQo+ICAJTlVM
TCwNCj4gIAkmcnBjYl92ZXJzaW9uMiwNCg0KLS0gDQpUcm9uZCBNeWtsZWJ1c3QNCkxpbnV4IE5G
UyBjbGllbnQgbWFpbnRhaW5lcg0KDQpOZXRBcHANClRyb25kLk15a2xlYnVzdEBuZXRhcHAuY29t
DQp3d3cubmV0YXBwLmNvbQ0KDQo=

2012-03-21 15:21:26

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 22/23] NFS: Use the IS_ENABLED macro for CONFIG_NFS_V4

From: Bryan Schumaker <[email protected]>

Once v4 is a module CONFIG_NFS_V4_MODULE may be set instead of
CONFIG_NFS_V4. This code doesn't care if it's a module or built in, but
it does need to know if any form of the option is enabled.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/callback.h | 2 +-
fs/nfs/client.c | 8 ++++----
fs/nfs/delegation.h | 2 +-
fs/nfs/dir.c | 4 ++--
fs/nfs/direct.c | 2 +-
fs/nfs/inode.c | 8 ++++----
fs/nfs/internal.h | 12 ++++++------
fs/nfs/namespace.c | 2 +-
fs/nfs/netns.h | 2 +-
fs/nfs/nfs4_fs.h | 2 +-
fs/nfs/super.c | 14 +++++++-------
fs/nfs/write.c | 8 ++++----
include/linux/nfs_fs.h | 6 +++---
include/linux/nfs_fs_sb.h | 6 +++---
include/linux/nfs_idmap.h | 2 +-
include/linux/nfs_xdr.h | 4 ++--
16 files changed, 42 insertions(+), 42 deletions(-)

diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index a5527c9..b44d7b1 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -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,
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 96de872..45f3a21 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -53,7 +53,7 @@
static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
static DEFINE_SPINLOCK(nfs_version_lock);
static LIST_HEAD(nfs_versions);
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)

/*
* Get a unique NFSv4.0 callback identifier which will be used
@@ -213,7 +213,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
return nfs_mod->alloc_client(cl_init);
}

-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
static void pnfs_init_server(struct nfs_server *server)
{
rpc_init_wait_queue(&server->roc_rpcwaitq, "pNFS ROC");
@@ -1159,7 +1159,7 @@ error:
}
EXPORT_SYMBOL_GPL(nfs_create_server);

-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
/*
* NFSv4.0 callback thread helper
*
@@ -1302,7 +1302,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);
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 26f77ca..6436548 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -9,7 +9,7 @@
#define FS_NFS_DELEGATION_H

#include "nfs.h"
-#if defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V4)
/*
* NFSv4 delegation
*/
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 4e8d06b..10c7275 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -81,7 +81,7 @@ const struct address_space_operations nfs_dir_aops = {
.freepage = nfs_readdir_clear_array,
};

-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)

static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
static int nfs_open_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd);
@@ -1301,7 +1301,7 @@ out:
}
EXPORT_SYMBOL_GPL(nfs_lookup);

-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
static int nfs_open_revalidate(struct dentry *, struct nameidata *);

const struct dentry_operations nfs4_dentry_operations = {
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 18b16a7..a43b9bd 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -458,7 +458,7 @@ static void nfs_direct_free_writedata(struct nfs_direct_req *dreq)
}
}

-#if IS_ENABLED(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 inode *inode = dreq->inode;
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 35f4175..e1e0568 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1532,7 +1532,7 @@ 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;
@@ -1551,7 +1551,7 @@ void nfs_destroy_inode(struct inode *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;
@@ -1700,7 +1700,7 @@ static int __init init_nfs_fs(void)
#endif
if ((err = register_nfs_fs()) != 0)
goto out;
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
init_nfs_v4();
#endif
return 0;
@@ -1733,7 +1733,7 @@ out9:

static void __exit exit_nfs_fs(void)
{
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
exit_nfs_v4();
#endif
nfs_destroy_directcache();
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 42d0903..2049975 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -188,7 +188,7 @@ static inline void nfs_fs_proc_exit(void)
#endif

/* nfs4namespace.c */
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
extern struct vfsmount *nfs_do_refmount(struct dentry *dentry);
#else
static inline
@@ -225,7 +225,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
@@ -235,7 +235,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[];
void nfs_fixup_secinfo_attributes(struct nfs_fattr *, struct nfs_fh *);
#endif
@@ -264,7 +264,7 @@ extern int nfs_wait_bit_killable(void *word);

/* super.c */
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
@@ -280,14 +280,14 @@ extern void nfs_sb_deactive(struct super_block *sb);
extern char *nfs_path(char **p, struct dentry *dentry,
char *buffer, ssize_t buflen);
extern struct vfsmount *nfs_d_automount(struct path *path);
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *);
#endif

/* 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 *);

diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index c071f54..aa8e6db 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -121,7 +121,7 @@ Elong:
return ERR_PTR(-ENAMETOOLONG);
}

-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
{
struct gss_api_mech *mech;
diff --git a/fs/nfs/netns.h b/fs/nfs/netns.h
index aa14ec3..c777c0d 100644
--- a/fs/nfs/netns.h
+++ b/fs/nfs/netns.h
@@ -16,7 +16,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/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 636786e..6258397 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -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)

#include "nfs.h"

diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 97f3ff0..b214f44 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -534,7 +534,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)
{
@@ -666,7 +666,7 @@ int nfs_show_options(struct seq_file *m, struct dentry *root)
return 0;
}

-#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)
{
@@ -699,7 +699,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)
{
}
@@ -764,7 +764,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]);
@@ -1847,7 +1847,7 @@ static int nfs_validate_mount_data(void *options,
goto out_no_address;

if (args->version == 4)
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
return nfs4_validate_text_mount_data(options,
args, dev_name);
#else
@@ -1902,7 +1902,7 @@ out_v3_not_compiled:
return -EPROTONOSUPPORT;
#endif /* !CONFIG_NFS_V3 */

-#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;
@@ -2422,7 +2422,7 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,
return nfs_mod->xdev_mount(flags, dev_name, data);
}

-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)

static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args)
{
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 46fff97..d8e9ef7 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -416,7 +416,7 @@ nfs_mark_request_dirty(struct nfs_page *req)
__set_page_dirty_nobuffers(req->wb_page);
}

-#if IS_ENABLED(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
@@ -551,7 +551,7 @@ int nfs_reschedule_unstable_write(struct nfs_page *req,
}
#endif

-#if IS_ENABLED(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
static int
nfs_need_commit(struct nfs_inode *nfsi)
{
@@ -1271,7 +1271,7 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
return;
nfs_add_stats(data->inode, NFSIOS_SERVERWRITTENBYTES, resp->count);

-#if IS_ENABLED(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
@@ -1330,7 +1330,7 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
}


-#if IS_ENABLED(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;
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 3e0758e..b17fbae 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -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;
@@ -436,7 +436,7 @@ extern const struct inode_operations nfs_file_inode_operations;
extern const struct inode_operations nfs3_file_inode_operations;
#endif /* CONFIG_NFS_V3 */
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;
@@ -550,7 +550,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 IS_ENABLED(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_write_data *nfs_commitdata_alloc(void);
extern void nfs_commit_free(struct nfs_write_data *wdata);
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 7073fc7..c47cea9 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -48,7 +48,7 @@ struct nfs_client {
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;
@@ -136,7 +136,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 */
@@ -199,7 +199,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))
diff --git a/include/linux/nfs_idmap.h b/include/linux/nfs_idmap.h
index 7eed201..ece91c5 100644
--- a/include/linux/nfs_idmap.h
+++ b/include/linux/nfs_idmap.h
@@ -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
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index a52ddd5..8d70dfa 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -790,7 +790,7 @@ struct nfs3_getaclres {
struct posix_acl * acl_default;
};

-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)

typedef u64 clientid4;

@@ -1184,7 +1184,7 @@ struct nfs_write_data {
int ds_commit_index;
const struct rpc_call_ops *mds_ops;
int (*write_done_cb) (struct rpc_task *task, struct nfs_write_data *data);
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
unsigned long timestamp; /* For lease renewal */
#endif
__u64 mds_offset; /* Filelayout dense stripe */
--
1.7.9.4


2012-03-21 15:21:13

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 02/23] NFS: Make v2 configurable

From: Bryan Schumaker <[email protected]>

With this patch NFS v2 will no longer be automatically compiled in.
Instead, users will have to select NFS_V2 during Kconfig if they want to
use v2.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Kconfig | 9 +++++++++
fs/nfs/Makefile | 5 +++--
fs/nfs/client.c | 11 ++++++++++-
3 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index 2a0e6c5..4995b24 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -29,6 +29,15 @@ config NFS_FS

If unsure, say N.

+config NFS_V2
+ bool "NFS client support for NFS version 2"
+ depends on NFS_FS
+ help
+ This option enables support for version 2 of the NFS protocol
+ (RFC 1094) in the kernel's NFS client.
+
+ If unsure, say Y.
+
config NFS_V3
bool "NFS client support for NFS version 3"
depends on NFS_FS
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index b58613d..7ddd45d 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -4,11 +4,12 @@

obj-$(CONFIG_NFS_FS) += nfs.o

-nfs-y := client.o dir.o file.o getroot.o inode.o super.o nfs2xdr.o \
- direct.o pagelist.o proc.o read.o symlink.o unlink.o \
+nfs-y := client.o dir.o file.o getroot.o inode.o super.o \
+ direct.o pagelist.o read.o symlink.o unlink.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 \
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 08e7f24..4d793b2 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -90,7 +90,9 @@ static bool nfs4_disable_idmapping = true;
* 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
@@ -847,7 +849,7 @@ static int nfs_init_server(struct nfs_server *server,
.hostname = data->nfs_server.hostname,
.addr = (const struct sockaddr *)&data->nfs_server.address,
.addrlen = data->nfs_server.addrlen,
- .rpc_ops = &nfs_v2_clientops,
+ .rpc_ops = NULL,
.proto = data->nfs_server.protocol,
.net = data->net,
};
@@ -857,10 +859,17 @@ static int nfs_init_server(struct nfs_server *server,

dprintk("--> nfs_init_server()\n");

+
+#ifdef CONFIG_NFS_V2
+ if (data->version == 2)
+ cl_init.rpc_ops = &nfs_v2_clientops;
+#endif
#ifdef CONFIG_NFS_V3
if (data->version == 3)
cl_init.rpc_ops = &nfs_v3_clientops;
#endif
+ if (cl_init.rpc_ops == NULL)
+ return -EPROTONOSUPPORT;

nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
data->timeo, data->retrans);
--
1.7.9.4


2012-03-21 15:21:16

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 07/23] NFS: Version specific xdev mounting

From: Bryan Schumaker <[email protected]>

I set up a common _nfs_xdev_mount() function that can be called by v2,
v3 and v4 with different parameters. This also gives each version a
chance to do their own thing both before and after the call.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/nfs.h | 4 ++
fs/nfs/nfs2super.c | 10 ++++-
fs/nfs/nfs3super.c | 8 ++++
fs/nfs/nfs4_fs.h | 1 +
fs/nfs/nfs4super.c | 11 +++++
fs/nfs/super.c | 126 ++++++++++------------------------------------------
6 files changed, 56 insertions(+), 104 deletions(-)

diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index a7a08b3..a5e6a63 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -12,6 +12,7 @@
#include <linux/nfs_xdr.h>

struct nfs_parsed_mount_data;
+struct nfs_clone_mount;

struct nfs_subversion {
unsigned int version; /* Protocol number */
@@ -23,6 +24,7 @@ struct nfs_subversion {
void (*unreference)(void); /* Also for reference counting */
struct dentry *(*fs_mount)(struct file_system_type *, int, const char *,
struct nfs_fh *, struct nfs_parsed_mount_data *);
+ struct dentry *(*xdev_mount)(int, const char *, struct nfs_clone_mount *);
};

void nfs_register_versions(void);
@@ -39,9 +41,11 @@ void unregister_nfs_version(struct nfs_subversion *);
struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *, struct nfs_fh *);

/* Exported in super.c */
+extern struct file_system_type nfs_fs_type;
struct dentry *_nfs_fs_mount(struct file_system_type *, struct nfs_server *,
int, const char *, struct nfs_fh *,
struct nfs_parsed_mount_data *);
+struct dentry *_nfs_xdev_mount(struct file_system_type *, int, const char *, void *, int);


#endif /* __LINUX_INTERNAL_NFS_H */
diff --git a/fs/nfs/nfs2super.c b/fs/nfs/nfs2super.c
index 8f92f5d..d1074a9 100644
--- a/fs/nfs/nfs2super.c
+++ b/fs/nfs/nfs2super.c
@@ -1,10 +1,11 @@
/*
* Copyright (c) 2012 Netapp, Inc. All rights reserved.
*
- * Initialize the NFS v2 module
+ Initialize[* Initialize the NFS v2 module
*/
#include <linux/module.h>
#include <linux/nfs_fs.h>
+#include <linux/nfs_mount.h>
#include "nfs.h"

static void nfs2_reference(void)
@@ -28,6 +29,12 @@ static struct dentry *nfs2_fs_mount(struct file_system_type *fs_type,
return _nfs_fs_mount(fs_type, server, flags, dev_name, mntfh, data);
}

+static struct dentry *nfs2_xdev_mount(int flags, const char *dev_name,
+ struct nfs_clone_mount *data)
+{
+ return _nfs_xdev_mount(&nfs_fs_type, flags, dev_name, data, NFS_MOUNT_UNSHARED);
+}
+
static struct nfs_subversion nfs_v2 = {
.version = 2,
.rpc_vers = &nfs_version2,
@@ -36,6 +43,7 @@ static struct nfs_subversion nfs_v2 = {
.reference = nfs2_reference,
.unreference = nfs2_unreference,
.fs_mount = nfs2_fs_mount,
+ .xdev_mount = nfs2_xdev_mount,
};

static int __init init_nfs_v2(void)
diff --git a/fs/nfs/nfs3super.c b/fs/nfs/nfs3super.c
index 2048460..7bdd388 100644
--- a/fs/nfs/nfs3super.c
+++ b/fs/nfs/nfs3super.c
@@ -3,6 +3,7 @@
*/
#include <linux/module.h>
#include <linux/nfs_fs.h>
+#include <linux/nfs_mount.h>
#include "nfs.h"

static void nfs3_reference(void)
@@ -26,6 +27,12 @@ struct dentry *nfs3_fs_mount(struct file_system_type *fs_type,
return _nfs_fs_mount(fs_type, server, flags, dev_name, mntfh, data);
}

+static struct dentry *nfs3_xdev_mount(int flags, const char *dev_name,
+ struct nfs_clone_mount *data)
+{
+ return _nfs_xdev_mount(&nfs_fs_type, flags, dev_name, data, NFS_MOUNT_UNSHARED);
+}
+
static struct nfs_subversion nfs_v3 = {
.version = 3,
.rpc_vers = &nfs_version3,
@@ -34,6 +41,7 @@ static struct nfs_subversion nfs_v3 = {
.reference = nfs3_reference,
.unreference = nfs3_unreference,
.fs_mount = nfs3_fs_mount,
+ .xdev_mount = nfs3_xdev_mount,
};

int __init init_nfs_v3(void)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index cb2f14c..6786c4f 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -207,6 +207,7 @@ extern const struct dentry_operations nfs4_dentry_operations;
extern const struct inode_operations nfs4_dir_inode_operations;

/* super.c */
+extern struct file_system_type nfs4_fs_type;
struct dentry *nfs4_try_mount(int flags, const char *dev_name, struct nfs_parsed_mount_data *);

/* nfs4proc.c */
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 0cc67b6..8a297c5 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -3,6 +3,7 @@
*/
#include <linux/module.h>
#include <linux/nfs_fs.h>
+#include <linux/nfs4_mount.h>
#include "nfs4_fs.h"
#include "nfs.h"

@@ -24,6 +25,15 @@ struct dentry *nfs4_fs_mount(struct file_system_type *fs_type,
return nfs4_try_mount(flags, dev_name, data);
}

+/*
+ * Clone an NFS4 server record on xdev traversal (FSID-change)
+ */
+struct dentry *nfs4_xdev_mount(int flags, const char *dev_name,
+ struct nfs_clone_mount *data)
+{
+ return _nfs_xdev_mount(&nfs4_fs_type, flags, dev_name, data, NFS4_MOUNT_UNSHARED);
+}
+
static struct nfs_subversion nfs_v4 = {
.version = 4,
.rpc_vers = &nfs_version4,
@@ -32,6 +42,7 @@ static struct nfs_subversion nfs_v4 = {
.reference = nfs4_reference,
.unreference = nfs4_unreference,
.fs_mount = nfs4_fs_mount,
+ .xdev_mount = nfs4_xdev_mount,
};

int __init init_nfs_v4(void)
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 16ceae3..994a0cc 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -293,13 +293,14 @@ static void nfs_put_super(struct super_block *);
static void nfs_kill_super(struct super_block *);
static int nfs_remount(struct super_block *sb, int *flags, char *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,
@@ -333,15 +334,13 @@ static struct dentry *nfs4_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data);
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,
int flags, const char *dev_name, void *raw_data);
static void nfs4_kill_super(struct super_block *sb);

-static struct file_system_type nfs4_fs_type = {
+struct file_system_type nfs4_fs_type = {
.owner = THIS_MODULE,
.name = "nfs4",
.mount = nfs4_mount,
@@ -360,7 +359,7 @@ static struct file_system_type nfs4_remote_fs_type = {
struct file_system_type nfs4_xdev_fs_type = {
.owner = THIS_MODULE,
.name = "nfs4",
- .mount = nfs4_xdev_mount,
+ .mount = nfs_xdev_mount,
.kill_sb = nfs4_kill_super,
.fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
};
@@ -2437,9 +2436,9 @@ static void nfs_kill_super(struct super_block *s)
/*
* 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 dentry *
+_nfs_xdev_mount(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *raw_data, int unshared_flag)
{
struct nfs_clone_mount *data = raw_data;
struct super_block *s;
@@ -2451,7 +2450,7 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,
};
int error;

- dprintk("--> nfs_xdev_mount()\n");
+ dprintk("--> _nfs_xdev_mount()\n");

/* create a new volume representation */
server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
@@ -2461,7 +2460,7 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,
}
sb_mntdata.server = server;

- if (server->flags & NFS_MOUNT_UNSHARED)
+ if (server->flags & unshared_flag)
compare_super = NULL;

/* -o noac implies -o sync */
@@ -2469,7 +2468,7 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,
sb_mntdata.mntflags |= MS_SYNCHRONOUS;

/* Get a superblock - note that we may end up sharing one that already exists */
- s = sget(&nfs_fs_type, compare_super, nfs_set_super, &sb_mntdata);
+ s = sget(fs_type, compare_super, nfs_set_super, &sb_mntdata);
if (IS_ERR(s)) {
error = PTR_ERR(s);
goto out_err_nosb;
@@ -2506,13 +2505,13 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,
/* clone any lsm security options from the parent to the new sb */
security_sb_clone_mnt_opts(data->sb, s);

- dprintk("<-- nfs_xdev_mount() = 0\n");
+ dprintk("<-- _nfs_xdev_mount() = 0\n");
return mntroot;

out_err_nosb:
nfs_free_server(server);
out_err_noserver:
- dprintk("<-- nfs_xdev_mount() = %d [error]\n", error);
+ dprintk("<-- _nfs_xdev_mount() = %d [error]\n", error);
return ERR_PTR(error);

error_splat_super:
@@ -2520,9 +2519,19 @@ error_splat_super:
nfs_unregister(server);
error_splat_bdi:
deactivate_locked_super(s);
- dprintk("<-- nfs_xdev_mount() = %d [splat]\n", error);
+ dprintk("<-- _nfs_xdev_mount() = %d [splat]\n", error);
return ERR_PTR(error);
}
+EXPORT_SYMBOL_GPL(_nfs_xdev_mount);
+
+static struct dentry *
+nfs_xdev_mount(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *raw_data)
+{
+ struct nfs_clone_mount *data = raw_data;
+ struct nfs_subversion *nfs_mod = get_nfs_server_version(NFS_SB(data->sb));
+ return nfs_mod->xdev_mount(flags, dev_name, data);
+}

#ifdef CONFIG_NFS_V4

@@ -2937,95 +2946,6 @@ static void nfs4_kill_super(struct super_block *sb)
dprintk("<-- %s\n", __func__);
}

-/*
- * 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_clone_mount *data = raw_data;
- struct super_block *s;
- struct nfs_server *server;
- struct dentry *mntroot;
- int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
- struct nfs_sb_mountdata sb_mntdata = {
- .mntflags = flags,
- };
- int error;
-
- dprintk("--> nfs4_xdev_mount()\n");
-
- /* create a new volume representation */
- server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
- if (IS_ERR(server)) {
- error = PTR_ERR(server);
- goto out_err_noserver;
- }
- sb_mntdata.server = server;
-
- if (server->flags & NFS4_MOUNT_UNSHARED)
- compare_super = NULL;
-
- /* -o noac implies -o sync */
- if (server->flags & NFS_MOUNT_NOAC)
- sb_mntdata.mntflags |= MS_SYNCHRONOUS;
-
- /* Get a superblock - note that we may end up sharing one that already exists */
- s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata);
- if (IS_ERR(s)) {
- error = PTR_ERR(s);
- goto out_err_nosb;
- }
-
- if (s->s_fs_info != server) {
- nfs_free_server(server);
- server = NULL;
- } else {
- error = nfs_register(server);
- if (error)
- goto error_splat_bdi;
- }
-
- if (!s->s_root) {
- /* initial superblock/root creation */
- nfs_clone_super(s, data->sb);
- nfs_fscache_get_super_cookie(s, NULL, data);
- }
-
- mntroot = nfs4_get_root(s, data->fh, dev_name);
- if (IS_ERR(mntroot)) {
- error = PTR_ERR(mntroot);
- goto error_splat_super;
- }
- if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) {
- dput(mntroot);
- error = -ESTALE;
- goto error_splat_super;
- }
-
- s->s_flags |= MS_ACTIVE;
-
- security_sb_clone_mnt_opts(data->sb, s);
-
- dprintk("<-- nfs4_xdev_mount() = 0\n");
- return mntroot;
-
-out_err_nosb:
- nfs_free_server(server);
-out_err_noserver:
- dprintk("<-- nfs4_xdev_mount() = %d [error]\n", error);
- return ERR_PTR(error);
-
-error_splat_super:
- if (server && !s->s_root)
- nfs_unregister(server);
-error_splat_bdi:
- deactivate_locked_super(s);
- dprintk("<-- nfs4_xdev_mount() = %d [splat]\n", error);
- return ERR_PTR(error);
-}
-
static struct dentry *
nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
const char *dev_name, void *raw_data)
--
1.7.9.4


2012-03-21 15:21:19

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 13/23] NFS: Custom alloc and free client functions for modules

From: Bryan Schumaker <[email protected]>

This gives v4 a chance to do any setup and teardown that it needs (such
as pnfs or v4.1 sessions).

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Makefile | 2 +-
fs/nfs/client.c | 96 +++++++++++----------------------------------------
fs/nfs/nfs.h | 15 ++++++++
fs/nfs/nfs2super.c | 2 ++
fs/nfs/nfs3super.c | 2 ++
fs/nfs/nfs4_fs.h | 4 +++
fs/nfs/nfs4client.c | 80 ++++++++++++++++++++++++++++++++++++++++++
fs/nfs/nfs4super.c | 2 ++
8 files changed, 127 insertions(+), 76 deletions(-)
create mode 100644 fs/nfs/nfs4client.c

diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 7c8a7a0..cf8b669 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -12,7 +12,7 @@ nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
nfs4super.o delegation.o idmap.o \
callback.o callback_xdr.o callback_proc.o \
- nfs4namespace.o nfs4sysctl.o
+ nfs4namespace.o nfs4sysctl.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
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index adc548c..41c687e 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -27,7 +27,6 @@
#include <linux/sunrpc/xprtrdma.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_mount.h>
-#include <linux/nfs4_mount.h>
#include <linux/lockd/bind.h>
#include <linux/seq_file.h>
#include <linux/mount.h>
@@ -44,9 +43,7 @@

#include <asm/system.h>

-#include "nfs4_fs.h"
#include "callback.h"
-#include "delegation.h"
#include "iostat.h"
#include "internal.h"
#include "fscache.h"
@@ -65,7 +62,7 @@ static LIST_HEAD(nfs_versions);
* Get a unique NFSv4.0 callback identifier which will be used
* by the V4.0 callback service to lookup the nfs_client struct
*/
-static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
+int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
{
int ret = 0;
struct nfs_net *nn = net_generic(clp->net, nfs_net_id);
@@ -111,16 +108,6 @@ struct rpc_stat nfs_rpcstat = {
.program = &nfs_program
};

-struct nfs_client_initdata {
- const char *hostname;
- const struct sockaddr *addr;
- size_t addrlen;
- const struct nfs_rpc_ops *rpc_ops;
- int proto;
- u32 minorversion;
- struct net *net;
-};
-
static int find_nfs_version(struct nfs_subversion **nfs, unsigned int version)
{
struct nfs_subversion *tmp;
@@ -184,7 +171,7 @@ EXPORT_SYMBOL_GPL(unregister_nfs_version);
* Since these are allocated/deallocated very rarely, we don't
* bother putting them in a slab cache...
*/
-static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
+struct nfs_client *_nfs_alloc_client(const struct nfs_client_initdata *cl_init)
{
struct nfs_client *clp;
struct rpc_cred *cred;
@@ -214,19 +201,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
clp->cl_proto = cl_init->proto;
clp->net = get_net(cl_init->net);

-#ifdef CONFIG_NFS_V4
- err = nfs_get_cb_ident_idr(clp, cl_init->minorversion);
- if (err)
- goto error_cleanup;
-
- spin_lock_init(&clp->cl_lock);
- INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
- rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
- clp->cl_boot_time = CURRENT_TIME;
- clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
- clp->cl_minorversion = cl_init->minorversion;
- clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion];
-#endif
cred = rpc_lookup_machine_cred("*");
if (!IS_ERR(cred))
clp->cl_machine_cred = cred;
@@ -239,42 +213,23 @@ error_cleanup:
error_0:
return ERR_PTR(err);
}
+EXPORT_SYMBOL_GPL(_nfs_alloc_client);

-#ifdef CONFIG_NFS_V4
-#ifdef CONFIG_NFS_V4_1
-static void nfs4_shutdown_session(struct nfs_client *clp)
-{
- if (nfs4_has_session(clp)) {
- nfs4_deviceid_purge_client(clp);
- nfs4_destroy_session(clp->cl_session);
- }
-
-}
-#else /* CONFIG_NFS_V4_1 */
-static void nfs4_shutdown_session(struct nfs_client *clp)
+static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
{
+ struct nfs_subversion *nfs_mod = get_nfs_version(cl_init->rpc_ops->version);
+ return nfs_mod->alloc_client(cl_init);
}
-#endif /* CONFIG_NFS_V4_1 */

-/*
- * Destroy the NFS4 callback service
- */
-static void nfs4_destroy_callback(struct nfs_client *clp)
+#ifdef CONFIG_NFS_V4
+static void pnfs_init_server(struct nfs_server *server)
{
- if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
- nfs_callback_down(clp->cl_mvops->minor_version);
+ rpc_init_wait_queue(&server->roc_rpcwaitq, "pNFS ROC");
}

-static void nfs4_shutdown_client(struct nfs_client *clp)
+static void nfs4_destroy_server(struct nfs_server *server)
{
- if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
- nfs4_kill_renewd(clp);
- nfs4_shutdown_session(clp);
- nfs4_destroy_callback(clp);
- if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
- nfs_idmap_delete(clp);
-
- rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
+ nfs4_purge_state_owners(server);
}

/* idr_remove_all is not needed as all id's are removed by nfs_put_client */
@@ -294,21 +249,7 @@ static void nfs_cb_idr_remove_locked(struct nfs_client *clp)
idr_remove(&nn->cb_ident_idr, clp->cl_cb_ident);
}

-static void pnfs_init_server(struct nfs_server *server)
-{
- rpc_init_wait_queue(&server->roc_rpcwaitq, "pNFS ROC");
-}
-
-static void nfs4_destroy_server(struct nfs_server *server)
-{
- nfs4_purge_state_owners(server);
-}
-
#else
-static void nfs4_shutdown_client(struct nfs_client *clp)
-{
-}
-
void nfs_cleanup_cb_ident_idr(struct net *net)
{
}
@@ -326,11 +267,9 @@ static void pnfs_init_server(struct nfs_server *server)
/*
* Destroy a shared client record
*/
-static void nfs_free_client(struct nfs_client *clp)
+void _nfs_free_client(struct nfs_client *clp)
{
- dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version);
-
- nfs4_shutdown_client(clp);
+ dprintk("--> _nfs_free_client(%u)\n", clp->rpc_ops->version);

nfs_fscache_release_client_cookie(clp);

@@ -347,7 +286,14 @@ static void nfs_free_client(struct nfs_client *clp)
kfree(clp->impl_id);
kfree(clp);

- dprintk("<-- nfs_free_client()\n");
+ dprintk("<-- _nfs_free_client()\n");
+}
+EXPORT_SYMBOL_GPL(_nfs_free_client);
+
+static void nfs_free_client(struct nfs_client *clp)
+{
+ struct nfs_subversion *nfs_mod = get_nfs_client_version(clp);
+ nfs_mod->free_client(clp);
}

/*
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 9e632c2..6036141 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -14,6 +14,16 @@
struct nfs_parsed_mount_data;
struct nfs_clone_mount;

+struct nfs_client_initdata {
+ const char *hostname;
+ const struct sockaddr *addr;
+ size_t addrlen;
+ const struct nfs_rpc_ops *rpc_ops;
+ int proto;
+ u32 minorversion;
+ struct net *net;
+};
+
struct nfs_subversion {
unsigned int version; /* Protocol number */
struct rpc_version *rpc_vers; /* NFS version information */
@@ -22,6 +32,8 @@ struct nfs_subversion {

void (*reference)(void); /* For reference counting */
void (*unreference)(void); /* Also for reference counting */
+ struct nfs_client *(*alloc_client)(const struct nfs_client_initdata *);
+ void (*free_client)(struct nfs_client *);
struct dentry *(*fs_mount)(struct file_system_type *, int, const char *,
struct nfs_fh *, struct nfs_parsed_mount_data *);
struct dentry *(*xdev_mount)(int, const char *, struct nfs_clone_mount *);
@@ -43,7 +55,10 @@ void register_nfs_version(struct nfs_subversion *);
void unregister_nfs_version(struct nfs_subversion *);

/* Exported in client.c */
+int nfs_get_cb_ident_idr(struct nfs_client *, int);
struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *, struct nfs_fh *);
+struct nfs_client *_nfs_alloc_client(const struct nfs_client_initdata *);
+void _nfs_free_client(struct nfs_client *);

/* Exported in dir.c */
struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *);
diff --git a/fs/nfs/nfs2super.c b/fs/nfs/nfs2super.c
index 6d2a1fd..697356f 100644
--- a/fs/nfs/nfs2super.c
+++ b/fs/nfs/nfs2super.c
@@ -54,6 +54,8 @@ static struct nfs_subversion nfs_v2 = {

.reference = nfs2_reference,
.unreference = nfs2_unreference,
+ .alloc_client = _nfs_alloc_client,
+ .free_client = _nfs_free_client,
.fs_mount = nfs2_fs_mount,
.xdev_mount = nfs2_xdev_mount,
.submount = nfs2_do_submount,
diff --git a/fs/nfs/nfs3super.c b/fs/nfs/nfs3super.c
index 7142c03..17dad41 100644
--- a/fs/nfs/nfs3super.c
+++ b/fs/nfs/nfs3super.c
@@ -85,6 +85,8 @@ static struct nfs_subversion nfs_v3 = {

.reference = nfs3_reference,
.unreference = nfs3_unreference,
+ .alloc_client = _nfs_alloc_client,
+ .free_client = _nfs_free_client,
.fs_mount = nfs3_fs_mount,
.xdev_mount = nfs3_xdev_mount,
.submount = nfs3_do_submount,
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index b6bc89c..636786e 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -210,6 +210,10 @@ extern const struct inode_operations nfs4_dir_inode_operations;
extern struct file_system_type nfs4_fs_type;
struct dentry *nfs4_try_mount(int flags, const char *dev_name, struct nfs_parsed_mount_data *);

+/* nfs4client.c */
+struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *);
+void nfs4_free_client(struct nfs_client *);
+
/* nfs4namespace.c */
struct vfsmount *nfs4_do_submount(struct dentry *, struct nfs_fh *, struct nfs_fattr *, rpc_authflavor_t);

diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
new file mode 100644
index 0000000..c555748
--- /dev/null
+++ b/fs/nfs/nfs4client.c
@@ -0,0 +1,80 @@
+/*
+ *Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells ([email protected])
+ */
+
+#include <linux/nfs4.h>
+#include <linux/nfs_fs.h>
+#include <linux/nfs_fs_sb.h>
+#include <linux/nfs_idmap.h>
+#include "internal.h"
+#include "callback.h"
+#include "pnfs.h"
+
+#ifdef CONFIG_NFS_V4_1
+static void nfs4_shutdown_session(struct nfs_client *clp)
+{
+ if (nfs4_has_session(clp)) {
+ nfs4_deviceid_purge_client(clp);
+ nfs4_destroy_session(clp->cl_session);
+ }
+}
+#else /* CONFIG_NFS_V4_1 */
+static void nfs4_shutdown_session(struct nfs_client *clp)
+{
+}
+#endif /* CONFIG_NFS_V4_1 */
+
+/*
+ * Destroy the NFS4 callback service
+ */
+static void nfs4_destroy_callback(struct nfs_client *clp)
+{
+ if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
+ nfs_callback_down(clp->cl_mvops->minor_version);
+}
+
+static void nfs4_shutdown_client(struct nfs_client *clp)
+{
+ if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
+ nfs4_kill_renewd(clp);
+ nfs4_shutdown_session(clp);
+ nfs4_destroy_callback(clp);
+ if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
+ nfs_idmap_delete(clp);
+
+ rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
+}
+
+void nfs4_free_client(struct nfs_client *clp)
+{
+ nfs4_shutdown_client(clp);
+ _nfs_free_client(clp);
+}
+
+struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init)
+{
+ struct nfs_client *clp = _nfs_alloc_client(cl_init);
+ int err = -ENOMEM;
+
+ if (IS_ERR(clp))
+ return clp;
+
+ err = nfs_get_cb_ident_idr(clp, cl_init->minorversion);
+ if (err)
+ goto error_cleanup;
+
+ spin_lock_init(&clp->cl_lock);
+ INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
+ rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
+ clp->cl_boot_time = CURRENT_TIME;
+ clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
+ clp->cl_minorversion = cl_init->minorversion;
+ clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion];
+
+ return clp;
+
+error_cleanup:
+ kfree(clp);
+ return ERR_PTR(err);
+}
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index b384a81..b0beba9 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -615,6 +615,8 @@ static struct nfs_subversion nfs_v4 = {

.reference = nfs4_reference,
.unreference = nfs4_unreference,
+ .alloc_client = nfs4_alloc_client,
+ .free_client = nfs4_free_client,
.fs_mount = nfs4_fs_mount,
.xdev_mount = nfs4_xdev_mount,
.submount = nfs4_do_submount,
--
1.7.9.4


2012-03-21 15:21:22

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 18/23] NFS: Create a v4-specific fsync function

From: Bryan Schumaker <[email protected]>

NFS v4 needs its own fsync function for the pnfs layoutcommit.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Makefile | 2 +-
fs/nfs/file.c | 86 +++++++++++++++++++----------------------------------
fs/nfs/nfs.h | 17 +++++++++++
fs/nfs/nfs4file.c | 57 +++++++++++++++++++++++++++++++++++
fs/nfs/write.c | 1 -
5 files changed, 105 insertions(+), 58 deletions(-)
create mode 100644 fs/nfs/nfs4file.c

diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 8028e09..85aafee 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -13,7 +13,7 @@ nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
nfs4super.o delegation.o idmap.o \
callback.o callback_xdr.o callback_proc.o \
nfs4namespace.o nfs4sysctl.o nfs4client.o \
- nfs4getroot.o
+ nfs4getroot.o nfs4file.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
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index c678c00..d169c2b 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -37,7 +37,6 @@
#include "internal.h"
#include "iostat.h"
#include "fscache.h"
-#include "pnfs.h"

#define NFSDBG_FACILITY NFSDBG_FILE

@@ -55,7 +54,7 @@ EXPORT_SYMBOL_GPL(nfs_file_inode_operations);
# define IS_SWAPFILE(inode) (0)
#endif

-static int nfs_check_flags(int flags)
+int nfs_check_flags(int flags)
{
if ((flags & (O_APPEND | O_DIRECT)) == (O_APPEND | O_DIRECT))
return -EINVAL;
@@ -84,7 +83,7 @@ nfs_file_open(struct inode *inode, struct file *filp)
return res;
}

-static int
+int
nfs_file_release(struct inode *inode, struct file *filp)
{
dprintk("NFS: release(%s/%s)\n",
@@ -126,7 +125,7 @@ force_reval:
return __nfs_revalidate_inode(server, inode);
}

-static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
+loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
{
dprintk("NFS: llseek file(%s/%s, %lld, %d)\n",
filp->f_path.dentry->d_parent->d_name.name,
@@ -151,7 +150,7 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
/*
* Flush all dirty pages, and check for write errors.
*/
-static int
+int
nfs_file_flush(struct file *file, fl_owner_t id)
{
struct dentry *dentry = file->f_path.dentry;
@@ -169,7 +168,7 @@ nfs_file_flush(struct file *file, fl_owner_t id)
return vfs_fsync(file, 0);
}

-static ssize_t
+ssize_t
nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
@@ -193,7 +192,7 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
return result;
}

-static ssize_t
+ssize_t
nfs_file_splice_read(struct file *filp, loff_t *ppos,
struct pipe_inode_info *pipe, size_t count,
unsigned int flags)
@@ -215,7 +214,7 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos,
return res;
}

-static int
+int
nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
{
struct dentry *dentry = file->f_path.dentry;
@@ -248,8 +247,8 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
* nfs_file_write() that a write error occurred, and hence cause it to
* fall back to doing a synchronous write.
*/
-static int
-nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
+int
+nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync)
{
struct dentry *dentry = file->f_path.dentry;
struct nfs_open_context *ctx = nfs_file_open_context(file);
@@ -261,9 +260,6 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
dentry->d_parent->d_name.name, dentry->d_name.name,
datasync);

- ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
- mutex_lock(&inode->i_mutex);
-
nfs_inc_stats(inode, NFSIOS_VFSFSYNC);
have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
status = nfs_commit_inode(inode, FLUSH_SYNC);
@@ -274,10 +270,20 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
ret = xchg(&ctx->error, 0);
if (!ret && status < 0)
ret = status;
- if (!ret && !datasync)
- /* application has asked for meta-data sync */
- ret = pnfs_layoutcommit_inode(inode, true);
+ return ret;
+}
+
+static int
+nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
+{
+ int ret;
+ struct inode *inode = file->f_path.dentry->d_inode;
+
+ ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+ mutex_lock(&inode->i_mutex);
+ ret = nfs_file_fsync_commit(file, start, end, datasync);
mutex_unlock(&inode->i_mutex);
+
return ret;
}

@@ -555,8 +561,8 @@ static int nfs_need_sync_write(struct file *filp, struct inode *inode)
return 0;
}

-static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
+ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
struct dentry * dentry = iocb->ki_filp->f_path.dentry;
struct inode * inode = dentry->d_inode;
@@ -607,9 +613,9 @@ out_swapfile:
goto out;
}

-static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
- struct file *filp, loff_t *ppos,
- size_t count, unsigned int flags)
+ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
+ struct file *filp, loff_t *ppos,
+ size_t count, unsigned int flags)
{
struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
@@ -761,7 +767,7 @@ out:
/*
* Lock a (portion of) a file
*/
-static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
+int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
{
struct inode *inode = filp->f_mapping->host;
int ret = -ENOLCK;
@@ -801,7 +807,7 @@ out_err:
/*
* Lock a (portion of) a file
*/
-static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
+int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
{
struct inode *inode = filp->f_mapping->host;
int is_local = 0;
@@ -831,7 +837,7 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
* There is no protocol support for leases, so we have no way to implement
* them correctly in the face of opens by other clients.
*/
-static int nfs_setlease(struct file *file, long arg, struct file_lock **fl)
+int nfs_setlease(struct file *file, long arg, struct file_lock **fl)
{
dprintk("NFS: setlease(%s/%s, arg=%ld)\n",
file->f_path.dentry->d_parent->d_name.name,
@@ -858,35 +864,3 @@ const struct file_operations nfs_file_operations = {
.setlease = nfs_setlease,
};
EXPORT_SYMBOL_GPL(nfs_file_operations);
-
-#ifdef CONFIG_NFS_V4
-static int
-nfs4_file_open(struct inode *inode, struct file *filp)
-{
- /*
- * NFSv4 opens are handled in d_lookup and d_revalidate. If we get to
- * this point, then something is very wrong
- */
- dprintk("NFS: %s called! inode=%p filp=%p\n", __func__, inode, filp);
- return -ENOTDIR;
-}
-
-const struct file_operations nfs4_file_operations = {
- .llseek = nfs_file_llseek,
- .read = do_sync_read,
- .write = do_sync_write,
- .aio_read = nfs_file_read,
- .aio_write = nfs_file_write,
- .mmap = nfs_file_mmap,
- .open = nfs4_file_open,
- .flush = nfs_file_flush,
- .release = nfs_file_release,
- .fsync = nfs_file_fsync,
- .lock = nfs_lock,
- .flock = nfs_flock,
- .splice_read = nfs_file_splice_read,
- .splice_write = nfs_file_splice_write,
- .check_flags = nfs_check_flags,
- .setlease = nfs_setlease,
-};
-#endif /* CONFIG_NFS_V4 */
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index fa0b531..b5771d5 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -85,6 +85,23 @@ int nfs_link(struct dentry *, struct inode *, struct dentry *);
int nfs_mknod(struct inode *, struct dentry *, umode_t, dev_t);
int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);

+/* Exported in file.c */
+int nfs_file_fsync_commit(struct file *, loff_t, loff_t, int);
+loff_t nfs_file_llseek(struct file *, loff_t, int);
+ssize_t nfs_file_read(struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ssize_t nfs_file_write(struct kiocb *, const struct iovec *, unsigned long, loff_t);
+int nfs_file_mmap(struct file *, struct vm_area_struct *);
+int nfs_file_flush(struct file *, fl_owner_t);
+int nfs_file_release(struct inode *, struct file *);
+int nfs_lock(struct file *, int, struct file_lock *);
+int nfs_flock(struct file *, int, struct file_lock *);
+ssize_t nfs_file_splice_read(struct file *, loff_t *, struct pipe_inode_info *,
+ size_t, unsigned int);
+ssize_t nfs_file_splice_write(struct pipe_inode_info *, struct file *, loff_t *,
+ size_t, unsigned int);
+int nfs_check_flags(int);
+int nfs_setlease(struct file *, long, struct file_lock **);
+
/* Exported in getroot.c */
int nfs_superblock_set_dummy_root(struct super_block *, struct inode *);

diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
new file mode 100644
index 0000000..6c52345
--- /dev/null
+++ b/fs/nfs/nfs4file.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2012 Netapp, Inc. All rights reserved.
+ */
+#include <linux/fs.h>
+#include <linux/nfs_fs.h>
+
+#include "nfs.h"
+#include "pnfs.h"
+
+#define NFSDBG_FACILITY NFSDBG_FILE
+
+static int
+nfs4_file_open(struct inode *inode, struct file *filp)
+{
+ /*
+ * NFSv4 opens are handled in d_lookup and d_revalidate. If we get to
+ * this point, then something is very wrong
+ */
+ dprintk("NFS: %s called! inode=%p filp=%p\n", __func__, inode, filp);
+ return -ENOTDIR;
+}
+
+static int
+nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
+{
+ int ret;
+ struct inode *inode = file->f_path.dentry->d_inode;
+
+ ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+ mutex_lock(&inode->i_mutex);
+ ret = nfs_file_fsync_commit(file, start, end, datasync);
+ if (!ret && !datasync)
+ /* application has asked for meta-data sync */
+ ret = pnfs_layoutcommit_inode(inode, true);
+ mutex_unlock(&inode->i_mutex);
+
+ return ret;
+}
+
+const struct file_operations nfs4_file_operations = {
+ .llseek = nfs_file_llseek,
+ .read = do_sync_read,
+ .write = do_sync_write,
+ .aio_read = nfs_file_read,
+ .aio_write = nfs_file_write,
+ .mmap = nfs_file_mmap,
+ .open = nfs4_file_open,
+ .flush = nfs_file_flush,
+ .release = nfs_file_release,
+ .fsync = nfs4_file_fsync,
+ .lock = nfs_lock,
+ .flock = nfs_flock,
+ .splice_read = nfs_file_splice_read,
+ .splice_write = nfs_file_splice_write,
+ .check_flags = nfs_check_flags,
+ .setlease = nfs_setlease,
+};
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 5e30b57..e4a72d6 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -26,7 +26,6 @@

#include "internal.h"
#include "iostat.h"
-#include "nfs4_fs.h"
#include "fscache.h"
#include "pnfs.h"
#include "nfs.h"
--
1.7.9.4


2012-03-21 16:36:19

by Anna Schumaker

[permalink] [raw]
Subject: Re: [PATCH v4 03/23] NFS: Add version registering framework

On 03/21/2012 11:57 AM, Myklebust, Trond wrote:

> On Wed, 2012-03-21 at 11:20 -0400, [email protected] wrote:
>> From: Bryan Schumaker <[email protected]>
>>
>> This patch adds in the code to track multiple versions of the NFS
>> protocol. I created default structures for v2, v3 and v4 so that each
>> version can continue to work while I convert them into kernel modules.
>> I also removed the const parameter from the rpc_version array so that I
>> can change it at runtime.
>>
>> Signed-off-by: Bryan Schumaker <[email protected]>
>> ---
>> fs/lockd/clnt4xdr.c | 2 +-
>> fs/lockd/clntxdr.c | 6 +--
>> fs/lockd/mon.c | 4 +-
>> fs/nfs/Makefile | 6 +--
>> fs/nfs/client.c | 111 ++++++++++++++++++++++++++++++++++---------
>> fs/nfs/inode.c | 2 +
>> fs/nfs/mount_clnt.c | 6 +--
>> fs/nfs/nfs.h | 35 ++++++++++++++
>> fs/nfs/nfs2super.c | 31 ++++++++++++
>> fs/nfs/nfs2xdr.c | 2 +-
>> fs/nfs/nfs3super.c | 31 ++++++++++++
>> fs/nfs/nfs3xdr.c | 4 +-
>> fs/nfs/nfs4super.c | 31 ++++++++++++
>> fs/nfs/nfs4xdr.c | 2 +-
>> fs/nfs/super.c | 48 ++++++++++++++-----
>> fs/nfsd/nfs4callback.c | 2 +-
>> include/linux/lockd/xdr4.h | 2 +-
>> include/linux/nfs_xdr.h | 8 ++--
>> include/linux/sunrpc/clnt.h | 2 +-
>> net/sunrpc/rpcb_clnt.c | 8 ++--
>> 20 files changed, 280 insertions(+), 63 deletions(-)
>> create mode 100644 fs/nfs/nfs.h
>> create mode 100644 fs/nfs/nfs2super.c
>> create mode 100644 fs/nfs/nfs3super.c
>> create mode 100644 fs/nfs/nfs4super.c
>>
>> diff --git a/fs/lockd/clnt4xdr.c b/fs/lockd/clnt4xdr.c
>> index 3ddcbb1..580dbe2 100644
>> --- a/fs/lockd/clnt4xdr.c
>> +++ b/fs/lockd/clnt4xdr.c
>> @@ -598,7 +598,7 @@ static struct rpc_procinfo nlm4_procedures[] = {
>> PROC(GRANTED_RES, res, norep),
>> };
>>
>> -const struct rpc_version nlm_version4 = {
>> +struct rpc_version nlm_version4 = {
>> .number = 4,
>> .nrprocs = ARRAY_SIZE(nlm4_procedures),
>> .procs = nlm4_procedures,
>> diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c
>> index 3d35e3e..78e80c4 100644
>> --- a/fs/lockd/clntxdr.c
>> +++ b/fs/lockd/clntxdr.c
>> @@ -596,19 +596,19 @@ static struct rpc_procinfo nlm_procedures[] = {
>> PROC(GRANTED_RES, res, norep),
>> };
>>
>> -static const struct rpc_version nlm_version1 = {
>
> Why shouldn't these (and the mount protocol equivalents etc) still be
> declared constant?


I didn't think I'd be allowed to change them if they were const. I removed it from the rpc_ops structure first, and then followed the compiler errors to change the rest.

>
>> +static struct rpc_version nlm_version1 = {
>> .number = 1,
>> .nrprocs = ARRAY_SIZE(nlm_procedures),
>> .procs = nlm_procedures,
>> };
>>
>> -static const struct rpc_version nlm_version3 = {
>> +static struct rpc_version nlm_version3 = {
>> .number = 3,
>> .nrprocs = ARRAY_SIZE(nlm_procedures),
>> .procs = nlm_procedures,
>> };
>>
>> -static const struct rpc_version *nlm_versions[] = {
>> +static struct rpc_version *nlm_versions[] = {
>> [1] = &nlm_version1,
>> [3] = &nlm_version3,
>> #ifdef CONFIG_LOCKD_V4
>> diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
>> index 7ef14b3..888d1ef 100644
>> --- a/fs/lockd/mon.c
>> +++ b/fs/lockd/mon.c
>> @@ -535,13 +535,13 @@ static struct rpc_procinfo nsm_procedures[] = {
>> },
>> };
>>
>> -static const struct rpc_version nsm_version1 = {
>> +static struct rpc_version nsm_version1 = {
>> .number = 1,
>> .nrprocs = ARRAY_SIZE(nsm_procedures),
>> .procs = nsm_procedures
>> };
>>
>> -static const struct rpc_version *nsm_version[] = {
>> +static struct rpc_version *nsm_version[] = {
>> [1] = &nsm_version1,
>> };
>>
>> diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
>> index 7ddd45d..c6e7844 100644
>> --- a/fs/nfs/Makefile
>> +++ b/fs/nfs/Makefile
>> @@ -9,11 +9,11 @@ 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_V2) += nfs2super.o proc.o nfs2xdr.o
>> +nfs-$(CONFIG_NFS_V3) += nfs3super.o nfs3proc.o nfs3xdr.o
>> nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
>> nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
>> - delegation.o idmap.o \
>> + nfs4super.o delegation.o idmap.o \
>> callback.o callback_xdr.o callback_proc.o \
>> nfs4namespace.o
>> nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o
>> diff --git a/fs/nfs/client.c b/fs/nfs/client.c
>> index 4d793b2..0fafedd 100644
>> --- a/fs/nfs/client.c
>> +++ b/fs/nfs/client.c
>> @@ -51,11 +51,14 @@
>> #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 LIST_HEAD(nfs_versions);
>> #ifdef CONFIG_NFS_V4
>>
>> /*
>> @@ -89,16 +92,10 @@ static bool nfs4_disable_idmapping = true;
>> /*
>> * 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
>> +static struct rpc_version *nfs_version[5] = {
>> + [2] = NULL,
>> + [3] = NULL,
>> + [4] = NULL,
>> };
>>
>> const struct rpc_program nfs_program = {
>> @@ -114,10 +111,9 @@ struct rpc_stat nfs_rpcstat = {
>> .program = &nfs_program
>> };
>>
>> -
>> #ifdef CONFIG_NFS_V3_ACL
>> static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program };
>> -static const struct rpc_version *nfsacl_version[] = {
>> +static struct rpc_version *nfsacl_version[] = {
>> [3] = &nfsacl_version3,
>> };
>>
>> @@ -140,6 +136,81 @@ struct nfs_client_initdata {
>> struct net *net;
>> };
>>
>> +static int find_nfs_version(struct nfs_subversion **nfs, unsigned int version)
>> +{
>> + struct nfs_subversion *tmp;
>> + spin_lock(&nfs_version_lock);
>> +
>> + list_for_each_entry_safe((*nfs), tmp, &nfs_versions, list) {
>> + if ((*nfs)->version == version) {
>> + spin_unlock(&nfs_version_lock);
>> + return 1;
>> + }
>> + };
>> +
>> + spin_unlock(&nfs_version_lock);
>> + return 0;
>> +}
>> +
>> +struct nfs_subversion *get_nfs_version(unsigned int version)
>> +{
>> + struct nfs_subversion *nfs;
>> +
>> + if (try_then_request_module(find_nfs_version(&nfs, version), "nfs%d", version))
>> + return nfs;
>> + return ERR_PTR(-EPROTONOSUPPORT);
>> +}
>> +
>> +inline struct nfs_subversion *get_nfs_client_version(struct nfs_client *clp)
>> +{
>> + return get_nfs_version(clp->rpc_ops->version);
>> +}
>> +
>> +inline struct nfs_subversion *get_nfs_server_version(struct nfs_server *srv)
>> +{
>> + return get_nfs_client_version(srv->nfs_client);
>> +}
>> +
>> +void register_nfs_version(struct nfs_subversion *nfs)
>> +{
>> + spin_lock(&nfs_version_lock);
>> +
>> + list_add(&nfs->list, &nfs_versions);
>> + nfs_version[nfs->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->version] = NULL;
>> + list_del(&nfs->list);
>> +
>> + spin_unlock(&nfs_version_lock);
>> +}
>> +EXPORT_SYMBOL_GPL(unregister_nfs_version);
>> +
>> +/*
>> + * Preload all configured NFS versions during module init.
>> + * This function should be edited after each protocol is converted,
>> + * and eventually removed.
>> + */
>> +void __init nfs_register_versions(void)
>> +{
>> +#ifdef CONFIG_NFS_V2
>> + init_nfs_v2();
>> +#endif
>> +#ifdef CONFIG_NFS_V3
>> + init_nfs_v3();
>> +#endif
>> +#ifdef CONFIG_NFS_V4
>> + init_nfs_v4();
>> +#endif
>> +}
>> +
>> /*
>> * Allocate a shared client record
>> *
>> @@ -855,21 +926,15 @@ static int nfs_init_server(struct nfs_server *server,
>> };
>> struct rpc_timeout timeparms;
>> struct nfs_client *clp;
>> + struct nfs_subversion *nfs_mod;
>> int error;
>>
>> dprintk("--> nfs_init_server()\n");
>>
>> -
>> -#ifdef CONFIG_NFS_V2
>> - if (data->version == 2)
>> - cl_init.rpc_ops = &nfs_v2_clientops;
>> -#endif
>> -#ifdef CONFIG_NFS_V3
>> - if (data->version == 3)
>> - cl_init.rpc_ops = &nfs_v3_clientops;
>> -#endif
>> - if (cl_init.rpc_ops == NULL)
>> - return -EPROTONOSUPPORT;
>> + nfs_mod = get_nfs_version(data->version);
>> + if (IS_ERR(nfs_mod))
>> + return PTR_ERR(nfs_mod);
>> + cl_init.rpc_ops = nfs_mod->rpc_ops;
>>
>> nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
>> data->timeo, data->retrans);
>> diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
>> index 7bb4d13..02a1c43 100644
>> --- a/fs/nfs/inode.c
>> +++ b/fs/nfs/inode.c
>> @@ -52,6 +52,7 @@
>> #include "fscache.h"
>> #include "dns_resolve.h"
>> #include "pnfs.h"
>> +#include "nfs.h"
>> #include "netns.h"
>>
>> #define NFSDBG_FACILITY NFSDBG_VFS
>> @@ -1695,6 +1696,7 @@ static int __init init_nfs_fs(void)
>> #endif
>> if ((err = register_nfs_fs()) != 0)
>> goto out;
>> + nfs_register_versions();
>> return 0;
>> out:
>> #ifdef CONFIG_PROC_FS
>> diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
>> index 8e65c7f..ddc7d19 100644
>> --- a/fs/nfs/mount_clnt.c
>> +++ b/fs/nfs/mount_clnt.c
>> @@ -488,19 +488,19 @@ static struct rpc_procinfo mnt3_procedures[] = {
>> };
>>
>>
>> -static const struct rpc_version mnt_version1 = {
>> +static struct rpc_version mnt_version1 = {
>> .number = 1,
>> .nrprocs = ARRAY_SIZE(mnt_procedures),
>> .procs = mnt_procedures,
>> };
>>
>> -static const struct rpc_version mnt_version3 = {
>> +static struct rpc_version mnt_version3 = {
>> .number = 3,
>> .nrprocs = ARRAY_SIZE(mnt3_procedures),
>> .procs = mnt3_procedures,
>> };
>>
>> -static const struct rpc_version *mnt_version[] = {
>> +static struct rpc_version *mnt_version[] = {
>> NULL,
>> &mnt_version1,
>> NULL,
>> diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
>> new file mode 100644
>> index 0000000..05f6849
>> --- /dev/null
>> +++ b/fs/nfs/nfs.h
>> @@ -0,0 +1,35 @@
>> +/*
>> + * 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 {
>> + unsigned int version; /* Protocol number */
> Won't this be a duplicate of what we already have in the rpc_ops?


Yeah, it would. I can change the register() / unregister() functions to take an int in addition to the subversion pointer.

>
>> + struct rpc_version *rpc_vers; /* NFS version information */
>> + const struct nfs_rpc_ops *rpc_ops; /* NFS operations */
>> + struct list_head list; /* List of NFS versions */
>> +
>> + void (*reference)(void); /* For reference counting */
>> + void (*unreference)(void); /* Also for reference counting */
>
> You are always just going to pin and unpin the module, so why do they
> need to be function pointers? Just have each module store a pointer to
> THIS_MODULE in the above structure instead.


That makes sense, I'll change it.

>
>> +};
>> +
>> +void nfs_register_versions(void);
>> +int init_nfs_v2(void);
>> +int init_nfs_v3(void);
>> +int init_nfs_v4(void);
>> +
>> +struct nfs_subversion *get_nfs_version(unsigned int);
>> +struct nfs_subversion *get_nfs_client_version(struct nfs_client *);
>> +struct nfs_subversion *get_nfs_server_version(struct nfs_server *);
>> +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
>> index 0000000..12fa906
>> --- /dev/null
>> +++ b/fs/nfs/nfs2super.c
>> @@ -0,0 +1,31 @@
>> +/*
>> + * Copyright (c) 2012 Netapp, Inc. All rights reserved.
>> + */
>> +#include <linux/module.h>
>> +#include <linux/nfs_fs.h>
>> +#include "nfs.h"
>> +
>> +static void nfs2_reference(void)
>> +{
>> + try_module_get(THIS_MODULE);
>> +}
>> +
>> +static void nfs2_unreference(void)
>> +{
>> + module_put(THIS_MODULE);
>> +}
>> +
>> +static struct nfs_subversion nfs_v2 = {
>> + .version = 2,
>> + .rpc_vers = &nfs_version2,
>> + .rpc_ops = &nfs_v2_clientops,
>> +
>> + .reference = nfs2_reference,
>> + .unreference = nfs2_unreference,
>> +};
>> +
>> +int __init init_nfs_v2(void)
>> +{
>> + register_nfs_version(&nfs_v2);
>> + return 0;
>> +}
>> diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
>> index a01084d..5d9ec8b 100644
>> --- a/fs/nfs/nfs2xdr.c
>> +++ b/fs/nfs/nfs2xdr.c
>> @@ -1086,7 +1086,7 @@ struct rpc_procinfo nfs_procedures[] = {
>> PROC(STATFS, fhandle, statfsres, 0),
>> };
>>
>> -const struct rpc_version nfs_version2 = {
>> +struct rpc_version nfs_version2 = {
>> .number = 2,
>> .nrprocs = ARRAY_SIZE(nfs_procedures),
>> .procs = nfs_procedures
>> diff --git a/fs/nfs/nfs3super.c b/fs/nfs/nfs3super.c
>> new file mode 100644
>> index 0000000..a02c815
>> --- /dev/null
>> +++ b/fs/nfs/nfs3super.c
>> @@ -0,0 +1,31 @@
>> +/*
>> + * Copyright (c) 2012 Netapp, Inc. All rights reserved.
>> + */
>> +#include <linux/module.h>
>> +#include <linux/nfs_fs.h>
>> +#include "nfs.h"
>> +
>> +static void nfs3_reference(void)
>> +{
>> + try_module_get(THIS_MODULE);
>> +}
>> +
>> +static void nfs3_unreference(void)
>> +{
>> + module_put(THIS_MODULE);
>> +}
>> +
>> +static struct nfs_subversion nfs_v3 = {
>> + .version = 3,
>> + .rpc_vers = &nfs_version3,
>> + .rpc_ops = &nfs_v3_clientops,
>> +
>> + .reference = nfs3_reference,
>> + .unreference = nfs3_unreference,
>> +};
>> +
>> +int __init init_nfs_v3(void)
>> +{
>> + register_nfs_version(&nfs_v3);
>> + return 0;
>> +}
>> diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
>> index a77cc9a..5f9aabd 100644
>> --- a/fs/nfs/nfs3xdr.c
>> +++ b/fs/nfs/nfs3xdr.c
>> @@ -2461,7 +2461,7 @@ struct rpc_procinfo nfs3_procedures[] = {
>> PROC(COMMIT, commit, commit, 5),
>> };
>>
>> -const struct rpc_version nfs_version3 = {
>> +struct rpc_version nfs_version3 = {
>> .number = 3,
>> .nrprocs = ARRAY_SIZE(nfs3_procedures),
>> .procs = nfs3_procedures
>> @@ -2489,7 +2489,7 @@ static struct rpc_procinfo nfs3_acl_procedures[] = {
>> },
>> };
>>
>> -const struct rpc_version nfsacl_version3 = {
>> +struct rpc_version nfsacl_version3 = {
>> .number = 3,
>> .nrprocs = sizeof(nfs3_acl_procedures)/
>> sizeof(nfs3_acl_procedures[0]),
>> diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
>> new file mode 100644
>> index 0000000..9b2a679
>> --- /dev/null
>> +++ b/fs/nfs/nfs4super.c
>> @@ -0,0 +1,31 @@
>> +/*
>> + * Copyright (c) 2012 Netapp, Inc. All rights reserved.
>> + */
>> +#include <linux/module.h>
>> +#include <linux/nfs_fs.h>
>> +#include "nfs.h"
>> +
>> +static void nfs4_reference(void)
>> +{
>> + try_module_get(THIS_MODULE);
>> +}
>> +
>> +static void nfs4_unreference(void)
>> +{
>> + module_put(THIS_MODULE);
>> +}
>> +
>> +static struct nfs_subversion nfs_v4 = {
>> + .version = 4,
>> + .rpc_vers = &nfs_version4,
>> + .rpc_ops = &nfs_v4_clientops,
>> +
>> + .reference = nfs4_reference,
>> + .unreference = nfs4_unreference,
>> +};
>> +
>> +int __init init_nfs_v4(void)
>> +{
>> + register_nfs_version(&nfs_v4);
>> + return 0;
>> +}
>> diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
>> index c74fdb1..cfd333c 100644
>> --- a/fs/nfs/nfs4xdr.c
>> +++ b/fs/nfs/nfs4xdr.c
>> @@ -7071,7 +7071,7 @@ struct rpc_procinfo nfs4_procedures[] = {
>> #endif /* CONFIG_NFS_V4_1 */
>> };
>>
>> -const struct rpc_version nfs_version4 = {
>> +struct rpc_version nfs_version4 = {
>> .number = 4,
>> .nrprocs = ARRAY_SIZE(nfs4_procedures),
>> .procs = nfs4_procedures
>> diff --git a/fs/nfs/super.c b/fs/nfs/super.c
>> index aac4030..5ab7c0d 100644
>> --- a/fs/nfs/super.c
>> +++ b/fs/nfs/super.c
>> @@ -65,6 +65,7 @@
>> #include "internal.h"
>> #include "fscache.h"
>> #include "pnfs.h"
>> +#include "nfs.h"
>>
>> #define NFSDBG_FACILITY NFSDBG_VFS
>>
>> @@ -2284,6 +2285,22 @@ static int nfs_bdi_register(struct nfs_server *server)
>> return bdi_register_dev(&server->backing_dev_info, server->s_dev);
>> }
>>
>> +static int nfs_register(struct nfs_server *server)
>> +{
>> + struct nfs_subversion *nfs_mod = get_nfs_server_version(server);
>> + int err = nfs_bdi_register(server);
>> + if (!err)
>> + nfs_mod->reference();
>> + return err;
>> +}
>> +
>> +static void nfs_unregister(struct nfs_server *server)
>> +{
>> + struct nfs_subversion *nfs_mod = get_nfs_server_version(server);
>> + bdi_unregister(&server->backing_dev_info);
>> + nfs_mod->unreference();
>> +}
>> +
>> static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
>> int flags, const char *dev_name, void *raw_data)
>> {
>> @@ -2296,6 +2313,7 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
>> struct nfs_sb_mountdata sb_mntdata = {
>> .mntflags = flags,
>> };
>> + struct nfs_subversion *nfs_mod;
>> int error;
>>
>> data = nfs_alloc_parsed_mount_data(NFS_DEFAULT_VERSION);
>> @@ -2310,6 +2328,12 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
>> goto out;
>> }
>>
>> + nfs_mod = get_nfs_version(data->version);
>> + if (IS_ERR(nfs_mod)) {
>> + mntroot = (struct dentry *)nfs_mod;
>> + goto out;
>> + }
>> +
>> #ifdef CONFIG_NFS_V4
>> if (data->version == 4) {
>> mntroot = nfs4_try_mount(flags, dev_name, data);
>> @@ -2343,7 +2367,7 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
>> nfs_free_server(server);
>> server = NULL;
>> } else {
>> - error = nfs_bdi_register(server);
>> + error = nfs_register(server);
>> if (error) {
>> mntroot = ERR_PTR(error);
>> goto error_splat_bdi;
>> @@ -2380,7 +2404,7 @@ error_splat_root:
>> mntroot = ERR_PTR(error);
>> error_splat_super:
>> if (server && !s->s_root)
>> - bdi_unregister(&server->backing_dev_info);
>> + nfs_unregister(server);
>> error_splat_bdi:
>> deactivate_locked_super(s);
>> goto out;
>> @@ -2392,9 +2416,7 @@ error_splat_bdi:
>> */
>> static void nfs_put_super(struct super_block *s)
>> {
>> - struct nfs_server *server = NFS_SB(s);
>> -
>> - bdi_unregister(&server->backing_dev_info);
>> + nfs_unregister(NFS_SB(s));
>> }
>>
>> /*
>> @@ -2454,7 +2476,7 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,
>> nfs_free_server(server);
>> server = NULL;
>> } else {
>> - error = nfs_bdi_register(server);
>> + error = nfs_register(server);
>> if (error)
>> goto error_splat_bdi;
>> }
>> @@ -2492,7 +2514,7 @@ out_err_noserver:
>>
>> error_splat_super:
>> if (server && !s->s_root)
>> - bdi_unregister(&server->backing_dev_info);
>> + nfs_unregister(server);
>> error_splat_bdi:
>> deactivate_locked_super(s);
>> dprintk("<-- nfs_xdev_mount() = %d [splat]\n", error);
>> @@ -2717,7 +2739,7 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags,
>> nfs_free_server(server);
>> server = NULL;
>> } else {
>> - error = nfs_bdi_register(server);
>> + error = nfs_register(server);
>> if (error)
>> goto error_splat_bdi;
>> }
>> @@ -2755,7 +2777,7 @@ error_splat_root:
>> dput(mntroot);
>> error_splat_super:
>> if (server && !s->s_root)
>> - bdi_unregister(&server->backing_dev_info);
>> + nfs_unregister(server);
>> error_splat_bdi:
>> deactivate_locked_super(s);
>> goto out;
>> @@ -2977,7 +2999,7 @@ nfs4_xdev_mount(struct file_system_type *fs_type, int flags,
>> nfs_free_server(server);
>> server = NULL;
>> } else {
>> - error = nfs_bdi_register(server);
>> + error = nfs_register(server);
>> if (error)
>> goto error_splat_bdi;
>> }
>> @@ -3014,7 +3036,7 @@ out_err_noserver:
>>
>> error_splat_super:
>> if (server && !s->s_root)
>> - bdi_unregister(&server->backing_dev_info);
>> + nfs_unregister(server);
>> error_splat_bdi:
>> deactivate_locked_super(s);
>> dprintk("<-- nfs4_xdev_mount() = %d [splat]\n", error);
>> @@ -3068,7 +3090,7 @@ nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
>> nfs_free_server(server);
>> server = NULL;
>> } else {
>> - error = nfs_bdi_register(server);
>> + error = nfs_register(server);
>> if (error)
>> goto error_splat_bdi;
>> }
>> @@ -3108,7 +3130,7 @@ out_err_nofh:
>>
>> error_splat_super:
>> if (server && !s->s_root)
>> - bdi_unregister(&server->backing_dev_info);
>> + nfs_unregister(server);
>> error_splat_bdi:
>> deactivate_locked_super(s);
>> nfs_free_fhandle(mntfh);
>> diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
>> index 0e262f3..74d19d4 100644
>> --- a/fs/nfsd/nfs4callback.c
>> +++ b/fs/nfsd/nfs4callback.c
>> @@ -605,7 +605,7 @@ static struct rpc_version nfs_cb_version4 = {
>> .procs = nfs4_cb_procedures
>> };
>>
>> -static const struct rpc_version *nfs_cb_version[] = {
>> +static struct rpc_version *nfs_cb_version[] = {
>> &nfs_cb_version4,
>> };
>>
>> diff --git a/include/linux/lockd/xdr4.h b/include/linux/lockd/xdr4.h
>> index e58c88b..7353821 100644
>> --- a/include/linux/lockd/xdr4.h
>> +++ b/include/linux/lockd/xdr4.h
>> @@ -42,6 +42,6 @@ int nlmclt_encode_lockargs(struct rpc_rqst *, u32 *, struct nlm_args *);
>> int nlmclt_encode_cancargs(struct rpc_rqst *, u32 *, struct nlm_args *);
>> int nlmclt_encode_unlockargs(struct rpc_rqst *, u32 *, struct nlm_args *);
>> */
>> -extern const struct rpc_version nlm_version4;
>> +extern struct rpc_version nlm_version4;
>>
>> #endif /* LOCKD_XDR4_H */
>> diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
>> index bfd0d1b..a52ddd5 100644
>> --- a/include/linux/nfs_xdr.h
>> +++ b/include/linux/nfs_xdr.h
>> @@ -1300,11 +1300,11 @@ struct nfs_rpc_ops {
>> extern const struct nfs_rpc_ops nfs_v2_clientops;
>> extern const struct nfs_rpc_ops nfs_v3_clientops;
>> extern const struct nfs_rpc_ops nfs_v4_clientops;
>> -extern const struct rpc_version nfs_version2;
>> -extern const struct rpc_version nfs_version3;
>> -extern const struct rpc_version nfs_version4;
>> +extern struct rpc_version nfs_version2;
>> +extern struct rpc_version nfs_version3;
>> +extern struct rpc_version nfs_version4;
>>
>> -extern const struct rpc_version nfsacl_version3;
>> +extern struct rpc_version nfsacl_version3;
>> extern const struct rpc_program nfsacl_program;
>>
>> #endif
>> diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
>> index 523547e..624d8e3 100644
>> --- a/include/linux/sunrpc/clnt.h
>> +++ b/include/linux/sunrpc/clnt.h
>> @@ -72,7 +72,7 @@ struct rpc_program {
>> const char * name; /* protocol name */
>> u32 number; /* program number */
>> unsigned int nrvers; /* number of versions */
>> - const struct rpc_version ** version; /* version array */
>> + struct rpc_version ** version; /* version array */
>
> This shouldn't be necessary.


Ok, I'll take it out (probably with the rest of the const changes).

- Bryan

>
>> struct rpc_stat * stats; /* statistics */
>> const char * pipe_dir_name; /* path to rpc_pipefs dir */
>> };
>> diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
>> index 207a746..227b5fb 100644
>> --- a/net/sunrpc/rpcb_clnt.c
>> +++ b/net/sunrpc/rpcb_clnt.c
>> @@ -1081,25 +1081,25 @@ static const struct rpcb_info rpcb_next_version6[] = {
>> },
>> };
>>
>> -static const struct rpc_version rpcb_version2 = {
>> +static struct rpc_version rpcb_version2 = {
>> .number = RPCBVERS_2,
>> .nrprocs = ARRAY_SIZE(rpcb_procedures2),
>> .procs = rpcb_procedures2
>> };
>>
>> -static const struct rpc_version rpcb_version3 = {
>> +static struct rpc_version rpcb_version3 = {
>> .number = RPCBVERS_3,
>> .nrprocs = ARRAY_SIZE(rpcb_procedures3),
>> .procs = rpcb_procedures3
>> };
>>
>> -static const struct rpc_version rpcb_version4 = {
>> +static struct rpc_version rpcb_version4 = {
>> .number = RPCBVERS_4,
>> .nrprocs = ARRAY_SIZE(rpcb_procedures4),
>> .procs = rpcb_procedures4
>> };
>>
>> -static const struct rpc_version *rpcb_version[] = {
>> +static struct rpc_version *rpcb_version[] = {
>> NULL,
>> NULL,
>> &rpcb_version2,
>



2012-03-21 15:21:15

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 05/23] NFS: Break up the nfs_fs_mount function

From: Bryan Schumaker <[email protected]>

I keep the first few generic steps before calling into a specific NFS
version to allocate a server and complete the mount. This will
eventually allow each NFS version to do custom server initialization
before attempting a mount, such as setting up the v3 aclclient or
initializing v4.1 pnfs.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 1 +
fs/nfs/nfs.h | 13 ++++++++
fs/nfs/nfs2super.c | 12 ++++++++
fs/nfs/nfs3super.c | 12 ++++++++
fs/nfs/nfs4_fs.h | 5 ++++
fs/nfs/nfs4super.c | 10 +++++++
fs/nfs/super.c | 84 +++++++++++++++++++++++++++-------------------------
7 files changed, 96 insertions(+), 41 deletions(-)

diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index a7e892e..ee4a154 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1284,6 +1284,7 @@ error:
nfs_free_server(server);
return ERR_PTR(error);
}
+EXPORT_SYMBOL_GPL(nfs_create_server);

#ifdef CONFIG_NFS_V4
/*
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index a92514c..a7a08b3 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -11,6 +11,8 @@
#include <linux/sunrpc/sched.h>
#include <linux/nfs_xdr.h>

+struct nfs_parsed_mount_data;
+
struct nfs_subversion {
unsigned int version; /* Protocol number */
struct rpc_version *rpc_vers; /* NFS version information */
@@ -19,6 +21,8 @@ struct nfs_subversion {

void (*reference)(void); /* For reference counting */
void (*unreference)(void); /* Also for reference counting */
+ struct dentry *(*fs_mount)(struct file_system_type *, int, const char *,
+ struct nfs_fh *, struct nfs_parsed_mount_data *);
};

void nfs_register_versions(void);
@@ -31,4 +35,13 @@ struct nfs_subversion *get_nfs_server_version(struct nfs_server *);
void register_nfs_version(struct nfs_subversion *);
void unregister_nfs_version(struct nfs_subversion *);

+/* Exported in client.c */
+struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *, struct nfs_fh *);
+
+/* Exported in super.c */
+struct dentry *_nfs_fs_mount(struct file_system_type *, struct nfs_server *,
+ int, const char *, struct nfs_fh *,
+ struct nfs_parsed_mount_data *);
+
+
#endif /* __LINUX_INTERNAL_NFS_H */
diff --git a/fs/nfs/nfs2super.c b/fs/nfs/nfs2super.c
index 773342d..8f92f5d 100644
--- a/fs/nfs/nfs2super.c
+++ b/fs/nfs/nfs2super.c
@@ -17,6 +17,17 @@ static void nfs2_unreference(void)
module_put(THIS_MODULE);
}

+static struct dentry *nfs2_fs_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name,
+ struct nfs_fh *mntfh,
+ struct nfs_parsed_mount_data *data)
+{
+ struct nfs_server *server = nfs_create_server(data, mntfh);
+ if (IS_ERR(server))
+ return ERR_CAST(server);
+ return _nfs_fs_mount(fs_type, server, flags, dev_name, mntfh, data);
+}
+
static struct nfs_subversion nfs_v2 = {
.version = 2,
.rpc_vers = &nfs_version2,
@@ -24,6 +35,7 @@ static struct nfs_subversion nfs_v2 = {

.reference = nfs2_reference,
.unreference = nfs2_unreference,
+ .fs_mount = nfs2_fs_mount,
};

static int __init init_nfs_v2(void)
diff --git a/fs/nfs/nfs3super.c b/fs/nfs/nfs3super.c
index a02c815..2048460 100644
--- a/fs/nfs/nfs3super.c
+++ b/fs/nfs/nfs3super.c
@@ -15,6 +15,17 @@ static void nfs3_unreference(void)
module_put(THIS_MODULE);
}

+struct dentry *nfs3_fs_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name,
+ struct nfs_fh *mntfh,
+ struct nfs_parsed_mount_data *data)
+{
+ struct nfs_server *server = nfs_create_server(data, mntfh);
+ if (IS_ERR(server))
+ return ERR_CAST(server);
+ return _nfs_fs_mount(fs_type, server, flags, dev_name, mntfh, data);
+}
+
static struct nfs_subversion nfs_v3 = {
.version = 3,
.rpc_vers = &nfs_version3,
@@ -22,6 +33,7 @@ static struct nfs_subversion nfs_v3 = {

.reference = nfs3_reference,
.unreference = nfs3_unreference,
+ .fs_mount = nfs3_fs_mount,
};

int __init init_nfs_v3(void)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 97ecc86..cb2f14c 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -11,6 +11,8 @@

#ifdef CONFIG_NFS_V4

+#include "nfs.h"
+
struct idmap;

enum nfs4_client_state {
@@ -204,6 +206,9 @@ struct nfs4_state_maintenance_ops {
extern const struct dentry_operations nfs4_dentry_operations;
extern const struct inode_operations nfs4_dir_inode_operations;

+/* super.c */
+struct dentry *nfs4_try_mount(int flags, const char *dev_name, struct nfs_parsed_mount_data *);
+
/* nfs4proc.c */
extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *);
extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *);
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 9b2a679..0cc67b6 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -3,6 +3,7 @@
*/
#include <linux/module.h>
#include <linux/nfs_fs.h>
+#include "nfs4_fs.h"
#include "nfs.h"

static void nfs4_reference(void)
@@ -15,6 +16,14 @@ static void nfs4_unreference(void)
module_put(THIS_MODULE);
}

+struct dentry *nfs4_fs_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name,
+ struct nfs_fh *mntfh,
+ struct nfs_parsed_mount_data *data)
+{
+ return nfs4_try_mount(flags, dev_name, data);
+}
+
static struct nfs_subversion nfs_v4 = {
.version = 4,
.rpc_vers = &nfs_version4,
@@ -22,6 +31,7 @@ static struct nfs_subversion nfs_v4 = {

.reference = nfs4_reference,
.unreference = nfs4_unreference,
+ .fs_mount = nfs4_fs_mount,
};

int __init init_nfs_v4(void)
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 5ab7c0d..de9b4f4 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -327,7 +327,7 @@ static const struct super_operations nfs_sops = {
#ifdef CONFIG_NFS_V4
static int nfs4_validate_text_mount_data(void *options,
struct nfs_parsed_mount_data *args, const char *dev_name);
-static struct dentry *nfs4_try_mount(int flags, const char *dev_name,
+struct dentry *nfs4_try_mount(int flags, const char *dev_name,
struct nfs_parsed_mount_data *data);
static struct dentry *nfs4_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data);
@@ -2301,52 +2301,20 @@ static void nfs_unregister(struct nfs_server *server)
nfs_mod->unreference();
}

-static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *raw_data)
+struct dentry *_nfs_fs_mount(struct file_system_type *fs_type,
+ struct nfs_server *server,
+ int flags, const char *dev_name,
+ struct nfs_fh *mntfh,
+ struct nfs_parsed_mount_data *data)
{
- struct nfs_server *server = NULL;
struct super_block *s;
- struct nfs_parsed_mount_data *data;
- struct nfs_fh *mntfh;
struct dentry *mntroot = ERR_PTR(-ENOMEM);
int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
struct nfs_sb_mountdata sb_mntdata = {
.mntflags = flags,
};
- struct nfs_subversion *nfs_mod;
int error;

- data = nfs_alloc_parsed_mount_data(NFS_DEFAULT_VERSION);
- mntfh = nfs_alloc_fhandle();
- if (data == NULL || mntfh == NULL)
- goto out;
-
- /* Validate the mount data */
- error = nfs_validate_mount_data(raw_data, data, mntfh, dev_name);
- if (error < 0) {
- mntroot = ERR_PTR(error);
- goto out;
- }
-
- nfs_mod = get_nfs_version(data->version);
- if (IS_ERR(nfs_mod)) {
- mntroot = (struct dentry *)nfs_mod;
- goto out;
- }
-
-#ifdef CONFIG_NFS_V4
- if (data->version == 4) {
- mntroot = nfs4_try_mount(flags, dev_name, data);
- goto out;
- }
-#endif /* CONFIG_NFS_V4 */
-
- /* Get a volume representation */
- server = nfs_create_server(data, mntfh);
- if (IS_ERR(server)) {
- mntroot = ERR_CAST(server);
- goto out;
- }
sb_mntdata.server = server;

if (server->flags & NFS_MOUNT_UNSHARED)
@@ -2391,8 +2359,6 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
s->s_flags |= MS_ACTIVE;

out:
- nfs_free_parsed_mount_data(data);
- nfs_free_fhandle(mntfh);
return mntroot;

out_err_nosb:
@@ -2409,6 +2375,42 @@ error_splat_bdi:
deactivate_locked_super(s);
goto out;
}
+EXPORT_SYMBOL_GPL(_nfs_fs_mount);
+
+static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *raw_data)
+{
+ struct nfs_parsed_mount_data *data;
+ struct nfs_fh *mntfh;
+ struct dentry *mntroot = ERR_PTR(-ENOMEM);
+ struct nfs_subversion *nfs_mod;
+ int error;
+
+ data = nfs_alloc_parsed_mount_data(NFS_DEFAULT_VERSION);
+ mntfh = nfs_alloc_fhandle();
+ if (data == NULL || mntfh == NULL)
+ goto out;
+
+ /* Validate the mount data */
+ error = nfs_validate_mount_data(raw_data, data, mntfh, dev_name);
+ if (error < 0) {
+ mntroot = ERR_PTR(error);
+ goto out;
+ }
+
+ nfs_mod = get_nfs_version(data->version);
+ if (IS_ERR(nfs_mod)) {
+ mntroot = (struct dentry *)nfs_mod;
+ goto out;
+ }
+
+ mntroot = nfs_mod->fs_mount(fs_type, flags, dev_name, mntfh, data);
+
+out:
+ nfs_free_parsed_mount_data(data);
+ nfs_free_fhandle(mntfh);
+ return mntroot;
+}

/*
* Ensure that we unregister the bdi before kill_anon_super
@@ -2887,7 +2889,7 @@ static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,
return dentry;
}

-static struct dentry *nfs4_try_mount(int flags, const char *dev_name,
+struct dentry *nfs4_try_mount(int flags, const char *dev_name,
struct nfs_parsed_mount_data *data)
{
char *export_path;
--
1.7.9.4


2012-03-21 15:21:22

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 19/23] NFS: Create custom NFS v4 write_inode() function

From: Bryan Schumaker <[email protected]>

This gives pnfs a chance to do a layout commit inside the v4 code.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/nfs4super.c | 20 +++++++++++++++++++-
fs/nfs/write.c | 16 +---------------
2 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index f463a2c..2a3974d 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -27,6 +27,24 @@ static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_typ
int flags, const char *dev_name, void *raw_data);
static void nfs4_kill_super(struct super_block *sb);

+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;
+}
+
/*
* Clean out any remaining NFSv4 state that might be left over due
* to open() calls that passed nfs_atomic_lookup, but failed to call
@@ -87,7 +105,7 @@ struct file_system_type nfs4_referral_fs_type = {
static const struct super_operations nfs4_sops = {
.alloc_inode = nfs_alloc_inode,
.destroy_inode = nfs_destroy_inode,
- .write_inode = nfs_write_inode,
+ .write_inode = nfs4_write_inode,
.put_super = nfs_put_super,
.statfs = nfs_statfs,
.evict_inode = nfs4_evict_inode,
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index e4a72d6..5b28bbe 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1620,21 +1620,7 @@ static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_contr

int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
{
- int ret;
-
- ret = nfs_commit_unstable_pages(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;
+ return nfs_commit_unstable_pages(inode, wbc);
}

/*
--
1.7.9.4


2012-03-21 15:21:17

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 09/23] NFS: Convert v3 into a module

From: Bryan Schumaker <[email protected]>

This patch exports symbols and moves over the final structures needed by
the v3 module. In addition, I also switch over to using IS_ENABLED() to
check if CONFIG_NFS_V3 or CONFIG_NFS_V3_MODULE are set.

The module (nfs3.ko) will be created in the same directory as nfs.ko and
will be automatically loaded the first time you try to mount over NFS v3.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Kconfig | 2 +-
fs/nfs/Makefile | 6 +++--
fs/nfs/client.c | 18 --------------
fs/nfs/dir.c | 65 ++++++++++++++++--------------------------------
fs/nfs/direct.c | 2 +-
fs/nfs/file.c | 12 ---------
fs/nfs/inode.c | 5 ++++
fs/nfs/nfs.h | 12 ++++++++-
fs/nfs/nfs3client.c | 15 ++++++++++-
fs/nfs/nfs3super.c | 41 +++++++++++++++++++++++++++++-
fs/nfs/super.c | 6 ++---
fs/nfs/write.c | 8 +++---
include/linux/nfs_fs.h | 6 ++---
13 files changed, 108 insertions(+), 90 deletions(-)
create mode 100644 fs/nfs/dangling.txt

diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index 9663563..1e11b08 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -39,7 +39,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
help
This option enables support for version 3 of the NFS protocol
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 6764e66..e155299 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -9,8 +9,6 @@ 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_V3) += nfs3super.o nfs3client.o 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 delegation.o idmap.o \
callback.o callback_xdr.o callback_proc.o \
@@ -22,6 +20,10 @@ nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
obj-$(CONFIG_NFS_V2) += nfs2.o
nfs2-y += nfs2super.o proc.o nfs2xdr.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_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o
nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o

diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 5db8005..66d4875 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -111,21 +111,6 @@ struct rpc_stat nfs_rpcstat = {
.program = &nfs_program
};

-#ifdef CONFIG_NFS_V3_ACL
-static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program };
-static 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,
-};
-#endif /* CONFIG_NFS_V3_ACL */
-
struct nfs_client_initdata {
const char *hostname;
const struct sockaddr *addr;
@@ -200,9 +185,6 @@ EXPORT_SYMBOL_GPL(unregister_nfs_version);
*/
void __init nfs_register_versions(void)
{
-#ifdef CONFIG_NFS_V3
- init_nfs_v3();
-#endif
#ifdef CONFIG_NFS_V4
init_nfs_v4();
#endif
diff --git a/fs/nfs/dangling.txt b/fs/nfs/dangling.txt
new file mode 100644
index 0000000..e69de29
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 08b3d15..4e8d06b 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -41,22 +41,13 @@
#include "iostat.h"
#include "internal.h"
#include "fscache.h"
+#include "nfs.h"

/* #define NFS_DEBUG_VERBOSE 1 */

static int nfs_opendir(struct inode *, struct file *);
static int nfs_closedir(struct inode *, struct file *);
static int nfs_readdir(struct file *, void *, filldir_t);
-static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *);
-static int nfs_create(struct inode *, struct dentry *, umode_t, struct nameidata *);
-static int nfs_mkdir(struct inode *, struct dentry *, umode_t);
-static int nfs_rmdir(struct inode *, struct dentry *);
-static int nfs_unlink(struct inode *, struct dentry *);
-static int nfs_symlink(struct inode *, struct dentry *, const char *);
-static int nfs_link(struct dentry *, struct inode *, struct dentry *);
-static int nfs_mknod(struct inode *, struct dentry *, umode_t, dev_t);
-static int nfs_rename(struct inode *, struct dentry *,
- struct inode *, struct dentry *);
static int nfs_fsync_dir(struct file *, loff_t, loff_t, int);
static loff_t nfs_llseek_dir(struct file *, loff_t, int);
static void nfs_readdir_clear_array(struct page*);
@@ -90,27 +81,6 @@ const struct address_space_operations nfs_dir_aops = {
.freepage = nfs_readdir_clear_array,
};

-#ifdef CONFIG_NFS_V3
-const struct inode_operations nfs3_dir_inode_operations = {
- .create = nfs_create,
- .lookup = nfs_lookup,
- .link = nfs_link,
- .unlink = nfs_unlink,
- .symlink = nfs_symlink,
- .mkdir = nfs_mkdir,
- .rmdir = nfs_rmdir,
- .mknod = nfs_mknod,
- .rename = nfs_rename,
- .permission = nfs_permission,
- .getattr = nfs_getattr,
- .setattr = nfs_setattr,
- .listxattr = nfs3_listxattr,
- .getxattr = nfs3_getxattr,
- .setxattr = nfs3_setxattr,
- .removexattr = nfs3_removexattr,
-};
-#endif /* CONFIG_NFS_V3 */
-
#ifdef CONFIG_NFS_V4

static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
@@ -1266,7 +1236,7 @@ const struct dentry_operations nfs_dentry_operations = {
};
EXPORT_SYMBOL_GPL(nfs_dentry_operations);

-static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
+struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
{
struct dentry *res;
struct dentry *parent;
@@ -1329,6 +1299,7 @@ out:
nfs_free_fhandle(fhandle);
return res;
}
+EXPORT_SYMBOL_GPL(nfs_lookup);

#ifdef CONFIG_NFS_V4
static int nfs_open_revalidate(struct dentry *, struct nameidata *);
@@ -1681,7 +1652,7 @@ EXPORT_SYMBOL_GPL(nfs_instantiate);
* that the operation succeeded on the server, but an error in the
* reply path made it appear to have failed.
*/
-static int nfs_create(struct inode *dir, struct dentry *dentry,
+int nfs_create(struct inode *dir, struct dentry *dentry,
umode_t mode, struct nameidata *nd)
{
struct iattr attr;
@@ -1705,12 +1676,12 @@ out_err:
d_drop(dentry);
return error;
}
+EXPORT_SYMBOL_GPL(nfs_create);

/*
* See comments for nfs_proc_create regarding failed operations.
*/
-static int
-nfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
+int nfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
{
struct iattr attr;
int status;
@@ -1732,11 +1703,12 @@ out_err:
d_drop(dentry);
return status;
}
+EXPORT_SYMBOL_GPL(nfs_mknod);

/*
* See comments for nfs_proc_create regarding failed operations.
*/
-static int nfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+int nfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
struct iattr attr;
int error;
@@ -1755,6 +1727,7 @@ out_err:
d_drop(dentry);
return error;
}
+EXPORT_SYMBOL_GPL(nfs_mkdir);

static void nfs_dentry_handle_enoent(struct dentry *dentry)
{
@@ -1762,7 +1735,7 @@ static void nfs_dentry_handle_enoent(struct dentry *dentry)
d_delete(dentry);
}

-static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
+int nfs_rmdir(struct inode *dir, struct dentry *dentry)
{
int error;

@@ -1778,6 +1751,7 @@ static 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,
@@ -1821,7 +1795,7 @@ out:
*
* If sillyrename() returns 0, we do nothing, otherwise we unlink.
*/
-static int nfs_unlink(struct inode *dir, struct dentry *dentry)
+int nfs_unlink(struct inode *dir, struct dentry *dentry)
{
int error;
int need_rehash = 0;
@@ -1849,6 +1823,7 @@ static 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,
@@ -1865,7 +1840,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry)
* now have a new file handle and can instantiate an in-core NFS inode
* and move the raw page into its mapping.
*/
-static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
+int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
{
struct pagevec lru_pvec;
struct page *page;
@@ -1919,9 +1894,9 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym

return 0;
}
+EXPORT_SYMBOL_GPL(nfs_symlink);

-static int
-nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
+int nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
{
struct inode *inode = old_dentry->d_inode;
int error;
@@ -1940,6 +1915,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
}
return error;
}
+EXPORT_SYMBOL_GPL(nfs_link);

/*
* RENAME
@@ -1965,8 +1941,8 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
* If these conditions are met, we can drop the dentries before doing
* the rename.
*/
-static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
{
struct inode *old_inode = old_dentry->d_inode;
struct inode *new_inode = new_dentry->d_inode;
@@ -2038,6 +2014,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);
@@ -2138,6 +2115,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)
{
@@ -2357,6 +2335,7 @@ out_notsup:
res = generic_permission(inode, mask);
goto out;
}
+EXPORT_SYMBOL_GPL(nfs_permission);

/*
* Local variables:
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 9c7f66a..18b16a7 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -458,7 +458,7 @@ static void nfs_direct_free_writedata(struct nfs_direct_req *dreq)
}
}

-#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
{
struct inode *inode = dreq->inode;
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 94af2db..c678c00 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -50,18 +50,6 @@ const struct inode_operations nfs_file_inode_operations = {
};
EXPORT_SYMBOL_GPL(nfs_file_inode_operations);

-#ifdef CONFIG_NFS_V3
-const struct inode_operations nfs3_file_inode_operations = {
- .permission = nfs_permission,
- .getattr = nfs_getattr,
- .setattr = nfs_setattr,
- .listxattr = nfs3_listxattr,
- .getxattr = nfs3_getxattr,
- .setxattr = nfs3_setxattr,
- .removexattr = nfs3_removexattr,
-};
-#endif /* CONFIG_NFS_v3 */
-
/* Hack for future NFS swap support */
#ifndef IS_SWAPFILE
# define IS_SWAPFILE(inode) (0)
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index d6db30b..88da7cd 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -188,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)
{
@@ -450,6 +451,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
@@ -547,6 +549,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)
{
@@ -853,6 +856,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)
{
@@ -1210,6 +1214,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
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 8ac594b..9caae33 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -28,7 +28,6 @@ struct nfs_subversion {
};

void nfs_register_versions(void);
-int init_nfs_v3(void);
int init_nfs_v4(void);

struct nfs_subversion *get_nfs_version(unsigned int);
@@ -40,6 +39,17 @@ void unregister_nfs_version(struct nfs_subversion *);
/* Exported in client.c */
struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *, struct nfs_fh *);

+/* Exported in dir.c */
+struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *);
+int nfs_create(struct inode *, struct dentry *, umode_t, struct nameidata *);
+int nfs_mkdir(struct inode *, struct dentry *, umode_t);
+int nfs_rmdir(struct inode *, struct dentry *);
+int nfs_unlink(struct inode *, struct dentry *);
+int nfs_symlink(struct inode *, struct dentry *, const char *);
+int nfs_link(struct dentry *, struct inode *, struct dentry *);
+int nfs_mknod(struct inode *, struct dentry *, umode_t, dev_t);
+int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
+
/* Exported in super.c */
extern struct file_system_type nfs_fs_type;
struct dentry *_nfs_fs_mount(struct file_system_type *, struct nfs_server *,
diff --git a/fs/nfs/nfs3client.c b/fs/nfs/nfs3client.c
index c2e6593..00daf1b 100644
--- a/fs/nfs/nfs3client.c
+++ b/fs/nfs/nfs3client.c
@@ -13,10 +13,23 @@
#include "internal.h"
#include "nfs.h"

+#ifdef CONFIG_NFS_V3_ACL
+static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program };
+static 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
*/
-#ifdef CONFIG_NFS_V3_ACL
static void nfs_init_server_aclclient(struct nfs_server *server)
{
if (server->flags & NFS_MOUNT_NOACL)
diff --git a/fs/nfs/nfs3super.c b/fs/nfs/nfs3super.c
index 5702895..8cf7371 100644
--- a/fs/nfs/nfs3super.c
+++ b/fs/nfs/nfs3super.c
@@ -41,6 +41,35 @@ static struct dentry *nfs3_xdev_mount(int flags, const char *dev_name,
return _nfs_xdev_mount(&nfs_fs_type, server, flags, dev_name, data, NFS_MOUNT_UNSHARED);
}

+const struct inode_operations nfs3_file_inode_operations = {
+ .permission = nfs_permission,
+ .getattr = nfs_getattr,
+ .setattr = nfs_setattr,
+ .listxattr = nfs3_listxattr,
+ .getxattr = nfs3_getxattr,
+ .setxattr = nfs3_setxattr,
+ .removexattr = nfs3_removexattr,
+};
+
+const struct inode_operations nfs3_dir_inode_operations = {
+ .create = nfs_create,
+ .lookup = nfs_lookup,
+ .link = nfs_link,
+ .unlink = nfs_unlink,
+ .symlink = nfs_symlink,
+ .mkdir = nfs_mkdir,
+ .rmdir = nfs_rmdir,
+ .mknod = nfs_mknod,
+ .rename = nfs_rename,
+ .permission = nfs_permission,
+ .getattr = nfs_getattr,
+ .setattr = nfs_setattr,
+ .listxattr = nfs3_listxattr,
+ .getxattr = nfs3_getxattr,
+ .setxattr = nfs3_setxattr,
+ .removexattr = nfs3_removexattr,
+};
+
static struct nfs_subversion nfs_v3 = {
.version = 3,
.rpc_vers = &nfs_version3,
@@ -52,8 +81,18 @@ static struct nfs_subversion nfs_v3 = {
.xdev_mount = nfs3_xdev_mount,
};

-int __init init_nfs_v3(void)
+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);
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 810b28e..9a9d45d 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -69,7 +69,7 @@

#define NFSDBG_FACILITY NFSDBG_VFS

-#ifdef CONFIG_NFS_V3
+#if IS_ENABLED(CONFIG_NFS_V3)
#define NFS_DEFAULT_VERSION 3
#else
#define NFS_DEFAULT_VERSION 2
@@ -1974,7 +1974,7 @@ static int nfs_validate_mount_data(void *options,
}
}

-#ifndef CONFIG_NFS_V3
+#if !IS_ENABLED(CONFIG_NFS_V3)
if (args->version == 3)
goto out_v3_not_compiled;
#endif /* !CONFIG_NFS_V3 */
@@ -1994,7 +1994,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;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 2c68818..0f28bd2 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -417,7 +417,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) || defined(CONFIG_NFS_V4)
/**
* nfs_request_add_commit_list - add request to a commit list
* @req: pointer to a struct nfs_page
@@ -552,7 +552,7 @@ int nfs_reschedule_unstable_write(struct nfs_page *req,
}
#endif

-#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
static int
nfs_need_commit(struct nfs_inode *nfsi)
{
@@ -1271,7 +1271,7 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
return;
nfs_add_stats(data->inode, NFSIOS_SERVERWRITTENBYTES, resp->count);

-#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V3) || defined(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
@@ -1330,7 +1330,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) || defined(CONFIG_NFS_V4)
static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait)
{
int ret;
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 52a1bdb..3e0758e 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -432,7 +432,7 @@ extern __be32 root_nfs_parse_addr(char *name); /*__init*/
* linux/fs/nfs/file.c
*/
extern const struct inode_operations nfs_file_inode_operations;
-#ifdef CONFIG_NFS_V3
+#if IS_ENABLED(CONFIG_NFS_V3)
extern const struct inode_operations nfs3_file_inode_operations;
#endif /* CONFIG_NFS_V3 */
extern const struct file_operations nfs_file_operations;
@@ -490,7 +490,7 @@ extern ssize_t nfs_file_direct_write(struct kiocb *iocb,
* linux/fs/nfs/dir.c
*/
extern const struct inode_operations nfs_dir_inode_operations;
-#ifdef CONFIG_NFS_V3
+#if IS_ENABLED(CONFIG_NFS_V3)
extern const struct inode_operations nfs3_dir_inode_operations;
#endif /* CONFIG_NFS_V3 */
extern const struct file_operations nfs_dir_operations;
@@ -550,7 +550,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) || defined(CONFIG_NFS_V4)
extern int nfs_commit_inode(struct inode *, int);
extern struct nfs_write_data *nfs_commitdata_alloc(void);
extern void nfs_commit_free(struct nfs_write_data *wdata);
--
1.7.9.4


2012-03-21 15:21:20

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 16/23] NFS: Move the v4 getroot code to nfs4getroot.c

From: Bryan Schumaker <[email protected]>

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Makefile | 3 +-
fs/nfs/getroot.c | 135 +-------------------------------------------------
fs/nfs/nfs.h | 3 ++
fs/nfs/nfs4getroot.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 141 insertions(+), 135 deletions(-)
create mode 100644 fs/nfs/nfs4getroot.c

diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index cf8b669..8028e09 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -12,7 +12,8 @@ nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
nfs4super.o delegation.o idmap.o \
callback.o callback_xdr.o callback_proc.o \
- nfs4namespace.o nfs4sysctl.o nfs4client.o
+ nfs4namespace.o nfs4sysctl.o nfs4client.o \
+ nfs4getroot.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
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index dcb6154..f6a14a6 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -23,11 +23,9 @@
#include <linux/sunrpc/stats.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_mount.h>
-#include <linux/nfs4_mount.h>
#include <linux/lockd/bind.h>
#include <linux/seq_file.h>
#include <linux/mount.h>
-#include <linux/nfs_idmap.h>
#include <linux/vfs.h>
#include <linux/namei.h>
#include <linux/security.h>
@@ -35,17 +33,13 @@
#include <asm/system.h>
#include <asm/uaccess.h>

-#include "nfs4_fs.h"
-#include "delegation.h"
-#include "internal.h"
-
#define NFSDBG_FACILITY NFSDBG_CLIENT

/*
* Set the superblock root dentry.
* Note that this function frees the inode in case of error.
*/
-static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *inode)
+int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *inode)
{
/* The mntroot acts as the dummy root dentry for this superblock */
if (sb->s_root == NULL) {
@@ -138,130 +132,3 @@ out:
nfs_free_fattr(fsinfo.fattr);
return ret;
}
-
-#ifdef CONFIG_NFS_V4
-
-int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh)
-{
- struct nfs_fsinfo fsinfo;
- int ret = -ENOMEM;
-
- dprintk("--> nfs4_get_rootfh()\n");
-
- fsinfo.fattr = nfs_alloc_fattr();
- if (fsinfo.fattr == NULL)
- goto out;
-
- /* Start by getting the root filehandle from the server */
- ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
- if (ret < 0) {
- dprintk("nfs4_get_rootfh: getroot error = %d\n", -ret);
- goto out;
- }
-
- if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_TYPE)
- || !S_ISDIR(fsinfo.fattr->mode)) {
- printk(KERN_ERR "nfs4_get_rootfh:"
- " getroot encountered non-directory\n");
- ret = -ENOTDIR;
- goto out;
- }
-
- if (fsinfo.fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) {
- printk(KERN_ERR "nfs4_get_rootfh:"
- " getroot obtained referral\n");
- ret = -EREMOTE;
- goto out;
- }
-
- memcpy(&server->fsid, &fsinfo.fattr->fsid, sizeof(server->fsid));
-out:
- nfs_free_fattr(fsinfo.fattr);
- dprintk("<-- nfs4_get_rootfh() = %d\n", ret);
- return ret;
-}
-
-/*
- * get an NFS4 root dentry from the root filehandle
- */
-struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh,
- const char *devname)
-{
- struct nfs_server *server = NFS_SB(sb);
- struct nfs_fattr *fattr = NULL;
- struct dentry *ret;
- struct inode *inode;
- void *name = kstrdup(devname, GFP_KERNEL);
- int error;
-
- dprintk("--> nfs4_get_root()\n");
-
- if (!name)
- return ERR_PTR(-ENOMEM);
-
- /* get the info about the server and filesystem */
- error = nfs4_server_capabilities(server, mntfh);
- if (error < 0) {
- dprintk("nfs_get_root: getcaps error = %d\n",
- -error);
- kfree(name);
- return ERR_PTR(error);
- }
-
- fattr = nfs_alloc_fattr();
- if (fattr == NULL) {
- kfree(name);
- return ERR_PTR(-ENOMEM);
- }
-
- /* get the actual root for this mount */
- error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr);
- if (error < 0) {
- dprintk("nfs_get_root: getattr error = %d\n", -error);
- ret = ERR_PTR(error);
- goto out;
- }
-
- if (fattr->valid & NFS_ATTR_FATTR_FSID &&
- !nfs_fsid_equal(&server->fsid, &fattr->fsid))
- memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid));
-
- inode = nfs_fhget(sb, mntfh, fattr);
- if (IS_ERR(inode)) {
- dprintk("nfs_get_root: get root inode failed\n");
- ret = ERR_CAST(inode);
- goto out;
- }
-
- error = nfs_superblock_set_dummy_root(sb, inode);
- if (error != 0) {
- ret = ERR_PTR(error);
- goto out;
- }
-
- /* root dentries normally start off anonymous and get spliced in later
- * if the dentry tree reaches them; however if the dentry already
- * exists, we'll pick it up at this point and use it as the root
- */
- ret = d_obtain_alias(inode);
- if (IS_ERR(ret)) {
- dprintk("nfs_get_root: get root dentry failed\n");
- goto out;
- }
-
- security_d_instantiate(ret, inode);
- spin_lock(&ret->d_lock);
- if (IS_ROOT(ret) && !(ret->d_flags & DCACHE_NFSFS_RENAMED)) {
- ret->d_fsdata = name;
- name = NULL;
- }
- spin_unlock(&ret->d_lock);
-out:
- if (name)
- kfree(name);
- nfs_free_fattr(fattr);
- dprintk("<-- nfs4_get_root()\n");
- return ret;
-}
-
-#endif /* CONFIG_NFS_V4 */
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index d53f350..877ca24 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -83,6 +83,9 @@ int nfs_link(struct dentry *, struct inode *, struct dentry *);
int nfs_mknod(struct inode *, struct dentry *, umode_t, dev_t);
int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);

+/* Exported in getroot.c */
+int nfs_superblock_set_dummy_root(struct super_block *, struct inode *);
+
/* Exported in namespace.c */
struct vfsmount *_nfs_do_submount(struct file_system_type *, struct dentry *,
struct nfs_fh *, struct nfs_fattr *, rpc_authflavor_t);
diff --git a/fs/nfs/nfs4getroot.c b/fs/nfs/nfs4getroot.c
new file mode 100644
index 0000000..14eea8d
--- /dev/null
+++ b/fs/nfs/nfs4getroot.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells ([email protected])
+ */
+#include <linux/sunrpc/sched.h>
+#include <linux/dcache.h>
+#include <linux/nfs_fs.h>
+#include <linux/nfs_xdr.h>
+
+#include "nfs4_fs.h"
+
+#define NFSDBG_FACILITY NFSDBG_CLIENT
+
+int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh)
+{
+ struct nfs_fsinfo fsinfo;
+ int ret = -ENOMEM;
+
+ dprintk("--> nfs4_get_rootfh()\n");
+
+ fsinfo.fattr = nfs_alloc_fattr();
+ if (fsinfo.fattr == NULL)
+ goto out;
+
+ /* Start by getting the root filehandle from the server */
+ ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
+ if (ret < 0) {
+ dprintk("nfs4_get_rootfh: getroot error = %d\n", -ret);
+ goto out;
+ }
+
+ if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_TYPE)
+ || !S_ISDIR(fsinfo.fattr->mode)) {
+ printk(KERN_ERR "nfs4_get_rootfh:"
+ " getroot encountered non-directory\n");
+ ret = -ENOTDIR;
+ goto out;
+ }
+
+ if (fsinfo.fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) {
+ printk(KERN_ERR "nfs4_get_rootfh:"
+ " getroot obtained referral\n");
+ ret = -EREMOTE;
+ goto out;
+ }
+
+ memcpy(&server->fsid, &fsinfo.fattr->fsid, sizeof(server->fsid));
+out:
+ nfs_free_fattr(fsinfo.fattr);
+ dprintk("<-- nfs4_get_rootfh() = %d\n", ret);
+ return ret;
+}
+
+/*
+ * get an NFS4 root dentry from the root filehandle
+ */
+struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh,
+ const char *devname)
+{
+ struct nfs_server *server = NFS_SB(sb);
+ struct nfs_fattr *fattr = NULL;
+ struct dentry *ret;
+ struct inode *inode;
+ void *name = kstrdup(devname, GFP_KERNEL);
+ int error;
+
+ dprintk("--> nfs4_get_root()\n");
+
+ if (!name)
+ return ERR_PTR(-ENOMEM);
+
+ /* get the info about the server and filesystem */
+ error = nfs4_server_capabilities(server, mntfh);
+ if (error < 0) {
+ dprintk("nfs_get_root: getcaps error = %d\n",
+ -error);
+ kfree(name);
+ return ERR_PTR(error);
+ }
+
+ fattr = nfs_alloc_fattr();
+ if (fattr == NULL) {
+ kfree(name);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* get the actual root for this mount */
+ error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr);
+ if (error < 0) {
+ dprintk("nfs_get_root: getattr error = %d\n", -error);
+ ret = ERR_PTR(error);
+ goto out;
+ }
+
+ if (fattr->valid & NFS_ATTR_FATTR_FSID &&
+ !nfs_fsid_equal(&server->fsid, &fattr->fsid))
+ memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid));
+
+ inode = nfs_fhget(sb, mntfh, fattr);
+ if (IS_ERR(inode)) {
+ dprintk("nfs_get_root: get root inode failed\n");
+ ret = ERR_CAST(inode);
+ goto out;
+ }
+
+ error = nfs_superblock_set_dummy_root(sb, inode);
+ if (error != 0) {
+ ret = ERR_PTR(error);
+ goto out;
+ }
+
+ /* root dentries normally start off anonymous and get spliced in later
+ * if the dentry tree reaches them; however if the dentry already
+ * exists, we'll pick it up at this point and use it as the root
+ */
+ ret = d_obtain_alias(inode);
+ if (IS_ERR(ret)) {
+ dprintk("nfs_get_root: get root dentry failed\n");
+ goto out;
+ }
+
+ security_d_instantiate(ret, inode);
+ spin_lock(&ret->d_lock);
+ if (IS_ROOT(ret) && !(ret->d_flags & DCACHE_NFSFS_RENAMED)) {
+ ret->d_fsdata = name;
+ name = NULL;
+ }
+ spin_unlock(&ret->d_lock);
+out:
+ if (name)
+ kfree(name);
+ nfs_free_fattr(fattr);
+ dprintk("<-- nfs4_get_root()\n");
+ return ret;
+}
--
1.7.9.4


2012-03-21 15:21:17

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 10/23] NFS: Initialize NFS v4 from nfs4super.c

From: Bryan Schumaker <[email protected]>

This includes starting the idmapper, registering sysctls and registering
the nfs_subversion struct with the generic NFS client. I also added in
a call to exit_nfs_v4() when the NFS module exits to undo everything
before exiting.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Makefile | 2 +-
fs/nfs/client.c | 12 ----------
fs/nfs/inode.c | 14 +++++------
fs/nfs/nfs.h | 2 +-
fs/nfs/nfs4_fs.h | 9 +++++++
fs/nfs/nfs4super.c | 23 ++++++++++++++++++
fs/nfs/{sysctl.c => nfs4sysctl.c} | 47 ++++++++++++++-----------------------
fs/nfs/sysctl.c | 26 --------------------
8 files changed, 57 insertions(+), 78 deletions(-)
copy fs/nfs/{sysctl.c => nfs4sysctl.c} (51%)

diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index e155299..7c8a7a0 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -12,7 +12,7 @@ nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
nfs4super.o delegation.o idmap.o \
callback.o callback_xdr.o callback_proc.o \
- nfs4namespace.o
+ nfs4namespace.o nfs4sysctl.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
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 66d4875..adc548c 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -179,18 +179,6 @@ void unregister_nfs_version(struct nfs_subversion *nfs)
EXPORT_SYMBOL_GPL(unregister_nfs_version);

/*
- * Preload all configured NFS versions during module init.
- * This function should be edited after each protocol is converted,
- * and eventually removed.
- */
-void __init nfs_register_versions(void)
-{
-#ifdef CONFIG_NFS_V4
- init_nfs_v4();
-#endif
-}
-
-/*
* Allocate a shared client record
*
* Since these are allocated/deallocated very rarely, we don't
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 88da7cd..30c7103 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1660,10 +1660,6 @@ static int __init init_nfs_fs(void)
{
int err;

- err = nfs_idmap_init();
- if (err < 0)
- goto out10;
-
err = nfs_dns_resolver_init();
if (err < 0)
goto out9;
@@ -1709,7 +1705,9 @@ static int __init init_nfs_fs(void)
#endif
if ((err = register_nfs_fs()) != 0)
goto out;
- nfs_register_versions();
+#ifdef CONFIG_NFS_V4
+ init_nfs_v4();
+#endif
return 0;
out:
#ifdef CONFIG_PROC_FS
@@ -1735,13 +1733,14 @@ out7:
out8:
nfs_dns_resolver_destroy();
out9:
- nfs_idmap_quit();
-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();
@@ -1750,7 +1749,6 @@ static void __exit exit_nfs_fs(void)
nfs_fscache_unregister();
unregister_pernet_subsys(&nfs_net_ops);
nfs_dns_resolver_destroy();
- nfs_idmap_quit();
#ifdef CONFIG_PROC_FS
rpc_proc_unregister(&init_net, "nfs");
#endif
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 9caae33..1f93181 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -27,8 +27,8 @@ struct nfs_subversion {
struct dentry *(*xdev_mount)(int, const char *, struct nfs_clone_mount *);
};

-void nfs_register_versions(void);
int init_nfs_v4(void);
+void exit_nfs_v4(void);

struct nfs_subversion *get_nfs_version(unsigned int);
struct nfs_subversion *get_nfs_client_version(struct nfs_client *);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 6786c4f..0652352 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -350,6 +350,15 @@ extern void nfs4_free_lock_state(struct nfs_server *server, struct nfs4_lock_sta

extern const nfs4_stateid zero_stateid;

+/* nfs4sysctl.h */
+#ifdef CONFIG_SYSCTL
+int nfs4_register_sysctl(void);
+void nfs4_unregister_sysctl(void);
+#else
+inline int nfs4_register_sysctl(void) { return 0; }
+inline void nfs4_unregister_sysctl(void) { }
+#endif /* CONFIG_SYSCTL */
+
/* nfs4xdr.c */
extern struct rpc_procinfo nfs4_procedures[];

diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index f6c8f9f..9dc0c37 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -4,6 +4,7 @@
#include <linux/module.h>
#include <linux/nfs_fs.h>
#include <linux/nfs4_mount.h>
+#include <linux/nfs_idmap.h>
#include "internal.h"
#include "nfs4_fs.h"
#include "nfs.h"
@@ -51,6 +52,28 @@ static struct nfs_subversion nfs_v4 = {

int __init init_nfs_v4(void)
{
+ int err;
+
+ err = nfs_idmap_init();
+ if (err < 0)
+ goto out_1;
+
+ err = nfs4_register_sysctl();
+ if (err < 0)
+ goto out_0;
+
register_nfs_version(&nfs_v4);
return 0;
+
+out_0:
+ nfs_idmap_quit();
+out_1:
+ return err;
+}
+
+void __exit exit_nfs_v4(void)
+{
+ unregister_nfs_version(&nfs_v4);
+ nfs4_unregister_sysctl();
+ nfs_idmap_quit();
}
diff --git a/fs/nfs/sysctl.c b/fs/nfs/nfs4sysctl.c
similarity index 51%
copy from fs/nfs/sysctl.c
copy to fs/nfs/nfs4sysctl.c
index ad4d2e7..07b67bb 100644
--- a/fs/nfs/sysctl.c
+++ b/fs/nfs/nfs4sysctl.c
@@ -3,6 +3,9 @@
*
* Sysctl interface to NFS parameters
*/
+
+#ifdef CONFIG_SYSCTL
+
#include <linux/types.h>
#include <linux/linkage.h>
#include <linux/ctype.h>
@@ -15,14 +18,11 @@

#include "callback.h"

-#ifdef CONFIG_NFS_V4
static const int nfs_set_port_min = 0;
static const int nfs_set_port_max = 65535;
-#endif
-static struct ctl_table_header *nfs_callback_sysctl_table;
+static struct ctl_table_header *nfs4_callback_sysctl_table;

-static ctl_table nfs_cb_sysctls[] = {
-#ifdef CONFIG_NFS_V4
+static ctl_table nfs4_cb_sysctls[] = {
{
.procname = "nfs_callback_tcpport",
.data = &nfs_callback_set_tcpport,
@@ -39,52 +39,39 @@ static ctl_table nfs_cb_sysctls[] = {
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
-#endif
- {
- .procname = "nfs_mountpoint_timeout",
- .data = &nfs_mountpoint_expiry_timeout,
- .maxlen = sizeof(nfs_mountpoint_expiry_timeout),
- .mode = 0644,
- .proc_handler = proc_dointvec_jiffies,
- },
- {
- .procname = "nfs_congestion_kb",
- .data = &nfs_congestion_kb,
- .maxlen = sizeof(nfs_congestion_kb),
- .mode = 0644,
- .proc_handler = proc_dointvec,
- },
{ }
};

-static ctl_table nfs_cb_sysctl_dir[] = {
+static ctl_table nfs4_cb_sysctl_dir[] = {
{
.procname = "nfs",
.mode = 0555,
- .child = nfs_cb_sysctls,
+ .child = nfs4_cb_sysctls,
},
{ }
};

-static ctl_table nfs_cb_sysctl_root[] = {
+static ctl_table nfs4_cb_sysctl_root[] = {
{
.procname = "fs",
.mode = 0555,
- .child = nfs_cb_sysctl_dir,
+ .child = nfs4_cb_sysctl_dir,
},
{ }
};

-int nfs_register_sysctl(void)
+int nfs4_register_sysctl(void)
{
- nfs_callback_sysctl_table = register_sysctl_table(nfs_cb_sysctl_root);
- if (nfs_callback_sysctl_table == NULL)
+ nfs4_callback_sysctl_table = register_sysctl_table(nfs4_cb_sysctl_root);
+ if (nfs4_callback_sysctl_table == NULL)
return -ENOMEM;
return 0;
}

-void nfs_unregister_sysctl(void)
+void nfs4_unregister_sysctl(void)
{
- unregister_sysctl_table(nfs_callback_sysctl_table);
- nfs_callback_sysctl_table = NULL;
+ unregister_sysctl_table(nfs4_callback_sysctl_table);
+ nfs4_callback_sysctl_table = NULL;
}
+
+#endif /* CONFIG_SYSCTL */
diff --git a/fs/nfs/sysctl.c b/fs/nfs/sysctl.c
index ad4d2e7..6b3f253 100644
--- a/fs/nfs/sysctl.c
+++ b/fs/nfs/sysctl.c
@@ -9,37 +9,11 @@
#include <linux/fs.h>
#include <linux/sysctl.h>
#include <linux/module.h>
-#include <linux/nfs4.h>
-#include <linux/nfs_idmap.h>
#include <linux/nfs_fs.h>

-#include "callback.h"
-
-#ifdef CONFIG_NFS_V4
-static const int nfs_set_port_min = 0;
-static const int nfs_set_port_max = 65535;
-#endif
static struct ctl_table_header *nfs_callback_sysctl_table;

static ctl_table nfs_cb_sysctls[] = {
-#ifdef CONFIG_NFS_V4
- {
- .procname = "nfs_callback_tcpport",
- .data = &nfs_callback_set_tcpport,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec_minmax,
- .extra1 = (int *)&nfs_set_port_min,
- .extra2 = (int *)&nfs_set_port_max,
- },
- {
- .procname = "idmap_cache_timeout",
- .data = &nfs_idmap_cache_timeout,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec_jiffies,
- },
-#endif
{
.procname = "nfs_mountpoint_timeout",
.data = &nfs_mountpoint_expiry_timeout,
--
1.7.9.4


2012-03-21 15:21:14

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 04/23] NFS: Convert v2 into a module

From: Bryan Schumaker <[email protected]>

The module (nfs2.ko) will be created in the same directory as nfs.ko and
will be automatically loaded the first time you try to mount over NFS v2.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Kconfig | 2 +-
fs/nfs/Makefile | 4 +++-
fs/nfs/client.c | 5 ++---
fs/nfs/dir.c | 4 ++++
fs/nfs/file.c | 3 +++
fs/nfs/inode.c | 8 ++++++++
fs/nfs/nfs.h | 1 -
fs/nfs/nfs2super.c | 14 +++++++++++++-
8 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index 4995b24..9663563 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -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
help
This option enables support for version 2 of the NFS protocol
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index c6e7844..bc2ba86 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -9,7 +9,6 @@ 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) += nfs2super.o proc.o nfs2xdr.o
nfs-$(CONFIG_NFS_V3) += nfs3super.o nfs3proc.o nfs3xdr.o
nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
@@ -20,6 +19,9 @@ nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o
nfs-$(CONFIG_SYSCTL) += sysctl.o
nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o

+obj-$(CONFIG_NFS_V2) += nfs2.o
+nfs2-y += nfs2super.o proc.o nfs2xdr.o
+
obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o
nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o

diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 0fafedd..a7e892e 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -200,9 +200,6 @@ EXPORT_SYMBOL_GPL(unregister_nfs_version);
*/
void __init nfs_register_versions(void)
{
-#ifdef CONFIG_NFS_V2
- init_nfs_v2();
-#endif
#ifdef CONFIG_NFS_V3
init_nfs_v3();
#endif
@@ -909,6 +906,7 @@ error:
dprintk("<-- nfs_init_client() = xerror %d\n", error);
return error;
}
+EXPORT_SYMBOL_GPL(nfs_init_client);

/*
* Create a version 2 or 3 client
@@ -2211,6 +2209,7 @@ int nfs_stat_to_errno(enum nfs_stat status)
dprintk("NFS: Unrecognized nfs status value: %u\n", status);
return nfs_errtbl[i].errno;
}
+EXPORT_SYMBOL_GPL(nfs_stat_to_errno);

module_param(nfs4_disable_idmapping, bool, 0644);
MODULE_PARM_DESC(nfs4_disable_idmapping,
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 9952170..08b3d15 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -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>
@@ -83,6 +84,7 @@ const struct inode_operations nfs_dir_inode_operations = {
.getattr = nfs_getattr,
.setattr = nfs_setattr,
};
+EXPORT_SYMBOL_GPL(nfs_dir_inode_operations);

const struct address_space_operations nfs_dir_aops = {
.freepage = nfs_readdir_clear_array,
@@ -1262,6 +1264,7 @@ const struct dentry_operations nfs_dentry_operations = {
.d_automount = nfs_d_automount,
.d_release = nfs_d_release,
};
+EXPORT_SYMBOL_GPL(nfs_dentry_operations);

static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
{
@@ -1670,6 +1673,7 @@ out_error:
dput(parent);
return error;
}
+EXPORT_SYMBOL_GPL(nfs_instantiate);

/*
* Following a failed create operation, we drop the dentry rather
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 4fdaaa6..94af2db 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -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>
@@ -47,6 +48,7 @@ const struct inode_operations nfs_file_inode_operations = {
.getattr = nfs_getattr,
.setattr = nfs_setattr,
};
+EXPORT_SYMBOL_GPL(nfs_file_inode_operations);

#ifdef CONFIG_NFS_V3
const struct inode_operations nfs3_file_inode_operations = {
@@ -867,6 +869,7 @@ const struct file_operations nfs_file_operations = {
.check_flags = nfs_check_flags,
.setlease = nfs_setlease,
};
+EXPORT_SYMBOL_GPL(nfs_file_operations);

#ifdef CONFIG_NFS_V4
static int
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 02a1c43..d6db30b 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -195,6 +195,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.
@@ -507,6 +508,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)
{
@@ -633,6 +635,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)
{
@@ -1027,6 +1030,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 +1041,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 +1052,7 @@ struct nfs_fh *nfs_alloc_fhandle(void)
fh->size = 0;
return fh;
}
+EXPORT_SYMBOL_GPL(nfs_alloc_fhandle);

#ifdef NFS_DEBUG
/*
@@ -1167,6 +1173,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)
{
@@ -1254,6 +1261,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
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 05f6849..a92514c 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -22,7 +22,6 @@ struct nfs_subversion {
};

void nfs_register_versions(void);
-int init_nfs_v2(void);
int init_nfs_v3(void);
int init_nfs_v4(void);

diff --git a/fs/nfs/nfs2super.c b/fs/nfs/nfs2super.c
index 12fa906..773342d 100644
--- a/fs/nfs/nfs2super.c
+++ b/fs/nfs/nfs2super.c
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2012 Netapp, Inc. All rights reserved.
+ *
+ * Initialize the NFS v2 module
*/
#include <linux/module.h>
#include <linux/nfs_fs.h>
@@ -24,8 +26,18 @@ static struct nfs_subversion nfs_v2 = {
.unreference = nfs2_unreference,
};

-int __init init_nfs_v2(void)
+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);
--
1.7.9.4


2012-03-21 15:21:20

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 14/23] NFS: Move nfs4_set_client() and support code to nfs4client.c

From: Bryan Schumaker <[email protected]>

This chunk of code is only used by NFS v4, so it can safely move to a
v4-only file that won't even be compiled if v4 isn't selected. This
also helps to avoid future modpost errors when v4 is turned into a
module.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 349 ++-------------------------------------------------
fs/nfs/nfs.h | 12 +-
fs/nfs/nfs4client.c | 337 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 356 insertions(+), 342 deletions(-)

diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 41c687e..38efcf4 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -82,11 +82,6 @@ retry:
#endif /* CONFIG_NFS_V4 */

/*
- * Turn off NFSv4 uid/gid mapping when using AUTH_SYS
- */
-static bool nfs4_disable_idmapping = true;
-
-/*
* RPC cruft for NFS
*/
static struct rpc_version *nfs_version[5] = {
@@ -227,11 +222,6 @@ static void pnfs_init_server(struct nfs_server *server)
rpc_init_wait_queue(&server->roc_rpcwaitq, "pNFS ROC");
}

-static void nfs4_destroy_server(struct nfs_server *server)
-{
- nfs4_purge_state_owners(server);
-}
-
/* 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)
{
@@ -494,7 +484,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
* Look up a client by IP address and protocol version
* - creates a new record if one doesn't yet exist
*/
-static struct nfs_client *
+struct nfs_client *
nfs_get_client(const struct nfs_client_initdata *cl_init,
const struct rpc_timeout *timeparms,
const char *ip_addr,
@@ -597,8 +587,8 @@ int nfs4_check_client_ready(struct nfs_client *clp)
/*
* Initialise the timeout values for a connection
*/
-static void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
- unsigned int timeo, unsigned int retrans)
+void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
+ unsigned int timeo, unsigned int retrans)
{
to->to_initval = timeo * HZ / 10;
to->to_retries = retrans;
@@ -728,7 +718,7 @@ static int nfs_start_lockd(struct nfs_server *server)
/*
* Create a general RPC client
*/
-static int nfs_init_server_rpcclient(struct nfs_server *server,
+int nfs_init_server_rpcclient(struct nfs_server *server,
const struct rpc_timeout *timeo,
rpc_authflavor_t pseudoflavour)
{
@@ -944,7 +934,7 @@ static void nfs_server_set_fsinfo(struct nfs_server *server,
/*
* Probe filesystem information, including the FSID on v2/v3
*/
-static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs_fattr *fattr)
+int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs_fattr *fattr)
{
struct nfs_fsinfo fsinfo;
struct nfs_client *clp = server->nfs_client;
@@ -988,7 +978,7 @@ out_error:
/*
* Copy useful information when duplicating a server record
*/
-static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source)
+void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source)
{
target->flags = source->flags;
target->rsize = source->rsize;
@@ -1001,7 +991,7 @@ static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_serve
target->options = source->options;
}

-static void nfs_server_insert_lists(struct nfs_server *server)
+void nfs_server_insert_lists(struct nfs_server *server)
{
struct nfs_client *clp = server->nfs_client;
struct nfs_net *nn = net_generic(clp->net, nfs_net_id);
@@ -1035,7 +1025,7 @@ static void nfs_server_remove_lists(struct nfs_server *server)
/*
* Allocate and initialise a server record
*/
-static struct nfs_server *nfs_alloc_server(void)
+struct nfs_server *nfs_alloc_server(void)
{
struct nfs_server *server;

@@ -1360,325 +1350,6 @@ error:
return error;
}

-/*
- * Set up an NFS4 client
- */
-static int nfs4_set_client(struct nfs_server *server,
- const char *hostname,
- const struct sockaddr *addr,
- const size_t addrlen,
- const char *ip_addr,
- rpc_authflavor_t authflavour,
- int proto, const struct rpc_timeout *timeparms,
- u32 minorversion, struct net *net)
-{
- struct nfs_client_initdata cl_init = {
- .hostname = hostname,
- .addr = addr,
- .addrlen = addrlen,
- .rpc_ops = &nfs_v4_clientops,
- .proto = proto,
- .minorversion = minorversion,
- .net = net,
- };
- struct nfs_client *clp;
- int error;
-
- dprintk("--> nfs4_set_client()\n");
-
- /* Allocate or find a client reference we can use */
- clp = nfs_get_client(&cl_init, timeparms, ip_addr, authflavour,
- server->flags & NFS_MOUNT_NORESVPORT);
- if (IS_ERR(clp)) {
- error = PTR_ERR(clp);
- goto error;
- }
-
- /*
- * Query for the lease time on clientid setup or renewal
- *
- * Note that this will be set on nfs_clients that were created
- * only for the DS role and did not set this bit, but now will
- * serve a dual role.
- */
- set_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state);
-
- server->nfs_client = clp;
- dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp);
- return 0;
-error:
- dprintk("<-- nfs4_set_client() = xerror %d\n", error);
- return error;
-}
-
-/*
- * Set up a pNFS Data Server client.
- *
- * Return any existing nfs_client that matches server address,port,version
- * and minorversion.
- *
- * For a new nfs_client, use a soft mount (default), a low retrans and a
- * low timeout interval so that if a connection is lost, we retry through
- * the MDS.
- */
-struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
- const struct sockaddr *ds_addr,
- int ds_addrlen, int ds_proto)
-{
- struct nfs_client_initdata cl_init = {
- .addr = ds_addr,
- .addrlen = ds_addrlen,
- .rpc_ops = &nfs_v4_clientops,
- .proto = ds_proto,
- .minorversion = mds_clp->cl_minorversion,
- .net = mds_clp->net,
- };
- struct rpc_timeout ds_timeout = {
- .to_initval = 15 * HZ,
- .to_maxval = 15 * HZ,
- .to_retries = 1,
- .to_exponential = 1,
- };
- struct nfs_client *clp;
-
- /*
- * Set an authflavor equual to the MDS value. Use the MDS nfs_client
- * cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS
- * (section 13.1 RFC 5661).
- */
- clp = nfs_get_client(&cl_init, &ds_timeout, mds_clp->cl_ipaddr,
- mds_clp->cl_rpcclient->cl_auth->au_flavor, 0);
-
- dprintk("<-- %s %p\n", __func__, clp);
- return clp;
-}
-EXPORT_SYMBOL_GPL(nfs4_set_ds_client);
-
-/*
- * Session has been established, and the client marked ready.
- * Set the mount rsize and wsize with negotiated fore channel
- * attributes which will be bound checked in nfs_server_set_fsinfo.
- */
-static void nfs4_session_set_rwsize(struct nfs_server *server)
-{
-#ifdef CONFIG_NFS_V4_1
- struct nfs4_session *sess;
- u32 server_resp_sz;
- u32 server_rqst_sz;
-
- if (!nfs4_has_session(server->nfs_client))
- return;
- sess = server->nfs_client->cl_session;
- server_resp_sz = sess->fc_attrs.max_resp_sz - nfs41_maxread_overhead;
- server_rqst_sz = sess->fc_attrs.max_rqst_sz - nfs41_maxwrite_overhead;
-
- if (server->rsize > server_resp_sz)
- server->rsize = server_resp_sz;
- if (server->wsize > server_rqst_sz)
- server->wsize = server_rqst_sz;
-#endif /* CONFIG_NFS_V4_1 */
-}
-
-static int nfs4_server_common_setup(struct nfs_server *server,
- struct nfs_fh *mntfh)
-{
- struct nfs_fattr *fattr;
- int error;
-
- BUG_ON(!server->nfs_client);
- BUG_ON(!server->nfs_client->rpc_ops);
- BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
-
- /* data servers support only a subset of NFSv4.1 */
- if (is_ds_only_client(server->nfs_client))
- return -EPROTONOSUPPORT;
-
- fattr = nfs_alloc_fattr();
- if (fattr == NULL)
- return -ENOMEM;
-
- /* We must ensure the session is initialised first */
- error = nfs4_init_session(server);
- if (error < 0)
- goto out;
-
- /* Probe the root fh to retrieve its FSID and filehandle */
- error = nfs4_get_rootfh(server, mntfh);
- if (error < 0)
- goto out;
-
- dprintk("Server FSID: %llx:%llx\n",
- (unsigned long long) server->fsid.major,
- (unsigned long long) server->fsid.minor);
- dprintk("Mount FH: %d\n", mntfh->size);
-
- nfs4_session_set_rwsize(server);
-
- error = nfs_probe_fsinfo(server, mntfh, fattr);
- if (error < 0)
- goto out;
-
- if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
- server->namelen = NFS4_MAXNAMLEN;
-
- nfs_server_insert_lists(server);
- server->mount_time = jiffies;
- server->destroy = nfs4_destroy_server;
-out:
- nfs_free_fattr(fattr);
- return error;
-}
-
-/*
- * Create a version 4 volume record
- */
-static int nfs4_init_server(struct nfs_server *server,
- const struct nfs_parsed_mount_data *data)
-{
- struct rpc_timeout timeparms;
- int error;
-
- dprintk("--> nfs4_init_server()\n");
-
- nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
- data->timeo, data->retrans);
-
- /* Initialise the client representation from the mount data */
- server->flags = data->flags;
- server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR|NFS_CAP_POSIX_LOCK;
- if (!(data->flags & NFS_MOUNT_NORDIRPLUS))
- server->caps |= NFS_CAP_READDIRPLUS;
- server->options = data->options;
-
- /* Get a client record */
- error = nfs4_set_client(server,
- data->nfs_server.hostname,
- (const struct sockaddr *)&data->nfs_server.address,
- data->nfs_server.addrlen,
- data->client_address,
- data->auth_flavors[0],
- data->nfs_server.protocol,
- &timeparms,
- data->minorversion,
- data->net);
- if (error < 0)
- goto error;
-
- /*
- * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower
- * authentication.
- */
- if (nfs4_disable_idmapping && data->auth_flavors[0] == RPC_AUTH_UNIX)
- server->caps |= NFS_CAP_UIDGID_NOMAP;
-
- if (data->rsize)
- server->rsize = nfs_block_size(data->rsize, NULL);
- if (data->wsize)
- server->wsize = nfs_block_size(data->wsize, NULL);
-
- server->acregmin = data->acregmin * HZ;
- server->acregmax = data->acregmax * HZ;
- server->acdirmin = data->acdirmin * HZ;
- server->acdirmax = data->acdirmax * HZ;
-
- server->port = data->nfs_server.port;
-
- error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]);
-
-error:
- /* Done */
- dprintk("<-- nfs4_init_server() = %d\n", error);
- return error;
-}
-
-/*
- * Create a version 4 volume record
- * - keyed on server and FSID
- */
-struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
- struct nfs_fh *mntfh)
-{
- struct nfs_server *server;
- int error;
-
- dprintk("--> nfs4_create_server()\n");
-
- server = nfs_alloc_server();
- if (!server)
- return ERR_PTR(-ENOMEM);
-
- /* set up the general RPC client */
- error = nfs4_init_server(server, data);
- if (error < 0)
- goto error;
-
- error = nfs4_server_common_setup(server, mntfh);
- if (error < 0)
- goto error;
-
- dprintk("<-- nfs4_create_server() = %p\n", server);
- return server;
-
-error:
- nfs_free_server(server);
- dprintk("<-- nfs4_create_server() = error %d\n", error);
- return ERR_PTR(error);
-}
-
-/*
- * Create an NFS4 referral server record
- */
-struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
- struct nfs_fh *mntfh)
-{
- struct nfs_client *parent_client;
- struct nfs_server *server, *parent_server;
- int error;
-
- dprintk("--> nfs4_create_referral_server()\n");
-
- server = nfs_alloc_server();
- if (!server)
- return ERR_PTR(-ENOMEM);
-
- parent_server = NFS_SB(data->sb);
- parent_client = parent_server->nfs_client;
-
- /* Initialise the client representation from the parent server */
- nfs_server_copy_userdata(server, parent_server);
- server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR;
-
- /* Get a client representation.
- * Note: NFSv4 always uses TCP, */
- error = nfs4_set_client(server, data->hostname,
- data->addr,
- data->addrlen,
- parent_client->cl_ipaddr,
- data->authflavor,
- rpc_protocol(parent_server->client),
- parent_server->client->cl_timeout,
- parent_client->cl_mvops->minor_version,
- parent_client->net);
- if (error < 0)
- goto error;
-
- error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout, data->authflavor);
- if (error < 0)
- goto error;
-
- error = nfs4_server_common_setup(server, mntfh);
- if (error < 0)
- goto error;
-
- dprintk("<-- nfs_create_referral_server() = %p\n", server);
- return server;
-
-error:
- nfs_free_server(server);
- dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
- return ERR_PTR(error);
-}
-
#endif /* CONFIG_NFS_V4 */

/*
@@ -2094,7 +1765,3 @@ int nfs_stat_to_errno(enum nfs_stat status)
return nfs_errtbl[i].errno;
}
EXPORT_SYMBOL_GPL(nfs_stat_to_errno);
-
-module_param(nfs4_disable_idmapping, bool, 0644);
-MODULE_PARM_DESC(nfs4_disable_idmapping,
- "Turn off NFSv4 idmapping when using 'sec=sys'");
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 6036141..3ed4b32 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -56,9 +56,19 @@ void unregister_nfs_version(struct nfs_subversion *);

/* Exported in client.c */
int nfs_get_cb_ident_idr(struct nfs_client *, int);
-struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *, struct nfs_fh *);
struct nfs_client *_nfs_alloc_client(const struct nfs_client_initdata *);
void _nfs_free_client(struct nfs_client *);
+struct nfs_client *nfs_get_client(const struct nfs_client_initdata *,
+ const struct rpc_timeout *, const char *,
+ rpc_authflavor_t, int);
+void nfs_init_timeout_values(struct rpc_timeout *, int, unsigned int, unsigned int);
+int nfs_init_server_rpcclient(struct nfs_server *, const struct rpc_timeout *,
+ rpc_authflavor_t);
+int nfs_probe_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *);
+void nfs_server_copy_userdata(struct nfs_server *, struct nfs_server *);
+void nfs_server_insert_lists(struct nfs_server *);
+struct nfs_server *nfs_alloc_server(void);
+struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *, struct nfs_fh *);

/* Exported in dir.c */
struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *);
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index c555748..230d25e 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -3,6 +3,8 @@
* Written by David Howells ([email protected])
*/

+#include <linux/module.h>
+#include <linux/nfs_mount.h>
#include <linux/nfs4.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_fs_sb.h>
@@ -11,6 +13,13 @@
#include "callback.h"
#include "pnfs.h"

+#define NFSDBG_FACILITY NFSDBG_CLIENT
+
+/*
+ * Turn off NFSv4 uid/gid mapping when using AUTH_SYS
+ */
+static bool nfs4_disable_idmapping = true;
+
#ifdef CONFIG_NFS_V4_1
static void nfs4_shutdown_session(struct nfs_client *clp)
{
@@ -25,6 +34,11 @@ static void nfs4_shutdown_session(struct nfs_client *clp)
}
#endif /* CONFIG_NFS_V4_1 */

+static void nfs4_destroy_server(struct nfs_server *server)
+{
+ nfs4_purge_state_owners(server);
+}
+
/*
* Destroy the NFS4 callback service
*/
@@ -78,3 +92,326 @@ error_cleanup:
kfree(clp);
return ERR_PTR(err);
}
+
+/*
+ * Set up an NFS4 client
+ */
+static int nfs4_set_client(struct nfs_server *server,
+ const char *hostname,
+ const struct sockaddr *addr,
+ const size_t addrlen,
+ const char *ip_addr,
+ rpc_authflavor_t authflavour,
+ int proto, const struct rpc_timeout *timeparms,
+ u32 minorversion, struct net *net)
+{
+ struct nfs_client_initdata cl_init = {
+ .hostname = hostname,
+ .addr = addr,
+ .addrlen = addrlen,
+ .rpc_ops = &nfs_v4_clientops,
+ .proto = proto,
+ .minorversion = minorversion,
+ .net = net,
+ };
+ struct nfs_client *clp;
+ int error;
+
+ dprintk("--> nfs4_set_client()\n");
+
+ /* Allocate or find a client reference we can use */
+ clp = nfs_get_client(&cl_init, timeparms, ip_addr, authflavour,
+ server->flags & NFS_MOUNT_NORESVPORT);
+ if (IS_ERR(clp)) {
+ error = PTR_ERR(clp);
+ goto error;
+ }
+
+ /*
+ * Query for the lease time on clientid setup or renewal
+ *
+ * Note that this will be set on nfs_clients that were created
+ * only for the DS role and did not set this bit, but now will
+ * serve a dual role.
+ */
+ set_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state);
+
+ server->nfs_client = clp;
+ dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp);
+ return 0;
+error:
+ dprintk("<-- nfs4_set_client() = xerror %d\n", error);
+ return error;
+}
+
+/*
+ * Set up a pNFS Data Server client.
+ *
+ * Return any existing nfs_client that matches server address,port,version
+ * and minorversion.
+ *
+ * For a new nfs_client, use a soft mount (default), a low retrans and a
+ * low timeout interval so that if a connection is lost, we retry through
+ * the MDS.
+ */
+struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
+ const struct sockaddr *ds_addr,
+ int ds_addrlen, int ds_proto)
+{
+ struct nfs_client_initdata cl_init = {
+ .addr = ds_addr,
+ .addrlen = ds_addrlen,
+ .rpc_ops = &nfs_v4_clientops,
+ .proto = ds_proto,
+ .minorversion = mds_clp->cl_minorversion,
+ .net = mds_clp->net,
+ };
+ struct rpc_timeout ds_timeout = {
+ .to_initval = 15 * HZ,
+ .to_maxval = 15 * HZ,
+ .to_retries = 1,
+ .to_exponential = 1,
+ };
+ struct nfs_client *clp;
+
+ /*
+ * Set an authflavor equual to the MDS value. Use the MDS nfs_client
+ * cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS
+ * (section 13.1 RFC 5661).
+ */
+ clp = nfs_get_client(&cl_init, &ds_timeout, mds_clp->cl_ipaddr,
+ mds_clp->cl_rpcclient->cl_auth->au_flavor, 0);
+
+ dprintk("<-- %s %p\n", __func__, clp);
+ return clp;
+}
+EXPORT_SYMBOL_GPL(nfs4_set_ds_client);
+
+/*
+ * Session has been established, and the client marked ready.
+ * Set the mount rsize and wsize with negotiated fore channel
+ * attributes which will be bound checked in nfs_server_set_fsinfo.
+ */
+static void nfs4_session_set_rwsize(struct nfs_server *server)
+{
+#ifdef CONFIG_NFS_V4_1
+ struct nfs4_session *sess;
+ u32 server_resp_sz;
+ u32 server_rqst_sz;
+
+ if (!nfs4_has_session(server->nfs_client))
+ return;
+ sess = server->nfs_client->cl_session;
+ server_resp_sz = sess->fc_attrs.max_resp_sz - nfs41_maxread_overhead;
+ server_rqst_sz = sess->fc_attrs.max_rqst_sz - nfs41_maxwrite_overhead;
+
+ if (server->rsize > server_resp_sz)
+ server->rsize = server_resp_sz;
+ if (server->wsize > server_rqst_sz)
+ server->wsize = server_rqst_sz;
+#endif /* CONFIG_NFS_V4_1 */
+}
+
+static int nfs4_server_common_setup(struct nfs_server *server,
+ struct nfs_fh *mntfh)
+{
+ struct nfs_fattr *fattr;
+ int error;
+
+ BUG_ON(!server->nfs_client);
+ BUG_ON(!server->nfs_client->rpc_ops);
+ BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
+
+ /* data servers support only a subset of NFSv4.1 */
+ if (is_ds_only_client(server->nfs_client))
+ return -EPROTONOSUPPORT;
+
+ fattr = nfs_alloc_fattr();
+ if (fattr == NULL)
+ return -ENOMEM;
+
+ /* We must ensure the session is initialised first */
+ error = nfs4_init_session(server);
+ if (error < 0)
+ goto out;
+
+ /* Probe the root fh to retrieve its FSID and filehandle */
+ error = nfs4_get_rootfh(server, mntfh);
+ if (error < 0)
+ goto out;
+
+ dprintk("Server FSID: %llx:%llx\n",
+ (unsigned long long) server->fsid.major,
+ (unsigned long long) server->fsid.minor);
+ dprintk("Mount FH: %d\n", mntfh->size);
+
+ nfs4_session_set_rwsize(server);
+
+ error = nfs_probe_fsinfo(server, mntfh, fattr);
+ if (error < 0)
+ goto out;
+
+ if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
+ server->namelen = NFS4_MAXNAMLEN;
+
+ nfs_server_insert_lists(server);
+ server->mount_time = jiffies;
+ server->destroy = nfs4_destroy_server;
+out:
+ nfs_free_fattr(fattr);
+ return error;
+}
+
+/*
+ * Create a version 4 volume record
+ */
+static int nfs4_init_server(struct nfs_server *server,
+ const struct nfs_parsed_mount_data *data)
+{
+ struct rpc_timeout timeparms;
+ int error;
+
+ dprintk("--> nfs4_init_server()\n");
+
+ nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
+ data->timeo, data->retrans);
+
+ /* Initialise the client representation from the mount data */
+ server->flags = data->flags;
+ server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR|NFS_CAP_POSIX_LOCK;
+ if (!(data->flags & NFS_MOUNT_NORDIRPLUS))
+ server->caps |= NFS_CAP_READDIRPLUS;
+ server->options = data->options;
+
+ /* Get a client record */
+ error = nfs4_set_client(server,
+ data->nfs_server.hostname,
+ (const struct sockaddr *)&data->nfs_server.address,
+ data->nfs_server.addrlen,
+ data->client_address,
+ data->auth_flavors[0],
+ data->nfs_server.protocol,
+ &timeparms,
+ data->minorversion,
+ data->net);
+ if (error < 0)
+ goto error;
+
+ /*
+ * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower
+ * authentication.
+ */
+ if (nfs4_disable_idmapping && data->auth_flavors[0] == RPC_AUTH_UNIX)
+ server->caps |= NFS_CAP_UIDGID_NOMAP;
+
+ if (data->rsize)
+ server->rsize = nfs_block_size(data->rsize, NULL);
+ if (data->wsize)
+ server->wsize = nfs_block_size(data->wsize, NULL);
+
+ server->acregmin = data->acregmin * HZ;
+ server->acregmax = data->acregmax * HZ;
+ server->acdirmin = data->acdirmin * HZ;
+ server->acdirmax = data->acdirmax * HZ;
+
+ server->port = data->nfs_server.port;
+
+ error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]);
+
+error:
+ /* Done */
+ dprintk("<-- nfs4_init_server() = %d\n", error);
+ return error;
+}
+
+/*
+ * Create a version 4 volume record
+ * - keyed on server and FSID
+ */
+struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
+ struct nfs_fh *mntfh)
+{
+ struct nfs_server *server;
+ int error;
+
+ dprintk("--> nfs4_create_server()\n");
+
+ server = nfs_alloc_server();
+ if (!server)
+ return ERR_PTR(-ENOMEM);
+
+ /* set up the general RPC client */
+ error = nfs4_init_server(server, data);
+ if (error < 0)
+ goto error;
+
+ error = nfs4_server_common_setup(server, mntfh);
+ if (error < 0)
+ goto error;
+
+ dprintk("<-- nfs4_create_server() = %p\n", server);
+ return server;
+
+error:
+ nfs_free_server(server);
+ dprintk("<-- nfs4_create_server() = error %d\n", error);
+ return ERR_PTR(error);
+}
+
+/*
+ * Create an NFS4 referral server record
+ */
+struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
+ struct nfs_fh *mntfh)
+{
+ struct nfs_client *parent_client;
+ struct nfs_server *server, *parent_server;
+ int error;
+
+ dprintk("--> nfs4_create_referral_server()\n");
+
+ server = nfs_alloc_server();
+ if (!server)
+ return ERR_PTR(-ENOMEM);
+
+ parent_server = NFS_SB(data->sb);
+ parent_client = parent_server->nfs_client;
+
+ /* Initialise the client representation from the parent server */
+ nfs_server_copy_userdata(server, parent_server);
+ server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR;
+
+ /* Get a client representation.
+ * Note: NFSv4 always uses TCP, */
+ error = nfs4_set_client(server, data->hostname,
+ data->addr,
+ data->addrlen,
+ parent_client->cl_ipaddr,
+ data->authflavor,
+ rpc_protocol(parent_server->client),
+ parent_server->client->cl_timeout,
+ parent_client->cl_mvops->minor_version,
+ parent_client->net);
+ if (error < 0)
+ goto error;
+
+ error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout, data->authflavor);
+ if (error < 0)
+ goto error;
+
+ error = nfs4_server_common_setup(server, mntfh);
+ if (error < 0)
+ goto error;
+
+ dprintk("<-- nfs_create_referral_server() = %p\n", server);
+ return server;
+
+error:
+ nfs_free_server(server);
+ dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
+ return ERR_PTR(error);
+}
+
+module_param(nfs4_disable_idmapping, bool, 0644);
+MODULE_PARM_DESC(nfs4_disable_idmapping,
+ "Turn off NFSv4 idmapping when using 'sec=sys'");
--
1.7.9.4


2012-03-21 16:03:40

by Myklebust, Trond

[permalink] [raw]
Subject: Re: [PATCH v4 03/23] NFS: Add version registering framework

T24gV2VkLCAyMDEyLTAzLTIxIGF0IDExOjIwIC0wNDAwLCBianNjaHVtYUBuZXRhcHAuY29tIHdy
b3RlOg0KPiAgDQo+ICtzdGF0aWMgaW50IGZpbmRfbmZzX3ZlcnNpb24oc3RydWN0IG5mc19zdWJ2
ZXJzaW9uICoqbmZzLCB1bnNpZ25lZCBpbnQgdmVyc2lvbikNCj4gK3sNCj4gKwlzdHJ1Y3QgbmZz
X3N1YnZlcnNpb24gKnRtcDsNCj4gKwlzcGluX2xvY2soJm5mc192ZXJzaW9uX2xvY2spOw0KPiAr
DQo+ICsJbGlzdF9mb3JfZWFjaF9lbnRyeV9zYWZlKCgqbmZzKSwgdG1wLCAmbmZzX3ZlcnNpb25z
LCBsaXN0KSB7DQo+ICsJCWlmICgoKm5mcyktPnZlcnNpb24gPT0gdmVyc2lvbikgew0KPiArCQkJ
c3Bpbl91bmxvY2soJm5mc192ZXJzaW9uX2xvY2spOw0KPiArCQkJcmV0dXJuIDE7DQo+ICsJCX0N
Cj4gKwl9Ow0KPiArDQoNCkJUVzogVGhlIGFib3ZlIGZ1bmN0aW9uIG5lZWRzIHRvIGNhbGwgdHJ5
X21vZHVsZV9nZXQoKSB1bmRlciB0aGUNCm5mc192ZXJzaW9uX2xvY2suIE90aGVyd2lzZSB5b3Ug
d2lsbCBub3QgYmUgZ3VhcmFudGVlZCB0aGF0IHRoZSBtb2R1bGUNCnN0aWxsIGV4aXN0cyBhbmQg
aXMgbGl2ZSB3aGVuIHlvdSB0cnkgdG8gdXNlIHRoZSBwb2ludGVyICcqbmZzJy4NCg0KLS0gDQpU
cm9uZCBNeWtsZWJ1c3QNCkxpbnV4IE5GUyBjbGllbnQgbWFpbnRhaW5lcg0KDQpOZXRBcHANClRy
b25kLk15a2xlYnVzdEBuZXRhcHAuY29tDQp3d3cubmV0YXBwLmNvbQ0KDQo=

2012-03-21 15:21:15

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 06/23] NFS: Create a single nfs_clone_super() function

From: Bryan Schumaker <[email protected]>

v2 and v3 shared a function for this, but v4 implemented something
different. When I looked closer at the v4 implementation, I found it
was basically doing the same thing as v3. Might as well share the code
whenever possible...

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/super.c | 33 +++++++--------------------------
1 file changed, 7 insertions(+), 26 deletions(-)

diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index de9b4f4..16ceae3 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2153,7 +2153,7 @@ static void nfs_fill_super(struct super_block *sb,
}

/*
- * Finish setting up a cloned NFS2/3 superblock
+ * Finish setting up a cloned NFS2/3/4 superblock
*/
static void nfs_clone_super(struct super_block *sb,
const struct super_block *old_sb)
@@ -2163,17 +2163,18 @@ static void nfs_clone_super(struct super_block *sb,
sb->s_blocksize_bits = old_sb->s_blocksize_bits;
sb->s_blocksize = old_sb->s_blocksize;
sb->s_maxbytes = old_sb->s_maxbytes;
+ sb->s_xattr = old_sb->s_xattr;
+ sb->s_op = old_sb->s_op;
+ sb->s_time_gran = 1;

- 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.
*/
sb->s_flags |= MS_POSIXACL;
- sb->s_time_gran = 1;
}

- sb->s_op = old_sb->s_op;
- nfs_initialise_sb(sb);
+ nfs_initialise_sb(sb);
}

static int nfs_compare_mount_options(const struct super_block *s, const struct nfs_server *b, int flags)
@@ -2526,26 +2527,6 @@ error_splat_bdi:
#ifdef CONFIG_NFS_V4

/*
- * Finish setting up a cloned NFS4 superblock
- */
-static void nfs4_clone_super(struct super_block *sb,
- const struct super_block *old_sb)
-{
- sb->s_blocksize_bits = old_sb->s_blocksize_bits;
- sb->s_blocksize = old_sb->s_blocksize;
- sb->s_maxbytes = old_sb->s_maxbytes;
- sb->s_time_gran = 1;
- sb->s_op = old_sb->s_op;
- /*
- * 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 = old_sb->s_xattr;
- nfs_initialise_sb(sb);
-}
-
-/*
* Set up an NFS4 superblock
*/
static void nfs4_fill_super(struct super_block *sb)
@@ -3008,7 +2989,7 @@ nfs4_xdev_mount(struct file_system_type *fs_type, int flags,

if (!s->s_root) {
/* initial superblock/root creation */
- nfs4_clone_super(s, data->sb);
+ nfs_clone_super(s, data->sb);
nfs_fscache_get_super_cookie(s, NULL, data);
}

--
1.7.9.4


2012-03-21 15:21:17

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 11/23] NFS: Move lots of code from super.c

From: Bryan Schumaker <[email protected]>

This patch started as an attempt to move from super.c to nfs4super.c,
but each function was dependant on others so I decided that moving
everything over in one chunk would be easier than creating several
smaller (and probably not bisectable) patches.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/nfs.h | 26 ++-
fs/nfs/nfs4super.c | 580 +++++++++++++++++++++++++++++++++++++++++++++-
fs/nfs/super.c | 644 ++--------------------------------------------------
3 files changed, 625 insertions(+), 625 deletions(-)

diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 1f93181..f298c17 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -27,6 +27,11 @@ struct nfs_subversion {
struct dentry *(*xdev_mount)(int, const char *, struct nfs_clone_mount *);
};

+struct nfs_sb_mountdata {
+ struct nfs_server *server;
+ int mntflags;
+};
+
int init_nfs_v4(void);
void exit_nfs_v4(void);

@@ -57,6 +62,25 @@ struct dentry *_nfs_fs_mount(struct file_system_type *, struct nfs_server *,
struct nfs_parsed_mount_data *);
struct dentry *_nfs_xdev_mount(struct file_system_type *, struct nfs_server *,
int, const char *, void *, int);
-
+struct dentry * nfs_xdev_mount(struct file_system_type *, int, const char *, void *);
+int nfs_statfs(struct dentry *, struct kstatfs *);
+void nfs_umount_begin(struct super_block *);
+struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned);
+void nfs_free_parsed_mount_data(struct nfs_parsed_mount_data *);
+int nfs4_validate_text_mount_data(void *, struct nfs_parsed_mount_data *, const char *);
+int nfs_verify_server_address(struct sockaddr *);
+void nfs_validate_transport_protocol(struct nfs_parsed_mount_data *);
+int nfs_parse_mount_options(char *, struct nfs_parsed_mount_data *);
+int nfs_show_options(struct seq_file *, struct dentry *);
+int nfs_show_devname(struct seq_file *, struct dentry *);
+int nfs_show_path(struct seq_file *, struct dentry *);
+int nfs_show_stats(struct seq_file *, struct dentry *);
+int nfs_remount(struct super_block *, int *, char *);
+inline void nfs_initialise_sb(struct super_block *);
+int nfs_compare_super(struct super_block *, void *);
+int nfs_register(struct nfs_server *);
+void nfs_unregister(struct nfs_server *);
+void nfs_put_super(struct super_block *);
+int nfs_set_super(struct super_block *, void *);

#endif /* __LINUX_INTERNAL_NFS_H */
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 9dc0c37..91b4758 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -3,12 +3,581 @@
*/
#include <linux/module.h>
#include <linux/nfs_fs.h>
+#include <linux/nfs_mount.h>
#include <linux/nfs4_mount.h>
#include <linux/nfs_idmap.h>
#include "internal.h"
+#include "delegation.h"
+#include "fscache.h"
#include "nfs4_fs.h"
#include "nfs.h"

+#define NFSDBG_FACILITY NFSDBG_VFS
+
+struct dentry *nfs4_try_mount(int flags, const char *dev_name,
+ struct nfs_parsed_mount_data *data);
+static struct dentry *nfs4_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *raw_data);
+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_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,
+ int flags, const char *dev_name, void *raw_data);
+static void nfs4_kill_super(struct super_block *sb);
+
+struct file_system_type nfs4_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "nfs4",
+ .mount = nfs4_mount,
+ .kill_sb = nfs4_kill_super,
+ .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+};
+
+static struct file_system_type nfs4_remote_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "nfs4",
+ .mount = nfs4_remote_mount,
+ .kill_sb = nfs4_kill_super,
+ .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 = nfs_xdev_mount,
+ .kill_sb = nfs4_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",
+ .mount = nfs4_remote_referral_mount,
+ .kill_sb = nfs4_kill_super,
+ .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+};
+
+struct file_system_type nfs4_referral_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "nfs4",
+ .mount = nfs4_referral_mount,
+ .kill_sb = nfs4_kill_super,
+ .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+};
+
+static const struct super_operations nfs4_sops = {
+ .alloc_inode = nfs_alloc_inode,
+ .destroy_inode = nfs_destroy_inode,
+ .write_inode = nfs_write_inode,
+ .put_super = nfs_put_super,
+ .statfs = nfs_statfs,
+ .evict_inode = nfs4_evict_inode,
+ .umount_begin = nfs_umount_begin,
+ .show_options = nfs_show_options,
+ .show_devname = nfs_show_devname,
+ .show_path = nfs_show_path,
+ .show_stats = nfs_show_stats,
+ .remount_fs = nfs_remount,
+};
+
+/*
+ * Set up an NFS4 superblock
+ */
+static void nfs4_fill_super(struct super_block *sb)
+{
+ 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);
+}
+
+/*
+ * Get the superblock for the NFS4 root partition
+ */
+static struct dentry *
+nfs4_remote_mount(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *raw_data)
+{
+ struct nfs_parsed_mount_data *data = raw_data;
+ struct super_block *s;
+ struct nfs_server *server;
+ struct nfs_fh *mntfh;
+ struct dentry *mntroot;
+ int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
+ struct nfs_sb_mountdata sb_mntdata = {
+ .mntflags = flags,
+ };
+ int error = -ENOMEM;
+
+ mntfh = nfs_alloc_fhandle();
+ if (data == NULL || mntfh == NULL)
+ goto out;
+
+ /* Get a volume representation */
+ server = nfs4_create_server(data, mntfh);
+ if (IS_ERR(server)) {
+ error = PTR_ERR(server);
+ goto out;
+ }
+ sb_mntdata.server = server;
+
+ if (server->flags & NFS4_MOUNT_UNSHARED)
+ compare_super = NULL;
+
+ /* -o noac implies -o sync */
+ if (server->flags & NFS_MOUNT_NOAC)
+ sb_mntdata.mntflags |= MS_SYNCHRONOUS;
+
+ /* Get a superblock - note that we may end up sharing one that already exists */
+ s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata);
+ if (IS_ERR(s)) {
+ error = PTR_ERR(s);
+ goto out_free;
+ }
+
+ if (s->s_fs_info != server) {
+ nfs_free_server(server);
+ server = NULL;
+ } else {
+ error = nfs_register(server);
+ if (error)
+ goto error_splat_bdi;
+ }
+
+ if (!s->s_root) {
+ /* initial superblock/root creation */
+ nfs4_fill_super(s);
+ nfs_fscache_get_super_cookie(s, data->fscache_uniq, NULL);
+ }
+
+ mntroot = nfs4_get_root(s, mntfh, dev_name);
+ if (IS_ERR(mntroot)) {
+ error = PTR_ERR(mntroot);
+ goto error_splat_super;
+ }
+
+ error = security_sb_set_mnt_opts(s, &data->lsm_opts);
+ if (error)
+ goto error_splat_root;
+
+ s->s_flags |= MS_ACTIVE;
+
+ nfs_free_fhandle(mntfh);
+ return mntroot;
+
+out:
+ nfs_free_fhandle(mntfh);
+ return ERR_PTR(error);
+
+out_free:
+ nfs_free_server(server);
+ goto out;
+
+error_splat_root:
+ dput(mntroot);
+error_splat_super:
+ if (server && !s->s_root)
+ nfs_unregister(server);
+error_splat_bdi:
+ deactivate_locked_super(s);
+ goto out;
+}
+
+static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type,
+ int flags, void *data, const char *hostname)
+{
+ struct vfsmount *root_mnt;
+ char *root_devname;
+ size_t len;
+
+ len = strlen(hostname) + 3;
+ root_devname = kmalloc(len, GFP_KERNEL);
+ if (root_devname == NULL)
+ return ERR_PTR(-ENOMEM);
+ snprintf(root_devname, len, "%s:/", hostname);
+ root_mnt = vfs_kern_mount(fs_type, flags, root_devname, data);
+ kfree(root_devname);
+ return root_mnt;
+}
+
+/*
+ * Validate NFSv4 mount options
+ */
+static int nfs4_validate_mount_data(void *options,
+ struct nfs_parsed_mount_data *args,
+ const char *dev_name)
+{
+ struct sockaddr *sap = (struct sockaddr *)&args->nfs_server.address;
+ struct nfs4_mount_data *data = (struct nfs4_mount_data *)options;
+ char *c;
+
+ if (data == NULL)
+ goto out_no_data;
+
+ switch (data->version) {
+ case 1:
+ if (data->host_addrlen > sizeof(args->nfs_server.address))
+ goto out_no_address;
+ if (data->host_addrlen == 0)
+ goto out_no_address;
+ args->nfs_server.addrlen = data->host_addrlen;
+ if (copy_from_user(sap, data->host_addr, data->host_addrlen))
+ return -EFAULT;
+ if (!nfs_verify_server_address(sap))
+ goto out_no_address;
+
+ if (data->auth_flavourlen) {
+ if (data->auth_flavourlen > 1)
+ goto out_inval_auth;
+ if (copy_from_user(&args->auth_flavors[0],
+ data->auth_flavours,
+ sizeof(args->auth_flavors[0])))
+ return -EFAULT;
+ }
+
+ c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN);
+ if (IS_ERR(c))
+ return PTR_ERR(c);
+ args->nfs_server.hostname = c;
+
+ c = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN);
+ if (IS_ERR(c))
+ return PTR_ERR(c);
+ args->nfs_server.export_path = c;
+ dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", c);
+
+ c = strndup_user(data->client_addr.data, 16);
+ if (IS_ERR(c))
+ return PTR_ERR(c);
+ args->client_address = c;
+
+ /*
+ * Translate to nfs_parsed_mount_data, which nfs4_fill_super
+ * can deal with.
+ */
+
+ args->flags = data->flags & NFS4_MOUNT_FLAGMASK;
+ args->rsize = data->rsize;
+ args->wsize = data->wsize;
+ args->timeo = data->timeo;
+ args->retrans = data->retrans;
+ args->acregmin = data->acregmin;
+ args->acregmax = data->acregmax;
+ args->acdirmin = data->acdirmin;
+ args->acdirmax = data->acdirmax;
+ args->nfs_server.protocol = data->proto;
+ nfs_validate_transport_protocol(args);
+
+ break;
+ default:
+ if (nfs_parse_mount_options((char *)options, args) == 0)
+ return -EINVAL;
+
+ if (!nfs_verify_server_address(sap))
+ return -EINVAL;
+
+ return nfs4_validate_text_mount_data(options, args, dev_name);
+ }
+
+ return 0;
+
+out_no_data:
+ dfprintk(MOUNT, "NFS4: mount program didn't pass any mount data\n");
+ return -EINVAL;
+
+out_inval_auth:
+ dfprintk(MOUNT, "NFS4: Invalid number of RPC auth flavours %d\n",
+ data->auth_flavourlen);
+ return -EINVAL;
+
+out_no_address:
+ dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n");
+ return -EINVAL;
+}
+
+struct nfs_referral_count {
+ struct list_head list;
+ const struct task_struct *task;
+ unsigned int referral_count;
+};
+
+static LIST_HEAD(nfs_referral_count_list);
+static DEFINE_SPINLOCK(nfs_referral_count_list_lock);
+
+static struct nfs_referral_count *nfs_find_referral_count(void)
+{
+ struct nfs_referral_count *p;
+
+ list_for_each_entry(p, &nfs_referral_count_list, list) {
+ if (p->task == current)
+ return p;
+ }
+ return NULL;
+}
+
+#define NFS_MAX_NESTED_REFERRALS 2
+
+static int nfs_referral_loop_protect(void)
+{
+ struct nfs_referral_count *p, *new;
+ int ret = -ENOMEM;
+
+ new = kmalloc(sizeof(*new), GFP_KERNEL);
+ if (!new)
+ goto out;
+ new->task = current;
+ new->referral_count = 1;
+
+ ret = 0;
+ spin_lock(&nfs_referral_count_list_lock);
+ p = nfs_find_referral_count();
+ if (p != NULL) {
+ if (p->referral_count >= NFS_MAX_NESTED_REFERRALS)
+ ret = -ELOOP;
+ else
+ p->referral_count++;
+ } else {
+ list_add(&new->list, &nfs_referral_count_list);
+ new = NULL;
+ }
+ spin_unlock(&nfs_referral_count_list_lock);
+ kfree(new);
+out:
+ return ret;
+}
+
+static void nfs_referral_loop_unprotect(void)
+{
+ struct nfs_referral_count *p;
+
+ spin_lock(&nfs_referral_count_list_lock);
+ p = nfs_find_referral_count();
+ p->referral_count--;
+ if (p->referral_count == 0)
+ list_del(&p->list);
+ else
+ p = NULL;
+ spin_unlock(&nfs_referral_count_list_lock);
+ kfree(p);
+}
+
+
+static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,
+ const char *export_path)
+{
+ struct dentry *dentry;
+ int err;
+
+ if (IS_ERR(root_mnt))
+ return ERR_CAST(root_mnt);
+
+ err = nfs_referral_loop_protect();
+ if (err) {
+ mntput(root_mnt);
+ return ERR_PTR(err);
+ }
+
+ dentry = mount_subtree(root_mnt, export_path);
+ nfs_referral_loop_unprotect();
+
+ return dentry;
+}
+
+struct dentry *nfs4_try_mount(int flags, const char *dev_name,
+ struct nfs_parsed_mount_data *data)
+{
+ char *export_path;
+ struct vfsmount *root_mnt;
+ struct dentry *res;
+
+ dfprintk(MOUNT, "--> nfs4_try_mount()\n");
+
+ export_path = data->nfs_server.export_path;
+ data->nfs_server.export_path = "/";
+ root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, data,
+ data->nfs_server.hostname);
+ data->nfs_server.export_path = export_path;
+
+ res = nfs_follow_remote_path(root_mnt, export_path);
+
+ dfprintk(MOUNT, "<-- nfs4_try_mount() = %ld%s\n",
+ IS_ERR(res) ? PTR_ERR(res) : 0,
+ IS_ERR(res) ? " [error]" : "");
+ return res;
+}
+
+/*
+ * Get the superblock for an NFS4 mountpoint
+ */
+static struct dentry *nfs4_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *raw_data)
+{
+ struct nfs_parsed_mount_data *data;
+ int error = -ENOMEM;
+ struct dentry *res = ERR_PTR(-ENOMEM);
+
+ data = nfs_alloc_parsed_mount_data(4);
+ if (data == NULL)
+ goto out;
+
+ /* Validate the mount data */
+ error = nfs4_validate_mount_data(raw_data, data, dev_name);
+ if (error < 0) {
+ res = ERR_PTR(error);
+ goto out;
+ }
+
+ res = nfs4_try_mount(flags, dev_name, data);
+ if (IS_ERR(res))
+ error = PTR_ERR(res);
+
+out:
+ nfs_free_parsed_mount_data(data);
+ dprintk("<-- nfs4_mount() = %d%s\n", error,
+ error != 0 ? " [error]" : "");
+ return res;
+}
+
+static void nfs4_kill_super(struct super_block *sb)
+{
+ struct nfs_server *server = NFS_SB(sb);
+
+ dprintk("--> %s\n", __func__);
+ nfs_super_return_all_delegations(sb);
+ kill_anon_super(sb);
+ nfs_fscache_release_super_cookie(sb);
+ nfs_free_server(server);
+ dprintk("<-- %s\n", __func__);
+}
+
+static struct dentry *
+nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *raw_data)
+{
+ struct nfs_clone_mount *data = raw_data;
+ struct super_block *s;
+ struct nfs_server *server;
+ struct dentry *mntroot;
+ struct nfs_fh *mntfh;
+ int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
+ struct nfs_sb_mountdata sb_mntdata = {
+ .mntflags = flags,
+ };
+ int error = -ENOMEM;
+
+ dprintk("--> nfs4_referral_get_sb()\n");
+
+ mntfh = nfs_alloc_fhandle();
+ if (mntfh == NULL)
+ goto out_err_nofh;
+
+ /* create a new volume representation */
+ server = nfs4_create_referral_server(data, mntfh);
+ if (IS_ERR(server)) {
+ error = PTR_ERR(server);
+ goto out_err_noserver;
+ }
+ sb_mntdata.server = server;
+
+ if (server->flags & NFS4_MOUNT_UNSHARED)
+ compare_super = NULL;
+
+ /* -o noac implies -o sync */
+ if (server->flags & NFS_MOUNT_NOAC)
+ sb_mntdata.mntflags |= MS_SYNCHRONOUS;
+
+ /* Get a superblock - note that we may end up sharing one that already exists */
+ s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata);
+ if (IS_ERR(s)) {
+ error = PTR_ERR(s);
+ goto out_err_nosb;
+ }
+
+ if (s->s_fs_info != server) {
+ nfs_free_server(server);
+ server = NULL;
+ } else {
+ error = nfs_register(server);
+ if (error)
+ goto error_splat_bdi;
+ }
+
+ if (!s->s_root) {
+ /* initial superblock/root creation */
+ nfs4_fill_super(s);
+ nfs_fscache_get_super_cookie(s, NULL, data);
+ }
+
+ mntroot = nfs4_get_root(s, mntfh, dev_name);
+ if (IS_ERR(mntroot)) {
+ error = PTR_ERR(mntroot);
+ goto error_splat_super;
+ }
+ if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) {
+ dput(mntroot);
+ error = -ESTALE;
+ goto error_splat_super;
+ }
+
+ s->s_flags |= MS_ACTIVE;
+
+ security_sb_clone_mnt_opts(data->sb, s);
+
+ nfs_free_fhandle(mntfh);
+ dprintk("<-- nfs4_referral_get_sb() = 0\n");
+ return mntroot;
+
+out_err_nosb:
+ nfs_free_server(server);
+out_err_noserver:
+ nfs_free_fhandle(mntfh);
+out_err_nofh:
+ dprintk("<-- nfs4_referral_get_sb() = %d [error]\n", error);
+ return ERR_PTR(error);
+
+error_splat_super:
+ if (server && !s->s_root)
+ nfs_unregister(server);
+error_splat_bdi:
+ deactivate_locked_super(s);
+ nfs_free_fhandle(mntfh);
+ dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error);
+ return ERR_PTR(error);
+}
+
+/*
+ * Create an NFS4 server record on referral traversal
+ */
+static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *raw_data)
+{
+ struct nfs_clone_mount *data = raw_data;
+ char *export_path;
+ struct vfsmount *root_mnt;
+ struct dentry *res;
+
+ dprintk("--> nfs4_referral_mount()\n");
+
+ export_path = data->mnt_path;
+ data->mnt_path = "/";
+
+ root_mnt = nfs_do_root_mount(&nfs4_remote_referral_fs_type,
+ flags, data, data->hostname);
+ data->mnt_path = export_path;
+
+ res = nfs_follow_remote_path(root_mnt, export_path);
+ dprintk("<-- nfs4_referral_mount() = %ld%s\n",
+ IS_ERR(res) ? PTR_ERR(res) : 0,
+ IS_ERR(res) ? " [error]" : "");
+ return res;
+}
+
static void nfs4_reference(void)
{
try_module_get(THIS_MODULE);
@@ -56,24 +625,31 @@ int __init init_nfs_v4(void)

err = nfs_idmap_init();
if (err < 0)
- goto out_1;
+ goto out_2;

err = nfs4_register_sysctl();
if (err < 0)
+ goto out_1;
+
+ err = register_filesystem(&nfs4_fs_type);
+ if (err < 0)
goto out_0;

register_nfs_version(&nfs_v4);
return 0;

out_0:
- nfs_idmap_quit();
+ nfs4_unregister_sysctl();
out_1:
+ nfs_idmap_quit();
+out_2:
return err;
}

void __exit exit_nfs_v4(void)
{
unregister_nfs_version(&nfs_v4);
+ unregister_filesystem(&nfs4_fs_type);
nfs4_unregister_sysctl();
nfs_idmap_quit();
}
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 9a9d45d..e2dd324 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -37,12 +37,10 @@
#include <linux/sunrpc/xprtrdma.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_mount.h>
-#include <linux/nfs4_mount.h>
#include <linux/lockd/bind.h>
#include <linux/seq_file.h>
#include <linux/mount.h>
#include <linux/namei.h>
-#include <linux/nfs_idmap.h>
#include <linux/vfs.h>
#include <linux/inet.h>
#include <linux/in6.h>
@@ -58,9 +56,6 @@
#include <asm/system.h>
#include <asm/uaccess.h>

-#include "nfs4_fs.h"
-#include "callback.h"
-#include "delegation.h"
#include "iostat.h"
#include "internal.h"
#include "fscache.h"
@@ -279,19 +274,9 @@ static match_table_t nfs_vers_tokens = {
{ Opt_vers_err, NULL }
};

-static void nfs_umount_begin(struct super_block *);
-static int nfs_statfs(struct dentry *, struct kstatfs *);
-static int nfs_show_options(struct seq_file *, struct dentry *);
-static int nfs_show_devname(struct seq_file *, struct dentry *);
-static int nfs_show_path(struct seq_file *, struct dentry *);
-static int nfs_show_stats(struct seq_file *, struct dentry *);
static struct dentry *nfs_fs_mount(struct file_system_type *,
int, const char *, void *);
-static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *raw_data);
-static void nfs_put_super(struct super_block *);
static void nfs_kill_super(struct super_block *);
-static int nfs_remount(struct super_block *sb, int *flags, char *raw_data);

struct file_system_type nfs_fs_type = {
.owner = THIS_MODULE,
@@ -325,77 +310,6 @@ static const struct super_operations nfs_sops = {
.remount_fs = nfs_remount,
};

-#ifdef CONFIG_NFS_V4
-static int nfs4_validate_text_mount_data(void *options,
- struct nfs_parsed_mount_data *args, const char *dev_name);
-struct dentry *nfs4_try_mount(int flags, const char *dev_name,
- struct nfs_parsed_mount_data *data);
-static struct dentry *nfs4_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *raw_data);
-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_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,
- int flags, const char *dev_name, void *raw_data);
-static void nfs4_kill_super(struct super_block *sb);
-
-struct file_system_type nfs4_fs_type = {
- .owner = THIS_MODULE,
- .name = "nfs4",
- .mount = nfs4_mount,
- .kill_sb = nfs4_kill_super,
- .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
-};
-
-static struct file_system_type nfs4_remote_fs_type = {
- .owner = THIS_MODULE,
- .name = "nfs4",
- .mount = nfs4_remote_mount,
- .kill_sb = nfs4_kill_super,
- .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 = nfs_xdev_mount,
- .kill_sb = nfs4_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",
- .mount = nfs4_remote_referral_mount,
- .kill_sb = nfs4_kill_super,
- .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
-};
-
-struct file_system_type nfs4_referral_fs_type = {
- .owner = THIS_MODULE,
- .name = "nfs4",
- .mount = nfs4_referral_mount,
- .kill_sb = nfs4_kill_super,
- .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
-};
-
-static const struct super_operations nfs4_sops = {
- .alloc_inode = nfs_alloc_inode,
- .destroy_inode = nfs_destroy_inode,
- .write_inode = nfs_write_inode,
- .put_super = nfs_put_super,
- .statfs = nfs_statfs,
- .evict_inode = nfs4_evict_inode,
- .umount_begin = nfs_umount_begin,
- .show_options = nfs_show_options,
- .show_devname = nfs_show_devname,
- .show_path = nfs_show_path,
- .show_stats = nfs_show_stats,
- .remount_fs = nfs_remount,
-};
-#endif
-
static struct shrinker acl_shrinker = {
.shrink = nfs_access_cache_shrinker,
.seeks = DEFAULT_SEEKS,
@@ -415,18 +329,9 @@ int __init register_nfs_fs(void)
ret = nfs_register_sysctl();
if (ret < 0)
goto error_1;
-#ifdef CONFIG_NFS_V4
- ret = register_filesystem(&nfs4_fs_type);
- if (ret < 0)
- goto error_2;
-#endif
register_shrinker(&acl_shrinker);
return 0;

-#ifdef CONFIG_NFS_V4
-error_2:
- nfs_unregister_sysctl();
-#endif
error_1:
unregister_filesystem(&nfs_fs_type);
error_0:
@@ -439,9 +344,6 @@ error_0:
void __exit unregister_nfs_fs(void)
{
unregister_shrinker(&acl_shrinker);
-#ifdef CONFIG_NFS_V4
- unregister_filesystem(&nfs4_fs_type);
-#endif
nfs_unregister_sysctl();
unregister_filesystem(&nfs_fs_type);
}
@@ -465,7 +367,7 @@ void nfs_sb_deactive(struct super_block *sb)
/*
* Deliver file system statistics to userspace
*/
-static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
+int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
struct nfs_server *server = NFS_SB(dentry->d_sb);
unsigned char blockbits;
@@ -748,7 +650,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
/*
* Describe the mount options on this VFS mountpoint
*/
-static int nfs_show_options(struct seq_file *m, struct dentry *root)
+int nfs_show_options(struct seq_file *m, struct dentry *root)
{
struct nfs_server *nfss = NFS_SB(root->d_sb);

@@ -806,7 +708,7 @@ static void show_implementation_id(struct seq_file *m, struct nfs_server *nfss)
}
#endif

-static int nfs_show_devname(struct seq_file *m, struct dentry *root)
+int nfs_show_devname(struct seq_file *m, struct dentry *root)
{
char *page = (char *) __get_free_page(GFP_KERNEL);
char *devname, *dummy;
@@ -822,7 +724,7 @@ static int nfs_show_devname(struct seq_file *m, struct dentry *root)
return err;
}

-static int nfs_show_path(struct seq_file *m, struct dentry *dentry)
+int nfs_show_path(struct seq_file *m, struct dentry *dentry)
{
seq_puts(m, "/");
return 0;
@@ -831,7 +733,7 @@ static int nfs_show_path(struct seq_file *m, struct dentry *dentry)
/*
* Present statistical information for this VFS mountpoint
*/
-static int nfs_show_stats(struct seq_file *m, struct dentry *root)
+int nfs_show_stats(struct seq_file *m, struct dentry *root)
{
int i, cpu;
struct nfs_server *nfss = NFS_SB(root->d_sb);
@@ -924,7 +826,7 @@ static int nfs_show_stats(struct seq_file *m, struct dentry *root)
* Begin unmount by attempting to remove all automounted mountpoints we added
* in response to xdev traversals and referrals
*/
-static void nfs_umount_begin(struct super_block *sb)
+void nfs_umount_begin(struct super_block *sb)
{
struct nfs_server *server;
struct rpc_clnt *rpc;
@@ -939,7 +841,7 @@ static void nfs_umount_begin(struct super_block *sb)
rpc_killall_tasks(rpc);
}

-static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int version)
+struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int version)
{
struct nfs_parsed_mount_data *data;

@@ -962,7 +864,7 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int ve
return data;
}

-static void nfs_free_parsed_mount_data(struct nfs_parsed_mount_data *data)
+void nfs_free_parsed_mount_data(struct nfs_parsed_mount_data *data)
{
if (data) {
kfree(data->client_address);
@@ -981,7 +883,7 @@ static void nfs_free_parsed_mount_data(struct nfs_parsed_mount_data *data)
* Address family must be initialized, and address must not be
* the ANY address for that family.
*/
-static int nfs_verify_server_address(struct sockaddr *addr)
+int nfs_verify_server_address(struct sockaddr *addr)
{
switch (addr->sa_family) {
case AF_INET: {
@@ -1015,7 +917,7 @@ static void nfs_set_port(struct sockaddr *sap, int *port,
* Sanity check the NFS transport protocol.
*
*/
-static void nfs_validate_transport_protocol(struct nfs_parsed_mount_data *mnt)
+void nfs_validate_transport_protocol(struct nfs_parsed_mount_data *mnt)
{
switch (mnt->nfs_server.protocol) {
case XPRT_TRANSPORT_UDP:
@@ -1162,8 +1064,7 @@ static int nfs_get_option_ul(substring_t args[], unsigned long *option)
* skipped as they are encountered. If there were no errors, return 1;
* otherwise return 0 (zero).
*/
-static int nfs_parse_mount_options(char *raw,
- struct nfs_parsed_mount_data *mnt)
+int nfs_parse_mount_options(char *raw, struct nfs_parsed_mount_data *mnt)
{
char *p, *string, *secdata;
int rc, sloppy = 0, invalid_option = 0;
@@ -2042,7 +1943,7 @@ nfs_compare_remount_data(struct nfs_server *nfss,
return 0;
}

-static int
+int
nfs_remount(struct super_block *sb, int *flags, char *raw_data)
{
int error;
@@ -2107,7 +2008,7 @@ out:
/*
* Initialise the common bits of the superblock
*/
-static inline void nfs_initialise_sb(struct super_block *sb)
+inline void nfs_initialise_sb(struct super_block *sb)
{
struct nfs_server *server = NFS_SB(sb);

@@ -2207,12 +2108,7 @@ Ebusy:
return 0;
}

-struct nfs_sb_mountdata {
- struct nfs_server *server;
- int mntflags;
-};
-
-static int nfs_set_super(struct super_block *s, void *data)
+int nfs_set_super(struct super_block *s, void *data)
{
struct nfs_sb_mountdata *sb_mntdata = data;
struct nfs_server *server = sb_mntdata->server;
@@ -2264,7 +2160,7 @@ static int nfs_compare_super_address(struct nfs_server *server1,
return 1;
}

-static int nfs_compare_super(struct super_block *sb, void *data)
+int nfs_compare_super(struct super_block *sb, void *data)
{
struct nfs_sb_mountdata *sb_mntdata = data;
struct nfs_server *server = sb_mntdata->server, *old = NFS_SB(sb);
@@ -2285,7 +2181,7 @@ static int nfs_bdi_register(struct nfs_server *server)
return bdi_register_dev(&server->backing_dev_info, server->s_dev);
}

-static int nfs_register(struct nfs_server *server)
+int nfs_register(struct nfs_server *server)
{
struct nfs_subversion *nfs_mod = get_nfs_server_version(server);
int err = nfs_bdi_register(server);
@@ -2294,7 +2190,7 @@ static int nfs_register(struct nfs_server *server)
return err;
}

-static void nfs_unregister(struct nfs_server *server)
+void nfs_unregister(struct nfs_server *server)
{
struct nfs_subversion *nfs_mod = get_nfs_server_version(server);
bdi_unregister(&server->backing_dev_info);
@@ -2416,7 +2312,7 @@ out:
* Ensure that we unregister the bdi before kill_anon_super
* releases the device name
*/
-static void nfs_put_super(struct super_block *s)
+void nfs_put_super(struct super_block *s)
{
nfs_unregister(NFS_SB(s));
}
@@ -2516,7 +2412,7 @@ error_splat_bdi:
}
EXPORT_SYMBOL_GPL(_nfs_xdev_mount);

-static struct dentry *
+struct dentry *
nfs_xdev_mount(struct file_system_type *fs_type, int flags,
const char *dev_name, void *raw_data)
{
@@ -2527,31 +2423,15 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,

#ifdef CONFIG_NFS_V4

-/*
- * Set up an NFS4 superblock
- */
-static void nfs4_fill_super(struct super_block *sb)
-{
- 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);
-}
-
static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args)
{
args->flags &= ~(NFS_MOUNT_NONLM|NFS_MOUNT_NOACL|NFS_MOUNT_VER3|
NFS_MOUNT_LOCAL_FLOCK|NFS_MOUNT_LOCAL_FCNTL);
}

-static int nfs4_validate_text_mount_data(void *options,
- struct nfs_parsed_mount_data *args,
- const char *dev_name)
+int nfs4_validate_text_mount_data(void *options,
+ struct nfs_parsed_mount_data *args,
+ const char *dev_name)
{
struct sockaddr *sap = (struct sockaddr *)&args->nfs_server.address;

@@ -2580,484 +2460,4 @@ static int nfs4_validate_text_mount_data(void *options,
NFS4_MAXPATHLEN);
}

-/*
- * Validate NFSv4 mount options
- */
-static int nfs4_validate_mount_data(void *options,
- struct nfs_parsed_mount_data *args,
- const char *dev_name)
-{
- struct sockaddr *sap = (struct sockaddr *)&args->nfs_server.address;
- struct nfs4_mount_data *data = (struct nfs4_mount_data *)options;
- char *c;
-
- if (data == NULL)
- goto out_no_data;
-
- switch (data->version) {
- case 1:
- if (data->host_addrlen > sizeof(args->nfs_server.address))
- goto out_no_address;
- if (data->host_addrlen == 0)
- goto out_no_address;
- args->nfs_server.addrlen = data->host_addrlen;
- if (copy_from_user(sap, data->host_addr, data->host_addrlen))
- return -EFAULT;
- if (!nfs_verify_server_address(sap))
- goto out_no_address;
-
- if (data->auth_flavourlen) {
- if (data->auth_flavourlen > 1)
- goto out_inval_auth;
- if (copy_from_user(&args->auth_flavors[0],
- data->auth_flavours,
- sizeof(args->auth_flavors[0])))
- return -EFAULT;
- }
-
- c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN);
- if (IS_ERR(c))
- return PTR_ERR(c);
- args->nfs_server.hostname = c;
-
- c = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN);
- if (IS_ERR(c))
- return PTR_ERR(c);
- args->nfs_server.export_path = c;
- dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", c);
-
- c = strndup_user(data->client_addr.data, 16);
- if (IS_ERR(c))
- return PTR_ERR(c);
- args->client_address = c;
-
- /*
- * Translate to nfs_parsed_mount_data, which nfs4_fill_super
- * can deal with.
- */
-
- args->flags = data->flags & NFS4_MOUNT_FLAGMASK;
- args->rsize = data->rsize;
- args->wsize = data->wsize;
- args->timeo = data->timeo;
- args->retrans = data->retrans;
- args->acregmin = data->acregmin;
- args->acregmax = data->acregmax;
- args->acdirmin = data->acdirmin;
- args->acdirmax = data->acdirmax;
- args->nfs_server.protocol = data->proto;
- nfs_validate_transport_protocol(args);
-
- break;
- default:
- if (nfs_parse_mount_options((char *)options, args) == 0)
- return -EINVAL;
-
- if (!nfs_verify_server_address(sap))
- return -EINVAL;
-
- return nfs4_validate_text_mount_data(options, args, dev_name);
- }
-
- return 0;
-
-out_no_data:
- dfprintk(MOUNT, "NFS4: mount program didn't pass any mount data\n");
- return -EINVAL;
-
-out_inval_auth:
- dfprintk(MOUNT, "NFS4: Invalid number of RPC auth flavours %d\n",
- data->auth_flavourlen);
- return -EINVAL;
-
-out_no_address:
- dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n");
- return -EINVAL;
-}
-
-/*
- * Get the superblock for the NFS4 root partition
- */
-static struct dentry *
-nfs4_remote_mount(struct file_system_type *fs_type, int flags,
- const char *dev_name, void *raw_data)
-{
- struct nfs_parsed_mount_data *data = raw_data;
- struct super_block *s;
- struct nfs_server *server;
- struct nfs_fh *mntfh;
- struct dentry *mntroot;
- int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
- struct nfs_sb_mountdata sb_mntdata = {
- .mntflags = flags,
- };
- int error = -ENOMEM;
-
- mntfh = nfs_alloc_fhandle();
- if (data == NULL || mntfh == NULL)
- goto out;
-
- /* Get a volume representation */
- server = nfs4_create_server(data, mntfh);
- if (IS_ERR(server)) {
- error = PTR_ERR(server);
- goto out;
- }
- sb_mntdata.server = server;
-
- if (server->flags & NFS4_MOUNT_UNSHARED)
- compare_super = NULL;
-
- /* -o noac implies -o sync */
- if (server->flags & NFS_MOUNT_NOAC)
- sb_mntdata.mntflags |= MS_SYNCHRONOUS;
-
- /* Get a superblock - note that we may end up sharing one that already exists */
- s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata);
- if (IS_ERR(s)) {
- error = PTR_ERR(s);
- goto out_free;
- }
-
- if (s->s_fs_info != server) {
- nfs_free_server(server);
- server = NULL;
- } else {
- error = nfs_register(server);
- if (error)
- goto error_splat_bdi;
- }
-
- if (!s->s_root) {
- /* initial superblock/root creation */
- nfs4_fill_super(s);
- nfs_fscache_get_super_cookie(s, data->fscache_uniq, NULL);
- }
-
- mntroot = nfs4_get_root(s, mntfh, dev_name);
- if (IS_ERR(mntroot)) {
- error = PTR_ERR(mntroot);
- goto error_splat_super;
- }
-
- error = security_sb_set_mnt_opts(s, &data->lsm_opts);
- if (error)
- goto error_splat_root;
-
- s->s_flags |= MS_ACTIVE;
-
- nfs_free_fhandle(mntfh);
- return mntroot;
-
-out:
- nfs_free_fhandle(mntfh);
- return ERR_PTR(error);
-
-out_free:
- nfs_free_server(server);
- goto out;
-
-error_splat_root:
- dput(mntroot);
-error_splat_super:
- if (server && !s->s_root)
- nfs_unregister(server);
-error_splat_bdi:
- deactivate_locked_super(s);
- goto out;
-}
-
-static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type,
- int flags, void *data, const char *hostname)
-{
- struct vfsmount *root_mnt;
- char *root_devname;
- size_t len;
-
- len = strlen(hostname) + 3;
- root_devname = kmalloc(len, GFP_KERNEL);
- if (root_devname == NULL)
- return ERR_PTR(-ENOMEM);
- snprintf(root_devname, len, "%s:/", hostname);
- root_mnt = vfs_kern_mount(fs_type, flags, root_devname, data);
- kfree(root_devname);
- return root_mnt;
-}
-
-struct nfs_referral_count {
- struct list_head list;
- const struct task_struct *task;
- unsigned int referral_count;
-};
-
-static LIST_HEAD(nfs_referral_count_list);
-static DEFINE_SPINLOCK(nfs_referral_count_list_lock);
-
-static struct nfs_referral_count *nfs_find_referral_count(void)
-{
- struct nfs_referral_count *p;
-
- list_for_each_entry(p, &nfs_referral_count_list, list) {
- if (p->task == current)
- return p;
- }
- return NULL;
-}
-
-#define NFS_MAX_NESTED_REFERRALS 2
-
-static int nfs_referral_loop_protect(void)
-{
- struct nfs_referral_count *p, *new;
- int ret = -ENOMEM;
-
- new = kmalloc(sizeof(*new), GFP_KERNEL);
- if (!new)
- goto out;
- new->task = current;
- new->referral_count = 1;
-
- ret = 0;
- spin_lock(&nfs_referral_count_list_lock);
- p = nfs_find_referral_count();
- if (p != NULL) {
- if (p->referral_count >= NFS_MAX_NESTED_REFERRALS)
- ret = -ELOOP;
- else
- p->referral_count++;
- } else {
- list_add(&new->list, &nfs_referral_count_list);
- new = NULL;
- }
- spin_unlock(&nfs_referral_count_list_lock);
- kfree(new);
-out:
- return ret;
-}
-
-static void nfs_referral_loop_unprotect(void)
-{
- struct nfs_referral_count *p;
-
- spin_lock(&nfs_referral_count_list_lock);
- p = nfs_find_referral_count();
- p->referral_count--;
- if (p->referral_count == 0)
- list_del(&p->list);
- else
- p = NULL;
- spin_unlock(&nfs_referral_count_list_lock);
- kfree(p);
-}
-
-static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,
- const char *export_path)
-{
- struct dentry *dentry;
- int err;
-
- if (IS_ERR(root_mnt))
- return ERR_CAST(root_mnt);
-
- err = nfs_referral_loop_protect();
- if (err) {
- mntput(root_mnt);
- return ERR_PTR(err);
- }
-
- dentry = mount_subtree(root_mnt, export_path);
- nfs_referral_loop_unprotect();
-
- return dentry;
-}
-
-struct dentry *nfs4_try_mount(int flags, const char *dev_name,
- struct nfs_parsed_mount_data *data)
-{
- char *export_path;
- struct vfsmount *root_mnt;
- struct dentry *res;
-
- dfprintk(MOUNT, "--> nfs4_try_mount()\n");
-
- export_path = data->nfs_server.export_path;
- data->nfs_server.export_path = "/";
- root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, data,
- data->nfs_server.hostname);
- data->nfs_server.export_path = export_path;
-
- res = nfs_follow_remote_path(root_mnt, export_path);
-
- dfprintk(MOUNT, "<-- nfs4_try_mount() = %ld%s\n",
- IS_ERR(res) ? PTR_ERR(res) : 0,
- IS_ERR(res) ? " [error]" : "");
- return res;
-}
-
-/*
- * Get the superblock for an NFS4 mountpoint
- */
-static struct dentry *nfs4_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *raw_data)
-{
- struct nfs_parsed_mount_data *data;
- int error = -ENOMEM;
- struct dentry *res = ERR_PTR(-ENOMEM);
-
- data = nfs_alloc_parsed_mount_data(4);
- if (data == NULL)
- goto out;
-
- /* Validate the mount data */
- error = nfs4_validate_mount_data(raw_data, data, dev_name);
- if (error < 0) {
- res = ERR_PTR(error);
- goto out;
- }
-
- res = nfs4_try_mount(flags, dev_name, data);
- if (IS_ERR(res))
- error = PTR_ERR(res);
-
-out:
- nfs_free_parsed_mount_data(data);
- dprintk("<-- nfs4_mount() = %d%s\n", error,
- error != 0 ? " [error]" : "");
- return res;
-}
-
-static void nfs4_kill_super(struct super_block *sb)
-{
- struct nfs_server *server = NFS_SB(sb);
-
- dprintk("--> %s\n", __func__);
- nfs_super_return_all_delegations(sb);
- kill_anon_super(sb);
- nfs_fscache_release_super_cookie(sb);
- nfs_free_server(server);
- dprintk("<-- %s\n", __func__);
-}
-
-static struct dentry *
-nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
- const char *dev_name, void *raw_data)
-{
- struct nfs_clone_mount *data = raw_data;
- struct super_block *s;
- struct nfs_server *server;
- struct dentry *mntroot;
- struct nfs_fh *mntfh;
- int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
- struct nfs_sb_mountdata sb_mntdata = {
- .mntflags = flags,
- };
- int error = -ENOMEM;
-
- dprintk("--> nfs4_referral_get_sb()\n");
-
- mntfh = nfs_alloc_fhandle();
- if (mntfh == NULL)
- goto out_err_nofh;
-
- /* create a new volume representation */
- server = nfs4_create_referral_server(data, mntfh);
- if (IS_ERR(server)) {
- error = PTR_ERR(server);
- goto out_err_noserver;
- }
- sb_mntdata.server = server;
-
- if (server->flags & NFS4_MOUNT_UNSHARED)
- compare_super = NULL;
-
- /* -o noac implies -o sync */
- if (server->flags & NFS_MOUNT_NOAC)
- sb_mntdata.mntflags |= MS_SYNCHRONOUS;
-
- /* Get a superblock - note that we may end up sharing one that already exists */
- s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata);
- if (IS_ERR(s)) {
- error = PTR_ERR(s);
- goto out_err_nosb;
- }
-
- if (s->s_fs_info != server) {
- nfs_free_server(server);
- server = NULL;
- } else {
- error = nfs_register(server);
- if (error)
- goto error_splat_bdi;
- }
-
- if (!s->s_root) {
- /* initial superblock/root creation */
- nfs4_fill_super(s);
- nfs_fscache_get_super_cookie(s, NULL, data);
- }
-
- mntroot = nfs4_get_root(s, mntfh, dev_name);
- if (IS_ERR(mntroot)) {
- error = PTR_ERR(mntroot);
- goto error_splat_super;
- }
- if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) {
- dput(mntroot);
- error = -ESTALE;
- goto error_splat_super;
- }
-
- s->s_flags |= MS_ACTIVE;
-
- security_sb_clone_mnt_opts(data->sb, s);
-
- nfs_free_fhandle(mntfh);
- dprintk("<-- nfs4_referral_get_sb() = 0\n");
- return mntroot;
-
-out_err_nosb:
- nfs_free_server(server);
-out_err_noserver:
- nfs_free_fhandle(mntfh);
-out_err_nofh:
- dprintk("<-- nfs4_referral_get_sb() = %d [error]\n", error);
- return ERR_PTR(error);
-
-error_splat_super:
- if (server && !s->s_root)
- nfs_unregister(server);
-error_splat_bdi:
- deactivate_locked_super(s);
- nfs_free_fhandle(mntfh);
- dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error);
- return ERR_PTR(error);
-}
-
-/*
- * Create an NFS4 server record on referral traversal
- */
-static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *raw_data)
-{
- struct nfs_clone_mount *data = raw_data;
- char *export_path;
- struct vfsmount *root_mnt;
- struct dentry *res;
-
- dprintk("--> nfs4_referral_mount()\n");
-
- export_path = data->mnt_path;
- data->mnt_path = "/";
-
- root_mnt = nfs_do_root_mount(&nfs4_remote_referral_fs_type,
- flags, data, data->hostname);
- data->mnt_path = export_path;
-
- res = nfs_follow_remote_path(root_mnt, export_path);
- dprintk("<-- nfs4_referral_mount() = %ld%s\n",
- IS_ERR(res) ? PTR_ERR(res) : 0,
- IS_ERR(res) ? " [error]" : "");
- return res;
-}
-
#endif /* CONFIG_NFS_V4 */
--
1.7.9.4


2012-03-21 15:21:16

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 08/23] NFS: Only initialize the ACL client in the v3 case

From: Bryan Schumaker <[email protected]>

v2 and v4 don't use it, so the function can be limited to v3 only.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Makefile | 2 +-
fs/nfs/client.c | 35 +----------------------------
fs/nfs/nfs.h | 3 ++-
fs/nfs/nfs2super.c | 6 ++++-
fs/nfs/nfs3client.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++
fs/nfs/nfs3super.c | 12 ++++++++--
fs/nfs/nfs4super.c | 6 ++++-
fs/nfs/super.c | 12 ++--------
8 files changed, 88 insertions(+), 50 deletions(-)
create mode 100644 fs/nfs/nfs3client.c

diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index bc2ba86..6764e66 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -9,7 +9,7 @@ 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_V3) += nfs3super.o nfs3proc.o nfs3xdr.o
+nfs-$(CONFIG_NFS_V3) += nfs3super.o nfs3client.o 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 delegation.o idmap.o \
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index ee4a154..5db8005 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -810,36 +810,6 @@ static int nfs_start_lockd(struct nfs_server *server)
}

/*
- * Initialise an NFSv3 ACL client connection
- */
-#ifdef CONFIG_NFS_V3_ACL
-static void nfs_init_server_aclclient(struct nfs_server *server)
-{
- if (server->nfs_client->rpc_ops->version != 3)
- goto out_noacl;
- if (server->flags & NFS_MOUNT_NOACL)
- goto out_noacl;
-
- server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3);
- if (IS_ERR(server->client_acl))
- goto out_noacl;
-
- /* No errors! Assume that Sun nfsacls are supported */
- server->caps |= NFS_CAP_ACLS;
- return;
-
-out_noacl:
- server->caps &= ~NFS_CAP_ACLS;
-}
-#else
-static inline void nfs_init_server_aclclient(struct nfs_server *server)
-{
- server->flags &= ~NFS_MOUNT_NOACL;
- server->caps &= ~NFS_CAP_ACLS;
-}
-#endif
-
-/*
* Create a general RPC client
*/
static int nfs_init_server_rpcclient(struct nfs_server *server,
@@ -986,8 +956,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;

@@ -1834,8 +1802,6 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
source->client->cl_auth->au_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);
@@ -1866,6 +1832,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)
{
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index a5e6a63..8ac594b 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -45,7 +45,8 @@ extern struct file_system_type nfs_fs_type;
struct dentry *_nfs_fs_mount(struct file_system_type *, struct nfs_server *,
int, const char *, struct nfs_fh *,
struct nfs_parsed_mount_data *);
-struct dentry *_nfs_xdev_mount(struct file_system_type *, int, const char *, void *, int);
+struct dentry *_nfs_xdev_mount(struct file_system_type *, struct nfs_server *,
+ int, const char *, void *, int);


#endif /* __LINUX_INTERNAL_NFS_H */
diff --git a/fs/nfs/nfs2super.c b/fs/nfs/nfs2super.c
index d1074a9..ddcc4d1 100644
--- a/fs/nfs/nfs2super.c
+++ b/fs/nfs/nfs2super.c
@@ -6,6 +6,7 @@
#include <linux/module.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_mount.h>
+#include "internal.h"
#include "nfs.h"

static void nfs2_reference(void)
@@ -32,7 +33,10 @@ static struct dentry *nfs2_fs_mount(struct file_system_type *fs_type,
static struct dentry *nfs2_xdev_mount(int flags, const char *dev_name,
struct nfs_clone_mount *data)
{
- return _nfs_xdev_mount(&nfs_fs_type, flags, dev_name, data, NFS_MOUNT_UNSHARED);
+ struct nfs_server *server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
+ if (IS_ERR(server))
+ return ERR_CAST(server);
+ return _nfs_xdev_mount(&nfs_fs_type, server, flags, dev_name, data, NFS_MOUNT_UNSHARED);
}

static struct nfs_subversion nfs_v2 = {
diff --git a/fs/nfs/nfs3client.c b/fs/nfs/nfs3client.c
new file mode 100644
index 0000000..c2e6593
--- /dev/null
+++ b/fs/nfs/nfs3client.c
@@ -0,0 +1,62 @@
+/* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells ([email protected])
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/types.h>
+#include <linux/nfs.h>
+#include <linux/nfs_fs.h>
+#include <linux/nfs_mount.h>
+#include "internal.h"
+#include "nfs.h"
+
+/*
+ * Initialise an NFSv3 ACL client connection
+ */
+#ifdef CONFIG_NFS_V3_ACL
+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(const struct nfs_parsed_mount_data *data,
+ struct nfs_fh *mntfh)
+{
+ struct nfs_server *server = nfs_create_server(data, mntfh);
+ /* Create a client RPC handle for the NFS v3 ACL management interface */
+ if (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)
+{
+ struct nfs_server *server = nfs_clone_server(source, fh, fattr);
+ if (server && !IS_ERR(source->client_acl))
+ nfs_init_server_aclclient(server);
+ return server;
+}
diff --git a/fs/nfs/nfs3super.c b/fs/nfs/nfs3super.c
index 7bdd388..5702895 100644
--- a/fs/nfs/nfs3super.c
+++ b/fs/nfs/nfs3super.c
@@ -4,8 +4,13 @@
#include <linux/module.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_mount.h>
+#include "internal.h"
#include "nfs.h"

+/* From nfs3client.c */
+struct nfs_server *nfs3_create_server(const struct nfs_parsed_mount_data *, struct nfs_fh *);
+struct nfs_server *nfs3_clone_server(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *);
+
static void nfs3_reference(void)
{
try_module_get(THIS_MODULE);
@@ -21,7 +26,7 @@ struct dentry *nfs3_fs_mount(struct file_system_type *fs_type,
struct nfs_fh *mntfh,
struct nfs_parsed_mount_data *data)
{
- struct nfs_server *server = nfs_create_server(data, mntfh);
+ struct nfs_server *server = nfs3_create_server(data, mntfh);
if (IS_ERR(server))
return ERR_CAST(server);
return _nfs_fs_mount(fs_type, server, flags, dev_name, mntfh, data);
@@ -30,7 +35,10 @@ struct dentry *nfs3_fs_mount(struct file_system_type *fs_type,
static struct dentry *nfs3_xdev_mount(int flags, const char *dev_name,
struct nfs_clone_mount *data)
{
- return _nfs_xdev_mount(&nfs_fs_type, flags, dev_name, data, NFS_MOUNT_UNSHARED);
+ struct nfs_server *server = nfs3_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
+ if (IS_ERR(server))
+ return ERR_CAST(server);
+ return _nfs_xdev_mount(&nfs_fs_type, server, flags, dev_name, data, NFS_MOUNT_UNSHARED);
}

static struct nfs_subversion nfs_v3 = {
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 8a297c5..f6c8f9f 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -4,6 +4,7 @@
#include <linux/module.h>
#include <linux/nfs_fs.h>
#include <linux/nfs4_mount.h>
+#include "internal.h"
#include "nfs4_fs.h"
#include "nfs.h"

@@ -31,7 +32,10 @@ struct dentry *nfs4_fs_mount(struct file_system_type *fs_type,
struct dentry *nfs4_xdev_mount(int flags, const char *dev_name,
struct nfs_clone_mount *data)
{
- return _nfs_xdev_mount(&nfs4_fs_type, flags, dev_name, data, NFS4_MOUNT_UNSHARED);
+ struct nfs_server *server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
+ if (IS_ERR(server))
+ return ERR_CAST(server);
+ return _nfs_xdev_mount(&nfs4_fs_type, server, flags, dev_name, data, NFS4_MOUNT_UNSHARED);
}

static struct nfs_subversion nfs_v4 = {
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 994a0cc..810b28e 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2437,12 +2437,11 @@ static void nfs_kill_super(struct super_block *s)
* Clone an NFS2/3 server record on xdev traversal (FSID-change)
*/
struct dentry *
-_nfs_xdev_mount(struct file_system_type *fs_type, int flags,
- const char *dev_name, void *raw_data, int unshared_flag)
+_nfs_xdev_mount(struct file_system_type *fs_type, struct nfs_server *server,
+ int flags, const char *dev_name, void *raw_data, int unshared_flag)
{
struct nfs_clone_mount *data = raw_data;
struct super_block *s;
- struct nfs_server *server;
struct dentry *mntroot;
int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
struct nfs_sb_mountdata sb_mntdata = {
@@ -2452,12 +2451,6 @@ _nfs_xdev_mount(struct file_system_type *fs_type, int flags,

dprintk("--> _nfs_xdev_mount()\n");

- /* create a new volume representation */
- server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
- if (IS_ERR(server)) {
- error = PTR_ERR(server);
- goto out_err_noserver;
- }
sb_mntdata.server = server;

if (server->flags & unshared_flag)
@@ -2510,7 +2503,6 @@ _nfs_xdev_mount(struct file_system_type *fs_type, int flags,

out_err_nosb:
nfs_free_server(server);
-out_err_noserver:
dprintk("<-- _nfs_xdev_mount() = %d [error]\n", error);
return ERR_PTR(error);

--
1.7.9.4


2012-03-21 15:21:24

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 20/23] NFS: Create custom init_read() and init_write() functions

From: Bryan Schumaker <[email protected]>

pNFS needs to select read and write functions based on the layout driver
currently in use, so I let each NFS version decide how to best handle
initializing reads and writes. I had to add ifndef guards to internal.h
to avoid multiple-redefinition errors.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/internal.h | 4 ++++
fs/nfs/nfs.h | 3 +++
fs/nfs/nfs2super.c | 2 ++
fs/nfs/nfs3super.c | 2 ++
fs/nfs/nfs4super.c | 2 ++
fs/nfs/pnfs.c | 16 ++++++++--------
fs/nfs/pnfs.h | 13 +++++++------
fs/nfs/read.c | 6 ++++--
fs/nfs/unlink.c | 1 +
fs/nfs/write.c | 5 +++--
10 files changed, 36 insertions(+), 18 deletions(-)

diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index bd335bb..42d0903 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -2,6 +2,9 @@
* NFS internal definitions
*/

+#ifndef FS_NFS_INTERNAL_H
+#define FS_NFS_INTERNAL_H
+
#include "nfs4_fs.h"
#include <linux/mount.h>
#include <linux/security.h>
@@ -463,3 +466,4 @@ unsigned int nfs_page_array_len(unsigned int base, size_t len)
PAGE_SIZE - 1) >> PAGE_SHIFT;
}

+#endif /* FS_NFS_INTERNAL_H */
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index b5771d5..21bc52b 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -9,6 +9,7 @@

#include <linux/fs.h>
#include <linux/sunrpc/sched.h>
+#include <linux/nfs_page.h>
#include <linux/nfs_xdr.h>

struct nfs_parsed_mount_data;
@@ -40,6 +41,8 @@ struct nfs_subversion {
struct vfsmount *(*submount)(struct dentry *, struct nfs_fh *, struct nfs_fattr *, rpc_authflavor_t);
int (*have_delegation)(struct inode *, fmode_t);
int (*return_delegation)(struct inode *);
+ void (*init_read)(struct nfs_pageio_descriptor *, struct inode *);
+ void (*init_write)(struct nfs_pageio_descriptor *, struct inode *, int);
};

struct nfs_sb_mountdata {
diff --git a/fs/nfs/nfs2super.c b/fs/nfs/nfs2super.c
index 697356f..a9a1a0b 100644
--- a/fs/nfs/nfs2super.c
+++ b/fs/nfs/nfs2super.c
@@ -59,6 +59,8 @@ static struct nfs_subversion nfs_v2 = {
.fs_mount = nfs2_fs_mount,
.xdev_mount = nfs2_xdev_mount,
.submount = nfs2_do_submount,
+ .init_read = nfs_pageio_init_read_mds,
+ .init_write = nfs_pageio_init_write_mds,
};

static int __init init_nfs_v2(void)
diff --git a/fs/nfs/nfs3super.c b/fs/nfs/nfs3super.c
index 17dad41..c84ffe3 100644
--- a/fs/nfs/nfs3super.c
+++ b/fs/nfs/nfs3super.c
@@ -90,6 +90,8 @@ static struct nfs_subversion nfs_v3 = {
.fs_mount = nfs3_fs_mount,
.xdev_mount = nfs3_xdev_mount,
.submount = nfs3_do_submount,
+ .init_read = nfs_pageio_init_read_mds,
+ .init_write = nfs_pageio_init_write_mds,
};

static int __init init_nfs_v3(void)
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 2a3974d..6bf44e3 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -656,6 +656,8 @@ static struct nfs_subversion nfs_v4 = {
.fs_mount = nfs4_fs_mount,
.xdev_mount = nfs4_xdev_mount,
.submount = nfs4_do_submount,
+ .init_read = pnfs_pageio_init_read,
+ .init_write = pnfs_pageio_init_write,
};

int __init init_nfs_v4(void)
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index b5d4515..722f235 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1112,28 +1112,28 @@ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *
}
EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_write);

-bool
+void
pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode)
{
struct nfs_server *server = NFS_SERVER(inode);
struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld;

if (ld == NULL)
- return false;
- nfs_pageio_init(pgio, inode, ld->pg_read_ops, server->rsize, 0);
- return true;
+ nfs_pageio_init_read_mds(pgio, inode);
+ else
+ nfs_pageio_init(pgio, inode, ld->pg_read_ops, server->rsize, 0);
}

-bool
+void
pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, int ioflags)
{
struct nfs_server *server = NFS_SERVER(inode);
struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld;

if (ld == NULL)
- return false;
- nfs_pageio_init(pgio, inode, ld->pg_write_ops, server->wsize, ioflags);
- return true;
+ nfs_pageio_init_write_mds(pgio, inode, ioflags);
+ else
+ nfs_pageio_init(pgio, inode, ld->pg_write_ops, server->wsize, ioflags);
}

bool
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 442ebf6..db422b2 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -32,6 +32,7 @@

#include <linux/nfs_fs.h>
#include <linux/nfs_page.h>
+#include "internal.h"

enum {
NFS_LSEG_VALID = 0, /* cleared when lseg is recalled/returned */
@@ -168,8 +169,8 @@ extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp);
void get_layout_hdr(struct pnfs_layout_hdr *lo);
void put_lseg(struct pnfs_layout_segment *lseg);

-bool pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *);
-bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *, int);
+void pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *);
+void pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *, int);

void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, u32);
void unset_pnfs_layoutdriver(struct nfs_server *);
@@ -396,14 +397,14 @@ static inline void unset_pnfs_layoutdriver(struct nfs_server *s)
{
}

-static inline bool pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode)
+static inline void pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode)
{
- return false;
+ nfs_pageio_init_read_mds(pgio, inode);
}

-static inline bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, int ioflags)
+static inline void pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, int ioflags)
{
- return false;
+ nfs_pageio_init_write_mds(pgio, inode, ioflags);
}

static inline int
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index cc1f758..667f32e 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -22,6 +22,7 @@

#include <asm/system.h>
#include "pnfs.h"
+#include "nfs.h"

#include "nfs4_fs.h"
#include "internal.h"
@@ -114,6 +115,7 @@ void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio,
nfs_pageio_init(pgio, inode, &nfs_pageio_read_ops,
NFS_SERVER(inode)->rsize, 0);
}
+EXPORT_SYMBOL_GPL(nfs_pageio_init_read_mds);

void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio)
{
@@ -125,8 +127,8 @@ EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds);
static void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
struct inode *inode)
{
- if (!pnfs_pageio_init_read(pgio, inode))
- nfs_pageio_init_read_mds(pgio, inode);
+ struct nfs_subversion *nfs_mod = get_nfs_server_version(NFS_SERVER(inode));
+ nfs_mod->init_read(pgio, inode);
}

int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 05abd34..8305948 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -15,6 +15,7 @@
#include <linux/wait.h>
#include <linux/namei.h>

+#include "delegation.h"
#include "internal.h"
#include "nfs4_fs.h"
#include "iostat.h"
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 5b28bbe..46fff97 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1101,6 +1101,7 @@ void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio,
nfs_pageio_init(pgio, inode, &nfs_pageio_write_ops,
NFS_SERVER(inode)->wsize, ioflags);
}
+EXPORT_SYMBOL_GPL(nfs_pageio_init_write_mds);

void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio)
{
@@ -1112,8 +1113,8 @@ EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds);
static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
struct inode *inode, int ioflags)
{
- if (!pnfs_pageio_init_write(pgio, inode, ioflags))
- nfs_pageio_init_write_mds(pgio, inode, ioflags);
+ struct nfs_subversion *nfs_mod = get_nfs_server_version(NFS_SERVER(inode));
+ nfs_mod->init_write(pgio, inode, ioflags);
}

/*
--
1.7.9.4


2012-03-21 15:21:28

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v4 23/23] NFS: Convert v4 into a module

From: Bryan Schumaker <[email protected]>

This patch exports all the symbols needed by the v4 module in addition
to creating the module itself.

The module (nfs4.ko) will be created in the same directory as nfs.ko and
will be automatically loaded the first time you try to mount over NFS v4.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Kconfig | 2 +-
fs/nfs/Makefile | 13 +++++++------
fs/nfs/client.c | 16 +++++++++++++++-
fs/nfs/dir.c | 4 ++++
fs/nfs/dns_resolve.c | 3 +++
fs/nfs/file.c | 13 +++++++++++++
fs/nfs/fscache.c | 3 +++
fs/nfs/getroot.c | 1 +
fs/nfs/inode.c | 14 ++++++++------
fs/nfs/namespace.c | 2 ++
fs/nfs/nfs.h | 3 ---
fs/nfs/nfs4super.c | 9 +++++++--
fs/nfs/nfs4sysctl.c | 4 ----
fs/nfs/pagelist.c | 3 +++
fs/nfs/read.c | 2 ++
fs/nfs/super.c | 22 ++++++++++++++++++++++
fs/nfs/write.c | 4 ++++
17 files changed, 95 insertions(+), 23 deletions(-)

diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index 1e11b08..dee5cf1 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -70,7 +70,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
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 85aafee..3f7e686 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -9,12 +9,6 @@ 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_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
- nfs4super.o delegation.o idmap.o \
- callback.o callback_xdr.o callback_proc.o \
- nfs4namespace.o nfs4sysctl.o nfs4client.o \
- nfs4getroot.o nfs4file.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

@@ -25,6 +19,13 @@ 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 \
+ delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \
+ nfs4namespace.o nfs4client.o nfs4getroot.o nfs4file.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

diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 45f3a21..1aa7190 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -76,6 +76,7 @@ retry:
goto retry;
return ret;
}
+EXPORT_SYMBOL_GPL(nfs_get_cb_ident_idr);
#endif /* CONFIG_NFS_V4 */

/*
@@ -555,6 +556,7 @@ found_client:
dprintk("--> nfs_get_client() = %p [share]\n", clp);
return clp;
}
+EXPORT_SYMBOL_GPL(nfs_get_client);

/*
* Mark a server as ready or failed
@@ -564,6 +566,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);

/*
* With sessions, the client is not marked ready until after a
@@ -580,6 +583,7 @@ int nfs4_check_client_ready(struct nfs_client *clp)
return -EPROTONOSUPPORT;
return 0;
}
+EXPORT_SYMBOL_GPL(nfs4_check_client_ready);

/*
* Initialise the timeout values for a connection
@@ -621,6 +625,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
@@ -661,6 +666,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
@@ -747,6 +753,7 @@ int nfs_init_server_rpcclient(struct nfs_server *server,

return 0;
}
+EXPORT_SYMBOL_GPL(nfs_init_server_rpcclient);

/*
* Initialise an NFS2 or NFS3 client
@@ -972,6 +979,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
@@ -988,6 +996,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)
{
@@ -1001,6 +1010,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)
{
@@ -1060,6 +1070,7 @@ struct nfs_server *nfs_alloc_server(void)

return server;
}
+EXPORT_SYMBOL_GPL(nfs_alloc_server);

/*
* Free up a server record
@@ -1090,6 +1101,7 @@ 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
@@ -1178,6 +1190,7 @@ nfs4_find_client_ident(struct net *net, int cb_ident)
spin_unlock(&nn->nfs_client_lock);
return clp;
}
+EXPORT_SYMBOL_GPL(nfs4_find_client_ident);

#if defined(CONFIG_NFS_V4_1)
/*
@@ -1214,7 +1227,7 @@ nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr,
spin_unlock(&nn->nfs_client_lock);
return NULL;
}
-
+EXPORT_SYMBOL_GPL(nfs4_find_client_sessionid);
#else /* CONFIG_NFS_V4_1 */

struct nfs_client *
@@ -1223,6 +1236,7 @@ nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr,
{
return NULL;
}
+EXPORT_SYMBOL_GPL(nfs4_find_client_sessionid);
#endif /* CONFIG_NFS_V4_1 */

#endif /* CONFIG_NFS_V4 */
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 10c7275..f8914c5 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -103,6 +103,7 @@ const struct inode_operations nfs4_dir_inode_operations = {
.listxattr = generic_listxattr,
.removexattr = generic_removexattr,
};
+EXPORT_SYMBOL_GPL(nfs4_dir_inode_operations);

#endif /* CONFIG_NFS_V4 */

@@ -958,6 +959,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.
@@ -1311,6 +1313,7 @@ const struct dentry_operations nfs4_dentry_operations = {
.d_automount = nfs_d_automount,
.d_release = nfs_d_release,
};
+EXPORT_SYMBOL_GPL(nfs4_dentry_operations);

/*
* Use intent information to determine whether we need to substitute
@@ -2276,6 +2279,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)
{
diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c
index b3924b8..eae00d4 100644
--- a/fs/nfs/dns_resolve.c
+++ b/fs/nfs/dns_resolve.c
@@ -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,6 +28,7 @@ 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

@@ -345,6 +347,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)
{
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index d169c2b..81e84ca 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -61,6 +61,7 @@ int nfs_check_flags(int flags)

return 0;
}
+EXPORT_SYMBOL_GPL(nfs_check_flags);

/*
* Open file
@@ -93,6 +94,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
@@ -146,6 +148,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.
@@ -167,6 +170,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,
@@ -191,6 +195,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,
@@ -213,6 +218,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)
@@ -234,6 +240,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.
@@ -272,6 +279,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)
@@ -612,6 +620,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,
@@ -643,6 +652,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)
@@ -803,6 +813,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
@@ -832,6 +843,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
@@ -844,6 +856,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,
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
index ae65c16..4947f88 100644
--- a/fs/nfs/fscache.c
+++ b/fs/nfs/fscache.c
@@ -11,6 +11,7 @@

#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/nfs_fs.h>
@@ -163,6 +164,7 @@ non_unique:
printk(KERN_WARNING "NFS:"
" Cache request denied due to non-unique superblock keys\n");
}
+EXPORT_SYMBOL_GPL(nfs_fscache_get_super_cookie);

/*
* release a per-superblock cookie
@@ -185,6 +187,7 @@ void nfs_fscache_release_super_cookie(struct super_block *sb)
nfss->fscache_key = NULL;
}
}
+EXPORT_SYMBOL_GPL(nfs_fscache_release_super_cookie);

/*
* Initialise the per-inode cache cookie pointer for an NFS inode.
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index f6a14a6..0a77a74 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -65,6 +65,7 @@ int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *inode)
}
return 0;
}
+EXPORT_SYMBOL_GPL(nfs_superblock_set_dummy_root);

/*
* get an NFS2/NFS3 root dentry from the root filehandle
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index e1e0568..04820e4 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -84,6 +84,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
@@ -119,6 +120,7 @@ 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)
{
@@ -422,6 +424,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)

@@ -687,6 +690,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)
{
@@ -713,6 +717,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
@@ -1537,6 +1542,7 @@ struct inode *nfs_alloc_inode(struct super_block *sb)
#endif /* CONFIG_NFS_V4 */
return &nfsi->vfs_inode;
}
+EXPORT_SYMBOL_GPL(nfs_alloc_inode);

static void nfs_i_callback(struct rcu_head *head)
{
@@ -1548,6 +1554,7 @@ 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)
{
@@ -1597,6 +1604,7 @@ static void nfs_destroy_inodecache(void)
}

struct workqueue_struct *nfsiod_workqueue;
+EXPORT_SYMBOL_GPL(nfsiod_workqueue);

/*
* start up the nfsiod workqueue
@@ -1700,9 +1708,6 @@ static int __init init_nfs_fs(void)
#endif
if ((err = register_nfs_fs()) != 0)
goto out;
-#if IS_ENABLED(CONFIG_NFS_V4)
- init_nfs_v4();
-#endif
return 0;
out:
#ifdef CONFIG_PROC_FS
@@ -1733,9 +1738,6 @@ out9:

static void __exit exit_nfs_fs(void)
{
-#if IS_ENABLED(CONFIG_NFS_V4)
- exit_nfs_v4();
-#endif
nfs_destroy_directcache();
nfs_destroy_writepagecache();
nfs_destroy_readpagecache();
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index aa8e6db..d25c8b5 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -120,6 +120,7 @@ Elong_unlock:
Elong:
return ERR_PTR(-ENAMETOOLONG);
}
+EXPORT_SYMBOL_GPL(nfs_path);

#if IS_ENABLED(CONFIG_NFS_V4)
rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
@@ -150,6 +151,7 @@ rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)

return pseudoflavor;
}
+EXPORT_SYMBOL_GPL(nfs_find_best_sec);

static int nfs_negotiate_security(const struct dentry *parent,
const struct dentry *dentry,
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index fe8152f..53bcf99 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -52,9 +52,6 @@ struct nfs_sb_mountdata {
int mntflags;
};

-int init_nfs_v4(void);
-void exit_nfs_v4(void);
-
struct nfs_subversion *get_nfs_version(unsigned int);
struct nfs_subversion *get_nfs_client_version(struct nfs_client *);
struct nfs_subversion *get_nfs_server_version(struct nfs_server *);
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 7b8e79b..6d0415a 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -662,7 +662,7 @@ static struct nfs_subversion nfs_v4 = {
.unset_layoutdriver = unset_pnfs_layoutdriver,
};

-int __init init_nfs_v4(void)
+static int __init init_nfs_v4(void)
{
int err;

@@ -689,10 +689,15 @@ out_2:
return err;
}

-void __exit 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);
diff --git a/fs/nfs/nfs4sysctl.c b/fs/nfs/nfs4sysctl.c
index 07b67bb..6ebdef7 100644
--- a/fs/nfs/nfs4sysctl.c
+++ b/fs/nfs/nfs4sysctl.c
@@ -4,8 +4,6 @@
* Sysctl interface to NFS parameters
*/

-#ifdef CONFIG_SYSCTL
-
#include <linux/types.h>
#include <linux/linkage.h>
#include <linux/ctype.h>
@@ -73,5 +71,3 @@ void nfs4_unregister_sysctl(void)
unregister_sysctl_table(nfs4_callback_sysctl_table);
nfs4_callback_sysctl_table = NULL;
}
-
-#endif /* CONFIG_SYSCTL */
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index d21fcea..0792dcf 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -219,6 +219,7 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
desc->pg_error = 0;
desc->pg_lseg = NULL;
}
+EXPORT_SYMBOL_GPL(nfs_pageio_init);

/**
* nfs_can_coalesce_requests - test two requests for compatibility
@@ -360,6 +361,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
@@ -375,6 +377,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
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 667f32e..d908b23 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -70,6 +70,7 @@ void nfs_readdata_release(struct nfs_read_data *rdata)
put_nfs_open_context(rdata->args.context);
nfs_readdata_free(rdata);
}
+EXPORT_SYMBOL_GPL(nfs_readdata_release);

static
int nfs_return_empty_page(struct page *page)
@@ -369,6 +370,7 @@ int nfs_generic_pagein(struct nfs_pageio_descriptor *desc, struct list_head *hea
return nfs_pagein_multi(desc, head);
return nfs_pagein_one(desc, head);
}
+EXPORT_SYMBOL_GPL(nfs_generic_pagein);

static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
{
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index b214f44..d657b51 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -356,6 +356,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)
{
@@ -364,6 +365,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
@@ -429,6 +431,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
@@ -665,6 +668,7 @@ int nfs_show_options(struct seq_file *m, struct dentry *root)

return 0;
}
+EXPORT_SYMBOL_GPL(nfs_show_options);

#if IS_ENABLED(CONFIG_NFS_V4)
#ifdef CONFIG_NFS_V4_1
@@ -724,12 +728,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
@@ -822,6 +828,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
@@ -841,6 +848,7 @@ void nfs_umount_begin(struct super_block *sb)
if (!IS_ERR(rpc))
rpc_killall_tasks(rpc);
}
+EXPORT_SYMBOL_GPL(nfs_umount_begin);

struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int version)
{
@@ -864,6 +872,7 @@ struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int version)
}
return data;
}
+EXPORT_SYMBOL_GPL(nfs_alloc_parsed_mount_data);

void nfs_free_parsed_mount_data(struct nfs_parsed_mount_data *data)
{
@@ -877,6 +886,7 @@ void nfs_free_parsed_mount_data(struct nfs_parsed_mount_data *data)
kfree(data);
}
}
+EXPORT_SYMBOL_GPL(nfs_free_parsed_mount_data);

/*
* Sanity-check a server address provided by the mount command.
@@ -900,6 +910,7 @@ int nfs_verify_server_address(struct sockaddr *addr)
dfprintk(MOUNT, "NFS: Invalid IP address specified\n");
return 0;
}
+EXPORT_SYMBOL_GPL(nfs_verify_server_address);

/*
* Select between a default port value and a user-specified port value.
@@ -929,6 +940,7 @@ void nfs_validate_transport_protocol(struct nfs_parsed_mount_data *mnt)
mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP;
}
}
+EXPORT_SYMBOL_GPL(nfs_validate_transport_protocol);

/*
* For text based NFSv2/v3 mounts, the mount protocol transport default
@@ -1526,6 +1538,7 @@ out_security_failure:
printk(KERN_INFO "NFS: security options invalid: %d\n", rc);
return 0;
}
+EXPORT_SYMBOL_GPL(nfs_parse_mount_options);

/*
* Match the requested auth flavors with the list returned by
@@ -2005,6 +2018,7 @@ out:
kfree(data);
return error;
}
+EXPORT_SYMBOL_GPL(nfs_remount);

/*
* Initialise the common bits of the superblock
@@ -2027,6 +2041,7 @@ inline void nfs_initialise_sb(struct super_block *sb)

nfs_super_set_maxbytes(sb, server->maxfilesize);
}
+EXPORT_SYMBOL_GPL(nfs_initialise_sb);

/*
* Finish setting up an NFS2/3 superblock
@@ -2123,6 +2138,7 @@ int nfs_set_super(struct super_block *s, void *data)
server->s_dev = s->s_dev;
return ret;
}
+EXPORT_SYMBOL_GPL(nfs_set_super);

static int nfs_compare_super_address(struct nfs_server *server1,
struct nfs_server *server2)
@@ -2176,6 +2192,7 @@ int nfs_compare_super(struct super_block *sb, void *data)
return 0;
return nfs_compare_mount_options(sb, server, mntflags);
}
+EXPORT_SYMBOL_GPL(nfs_compare_super);

static int nfs_bdi_register(struct nfs_server *server)
{
@@ -2190,6 +2207,7 @@ int nfs_register(struct nfs_server *server)
nfs_mod->reference();
return err;
}
+EXPORT_SYMBOL_GPL(nfs_register);

void nfs_unregister(struct nfs_server *server)
{
@@ -2197,6 +2215,7 @@ void nfs_unregister(struct nfs_server *server)
bdi_unregister(&server->backing_dev_info);
nfs_mod->unreference();
}
+EXPORT_SYMBOL_GPL(nfs_unregister);

struct dentry *_nfs_fs_mount(struct file_system_type *fs_type,
struct nfs_server *server,
@@ -2317,6 +2336,7 @@ void nfs_put_super(struct super_block *s)
{
nfs_unregister(NFS_SB(s));
}
+EXPORT_SYMBOL_GPL(nfs_put_super);

/*
* Destroy an NFS2/3 superblock
@@ -2421,6 +2441,7 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,
struct nfs_subversion *nfs_mod = get_nfs_server_version(NFS_SB(data->sb));
return nfs_mod->xdev_mount(flags, dev_name, data);
}
+EXPORT_SYMBOL_GPL(nfs_xdev_mount);

#if IS_ENABLED(CONFIG_NFS_V4)

@@ -2460,5 +2481,6 @@ int nfs4_validate_text_mount_data(void *options,
&args->nfs_server.export_path,
NFS4_MAXPATHLEN);
}
+EXPORT_SYMBOL_GPL(nfs4_validate_text_mount_data);

#endif /* CONFIG_NFS_V4 */
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index d8e9ef7..9e7cd89 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -102,6 +102,7 @@ void nfs_writedata_release(struct nfs_write_data *wdata)
put_nfs_open_context(wdata->args.context);
nfs_writedata_free(wdata);
}
+EXPORT_SYMBOL_GPL(nfs_writedata_release);

static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error)
{
@@ -1077,6 +1078,7 @@ int nfs_generic_flush(struct nfs_pageio_descriptor *desc, struct list_head *head
return nfs_flush_multi(desc, head);
return nfs_flush_one(desc, head);
}
+EXPORT_SYMBOL_GPL(nfs_generic_flush);

static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
{
@@ -1623,6 +1625,7 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
{
return nfs_commit_unstable_pages(inode, wbc);
}
+EXPORT_SYMBOL_GPL(nfs_write_inode);

/*
* flush the inode to disk.
@@ -1638,6 +1641,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)
{
--
1.7.9.4