All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 00/21] NFS: Create NFS Modules
@ 2012-02-10 22:01 bjschuma
  2012-02-10 22:01 ` [RFC 02/21] NFS: Make v2 configurable bjschuma
                   ` (19 more replies)
  0 siblings, 20 replies; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:01 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

This patch series turns NFS v2, v3 and v4 into loadable kernel modules that
need to be loaded 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.

This time around, I tried to move as little code as possible while still
getting everything to compile as their own module.  I still had to move a
large chunk of v4 specific code from super.c, but most other files should be
(mostly) untouched.  Rather than creating new subdirectories, I instead kept
everything in fs/nfs/, significantly cutting down on the number of patches
to modularize everything.

These patches are about a week out-of-date with Trond's nfs-for-next tree,
so I expect to spend some time addressing comments and updating them so they
apply nicely.  I have also found some bugs that I'll fix up in the next
version as well.

Patch Map
---------
- Patch 1 does basic preparations
- Patches 2 - 4 make NFS v2 an optional kernel module
- Patches 5 - 9 make NFS v3 an optional kernel module
- Patches 10 - 20 make NFS v4 an optional kernel module
- Patch 21 exports functions from nfs4.ko to nfs.ko to fix modpost errors

Known bugs
----------
- Depmod detects a dependency loop when you try to install
- #include errors when NFS v4 isn't enabled
- I don't yet use request_module()

Comments and suggestions are appreciated.  Thanks!

- Bryan

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [RFC 02/21] NFS: Make v2 configurable
  2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
@ 2012-02-10 22:01 ` bjschuma
  2012-02-10 22:01 ` [RFC 03/21] NFS: Add version registering framework bjschuma
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:01 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

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 <bjschuma@netapp.com>
---
 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 dbcd821..5419166 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 872521e..02a33d8 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
@@ -834,7 +836,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,
 	};
@@ -844,10 +846,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


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 03/21] NFS: Add version registering framework
  2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
  2012-02-10 22:01 ` [RFC 02/21] NFS: Make v2 configurable bjschuma
@ 2012-02-10 22:01 ` bjschuma
  2012-02-10 22:01 ` [RFC 04/21] NFS: Convert v2 into a module bjschuma
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:01 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

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 <bjschuma@netapp.com>
---
 fs/lockd/clnt4xdr.c         |    2 +-
 fs/lockd/clntxdr.c          |    6 +-
 fs/lockd/mon.c              |    4 +-
 fs/nfs/Makefile             |    6 +-
 fs/nfs/client.c             |  108 +++++++++++++++++++++++++++++++++---------
 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, 277 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 c196030..ff247f4 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -534,13 +534,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 02a33d8..59bf964 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -49,10 +49,13 @@
 #include "internal.h"
 #include "fscache.h"
 #include "pnfs.h"
+#include "nfs.h"
 
 #define NFSDBG_FACILITY		NFSDBG_CLIENT
 
 DEFINE_SPINLOCK(nfs_client_lock);
+static DEFINE_SPINLOCK(nfs_version_lock);
+static LIST_HEAD(nfs_versions);
 LIST_HEAD(nfs_client_list);
 static LIST_HEAD(nfs_volume_list);
 static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
@@ -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,78 @@ struct nfs_client_initdata {
 	struct net *net;
 };
 
+struct nfs_subversion *get_nfs_version(unsigned int version)
+{
+	struct nfs_subversion *nfs;
+
+	spin_lock(&nfs_version_lock);
+
+	list_for_each_entry(nfs, &nfs_versions, list) {
+		if (nfs->version == version) {
+			/* Keep track of the most recently used version */
+			list_move(&nfs->list, &nfs_versions);
+			goto out;
+		}
+	};
+
+	nfs = ERR_PTR(-EPROTONOSUPPORT);
+
+out:
+	spin_unlock(&nfs_version_lock);
+	return nfs;
+}
+
+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);
+
+	INIT_LIST_HEAD(&nfs->list);
+	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
  *
@@ -842,21 +910,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 d2c760e..e30d6d3 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -51,6 +51,7 @@
 #include "fscache.h"
 #include "dns_resolve.h"
 #include "pnfs.h"
+#include "nfs.h"
 #include "netns.h"
 
 #define NFSDBG_FACILITY		NFSDBG_VFS
@@ -1629,6 +1630,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 b37ca34..4d147a3 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 ca288d1..c091f73 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -7114,7 +7114,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 8e210b2..c5a2085 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -64,6 +64,7 @@
 #include "internal.h"
 #include "fscache.h"
 #include "pnfs.h"
+#include "nfs.h"
 
 #define NFSDBG_FACILITY		NFSDBG_VFS
 
@@ -2220,6 +2221,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)
 {
@@ -2232,6 +2249,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);
@@ -2246,6 +2264,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);
@@ -2279,7 +2303,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;
@@ -2316,7 +2340,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;
@@ -2328,9 +2352,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));
 }
 
 /*
@@ -2390,7 +2412,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;
 	}
@@ -2428,7 +2450,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);
@@ -2659,7 +2681,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;
 	}
@@ -2697,7 +2719,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;
@@ -2919,7 +2941,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;
 	}
@@ -2956,7 +2978,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);
@@ -3010,7 +3032,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;
 	}
@@ -3050,7 +3072,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 144419a..9eaa8f7 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1274,11 +1274,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 a4c62e9..0c0ee9e 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -73,7 +73,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 b1f08bd..bd3954f 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -1075,25 +1075,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


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 04/21] NFS: Convert v2 into a module
  2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
  2012-02-10 22:01 ` [RFC 02/21] NFS: Make v2 configurable bjschuma
  2012-02-10 22:01 ` [RFC 03/21] NFS: Add version registering framework bjschuma
@ 2012-02-10 22:01 ` bjschuma
  2012-02-10 22:01 ` [RFC 05/21] NFS: Break up the nfs_fs_mount function bjschuma
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:01 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

The module will be created in the same subdirectory as nfs.ko.  You need
to run `modprobe nfs2` before you can use it.

Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
---
 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       |    3 ++-
 fs/nfs/nfs2super.c |   14 +++++++++++++-
 8 files changed, 36 insertions(+), 7 deletions(-)

diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index 5419166..b28e56f 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 59bf964..4312a51 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -197,9 +197,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
@@ -893,6 +890,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
@@ -2137,6 +2135,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 bb132a8..0a2bf0e 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 e30d6d3..773dfb9 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -194,6 +194,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.
@@ -505,6 +506,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)
 {
@@ -631,6 +633,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)
 {
@@ -1025,6 +1028,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)
 {
@@ -1035,6 +1039,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)
 {
@@ -1045,6 +1050,7 @@ struct nfs_fh *nfs_alloc_fhandle(void)
 		fh->size = 0;
 	return fh;
 }
+EXPORT_SYMBOL_GPL(nfs_alloc_fhandle);
 
 /**
  * nfs_inode_attrs_need_update - check if the inode attributes need updating
@@ -1104,6 +1110,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)
 {
@@ -1191,6 +1198,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..4e4802e 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -9,6 +9,8 @@
 
 #include <linux/fs.h>
 #include <linux/sunrpc/sched.h>
+#include <linux/nfs_fs.h>
+#include <linux/nfs4.h>
 #include <linux/nfs_xdr.h>
 
 struct nfs_subversion {
@@ -22,7 +24,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


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 05/21] NFS: Break up the nfs_fs_mount function
  2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
                   ` (2 preceding siblings ...)
  2012-02-10 22:01 ` [RFC 04/21] NFS: Convert v2 into a module bjschuma
@ 2012-02-10 22:01 ` bjschuma
  2012-02-10 22:01 ` [RFC 06/21] NFS: Create a single nfs_clone_super() function bjschuma
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:01 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

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 <bjschuma@netapp.com>
---
 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 4312a51..67a6187 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1263,6 +1263,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 4e4802e..dc7d047 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -13,6 +13,8 @@
 #include <linux/nfs4.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 */
@@ -21,6 +23,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);
@@ -33,4 +37,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 b133b50..b888151 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 c5a2085..c1e8994 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -310,7 +310,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);
@@ -2237,52 +2237,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)
@@ -2327,8 +2295,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:
@@ -2345,6 +2311,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
@@ -2829,7 +2831,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


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 06/21] NFS: Create a single nfs_clone_super() function
  2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
                   ` (3 preceding siblings ...)
  2012-02-10 22:01 ` [RFC 05/21] NFS: Break up the nfs_fs_mount function bjschuma
@ 2012-02-10 22:01 ` bjschuma
  2012-02-10 22:01 ` [RFC 07/21] NFS: Version specific xdev mounting bjschuma
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:01 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

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 <bjschuma@netapp.com>
---
 fs/nfs/super.c |   33 +++++++--------------------------
 1 files changed, 7 insertions(+), 26 deletions(-)

diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index c1e8994..ea1d932 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2089,7 +2089,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)
@@ -2099,17 +2099,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)
@@ -2462,26 +2463,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)
@@ -2950,7 +2931,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


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 07/21] NFS: Version specific xdev mounting
  2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
                   ` (4 preceding siblings ...)
  2012-02-10 22:01 ` [RFC 06/21] NFS: Create a single nfs_clone_super() function bjschuma
@ 2012-02-10 22:01 ` bjschuma
  2012-02-10 22:01 ` [RFC 08/21] NFS: Only initialize the ACL client in the v3 case bjschuma
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:01 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

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 <bjschuma@netapp.com>
---
 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 dc7d047..a813d00 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -14,6 +14,7 @@
 #include <linux/nfs_xdr.h>
 
 struct nfs_parsed_mount_data;
+struct nfs_clone_mount;
 
 struct nfs_subversion {
 	unsigned int version;		/* Protocol number */
@@ -25,6 +26,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);
@@ -41,9 +43,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 b888151..449b943 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 ea1d932..e6c62b5 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -276,13 +276,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,
@@ -316,15 +317,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,
@@ -343,7 +342,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,
 };
@@ -2373,9 +2372,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;
@@ -2387,7 +2386,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);
@@ -2397,7 +2396,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 */
@@ -2405,7 +2404,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;
@@ -2442,13 +2441,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:
@@ -2456,9 +2455,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
 
@@ -2879,95 +2888,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


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 08/21] NFS: Only initialize the ACL client in the v3 case
  2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
                   ` (5 preceding siblings ...)
  2012-02-10 22:01 ` [RFC 07/21] NFS: Version specific xdev mounting bjschuma
@ 2012-02-10 22:01 ` bjschuma
  2012-02-10 22:01 ` [RFC 09/21] NFS: Convert v3 into a module bjschuma
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:01 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

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

Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
---
 fs/nfs/Makefile     |    2 +-
 fs/nfs/client.c     |   35 +----------------------------
 fs/nfs/nfs.h        |    3 +-
 fs/nfs/nfs2super.c  |    6 ++++-
 fs/nfs/nfs3client.c |   61 +++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/nfs/nfs3super.c  |   12 ++++++++-
 fs/nfs/nfs4super.c  |    6 ++++-
 fs/nfs/super.c      |   12 +--------
 8 files changed, 87 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 67a6187..ca3a408 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -794,36 +794,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,
@@ -970,8 +940,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;
 
@@ -1794,8 +1762,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);
@@ -1826,6 +1792,7 @@ out_free_server:
 	dprintk("<-- nfs_clone_server() = error %d\n", error);
 	return ERR_PTR(error);
 }
+EXPORT_SYMBOL_GPL(nfs_clone_server);
 
 #ifdef CONFIG_PROC_FS
 static struct proc_dir_entry *proc_fs_nfs;
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index a813d00..921e8c8 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -47,7 +47,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..f23fc46
--- /dev/null
+++ b/fs/nfs/nfs3client.c
@@ -0,0 +1,61 @@
+/* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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_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 e6c62b5..ec5287d 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2373,12 +2373,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 = {
@@ -2388,12 +2387,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)
@@ -2446,7 +2439,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


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 09/21] NFS: Convert v3 into a module
  2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
                   ` (6 preceding siblings ...)
  2012-02-10 22:01 ` [RFC 08/21] NFS: Only initialize the ACL client in the v3 case bjschuma
@ 2012-02-10 22:01 ` bjschuma
  2012-02-10 22:01 ` [RFC 10/21] NFS: Initialize NFS v4 from nfs4super.c bjschuma
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:01 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

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 will be created in the same directory as nfs.ko.  You need to
run `modprobe nfs3` before you can use it.

Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
---
 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     |   39 ++++++++++++++++++++++++++++
 fs/nfs/super.c         |    6 ++--
 fs/nfs/write.c         |    8 +++---
 include/linux/nfs_fs.h |    6 ++--
 13 files changed, 107 insertions(+), 89 deletions(-)
 create mode 100644 fs/nfs/dangling.txt

diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index b28e56f..57c4b19 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..938db05 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-y += 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 ca3a408..75fe112 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;
@@ -197,9 +182,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 0a2bf0e..07ed31d 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 1940f1a..185e177 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -460,7 +460,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 773dfb9..a78d701 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -187,6 +187,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)
 {
@@ -448,6 +449,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
@@ -545,6 +547,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)
 {
@@ -851,6 +854,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)
 {
@@ -1147,6 +1151,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 921e8c8..dccbcfc 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -30,7 +30,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);
@@ -42,6 +41,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 f23fc46..f246cbd 100644
--- a/fs/nfs/nfs3client.c
+++ b/fs/nfs/nfs3client.c
@@ -12,10 +12,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..474840f 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,
@@ -57,3 +86,13 @@ 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 ec5287d..88bbebe 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -68,7 +68,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
@@ -1910,7 +1910,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 */
@@ -1930,7 +1930,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 0b1831d..b8111cb 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -431,7 +431,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)
 /*
  * Add a request to the inode's commit list.
  */
@@ -516,7 +516,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)
 {
@@ -1238,7 +1238,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
@@ -1297,7 +1297,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 8c29950..766ea02 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -406,7 +406,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;
@@ -464,7 +464,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;
@@ -524,7 +524,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


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 10/21] NFS: Initialize NFS v4 from nfs4super.c
  2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
                   ` (7 preceding siblings ...)
  2012-02-10 22:01 ` [RFC 09/21] NFS: Convert v3 into a module bjschuma
@ 2012-02-10 22:01 ` bjschuma
  2012-02-10 22:01 ` [RFC 11/21] NFS: Move lots of code from super.c bjschuma
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:01 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

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 <bjschuma@netapp.com>
---
 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} |   42 ++++++++++--------------------------
 fs/nfs/sysctl.c                   |   28 ------------------------
 8 files changed, 52 insertions(+), 80 deletions(-)
 copy fs/nfs/{sysctl.c => nfs4sysctl.c} (53%)

diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 938db05..92ebf2f 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -14,7 +14,7 @@ nfs-$(CONFIG_NFS_V4)	+= nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
 			   callback.o callback_xdr.o callback_proc.o \
 			   nfs4namespace.o
 nfs-$(CONFIG_NFS_V4_1)	+= pnfs.o pnfs_dev.o
-nfs-$(CONFIG_SYSCTL) += sysctl.o
+nfs-$(CONFIG_SYSCTL) += sysctl.o nfs4sysctl.o
 nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
 
 obj-$(CONFIG_NFS_V2) += nfs2.o
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 75fe112..a954a12 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -176,18 +176,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 a78d701..da01c56 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1594,10 +1594,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;
@@ -1643,7 +1639,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
@@ -1669,13 +1667,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();
@@ -1684,7 +1683,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 dccbcfc..cf49c63 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -29,8 +29,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 449b943..1147640 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -345,6 +345,15 @@ extern void nfs_free_seqid(struct nfs_seqid *seqid);
 
 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 53%
copy from fs/nfs/sysctl.c
copy to fs/nfs/nfs4sysctl.c
index 978aaeb..b19d29e 100644
--- a/fs/nfs/sysctl.c
+++ b/fs/nfs/nfs4sysctl.c
@@ -15,14 +15,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,
@@ -41,52 +38,37 @@ static ctl_table nfs_cb_sysctls[] = {
 		.proc_handler = proc_dointvec_jiffies,
 	},
 #endif /* CONFIG_NFS_USE_NEW_IDMAPPER */
-#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;
 }
diff --git a/fs/nfs/sysctl.c b/fs/nfs/sysctl.c
index 978aaeb..6b3f253 100644
--- a/fs/nfs/sysctl.c
+++ b/fs/nfs/sysctl.c
@@ -9,39 +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,
-	},
-#ifndef CONFIG_NFS_USE_NEW_IDMAPPER
-	{
-		.procname = "idmap_cache_timeout",
-		.data = &nfs_idmap_cache_timeout,
-		.maxlen = sizeof(int),
-		.mode = 0644,
-		.proc_handler = proc_dointvec_jiffies,
-	},
-#endif /* CONFIG_NFS_USE_NEW_IDMAPPER */
-#endif
 	{
 		.procname	= "nfs_mountpoint_timeout",
 		.data		= &nfs_mountpoint_expiry_timeout,
-- 
1.7.9


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 11/21] NFS: Move lots of code from super.c
  2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
                   ` (8 preceding siblings ...)
  2012-02-10 22:01 ` [RFC 10/21] NFS: Initialize NFS v4 from nfs4super.c bjschuma
@ 2012-02-10 22:01 ` bjschuma
  2012-02-10 22:01 ` [RFC 12/21] NFS: module-specific submount function bjschuma
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:01 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

Each function that I moved required me to move two more functions... and
then solve a bunch of modpost errors.  I really wanted this to be less
than 1500 lines (actually, I was hoping for less than 1000).  Too bad
that didn't work out...

Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
---
 fs/nfs/fscache.c   |    3 +
 fs/nfs/inode.c     |    3 +
 fs/nfs/nfs.h       |   26 ++-
 fs/nfs/nfs4super.c |  571 +++++++++++++++++++++++++++++++++++++++++++++
 fs/nfs/super.c     |  649 ++++------------------------------------------------
 fs/nfs/write.c     |    1 +
 6 files changed, 646 insertions(+), 607 deletions(-)

diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
index 419119c..a5460ff 100644
--- a/fs/nfs/fscache.c
+++ b/fs/nfs/fscache.c
@@ -9,6 +9,7 @@
  * 2 of the Licence, or (at your option) any later version.
  */
 
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.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/inode.c b/fs/nfs/inode.c
index da01c56..53bb916 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1459,6 +1459,7 @@ void nfs4_evict_inode(struct inode *inode)
 	/* First call standard NFS clear_inode() code */
 	nfs_clear_inode(inode);
 }
+EXPORT_SYMBOL_GPL(nfs4_evict_inode);
 #endif
 
 struct inode *nfs_alloc_inode(struct super_block *sb)
@@ -1478,6 +1479,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)
 {
@@ -1489,6 +1491,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)
 {
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index cf49c63..dc1854c 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -29,6 +29,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);
 
@@ -59,6 +64,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 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 *);
+int nfs4_validate_text_mount_data(void *, struct nfs_parsed_mount_data *, const char *);
 
 #endif /* __LINUX_INTERNAL_NFS_H */
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 9dc0c37..b35840e 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -3,12 +3,583 @@
  */
 #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,
+};
+EXPORT_SYMBOL_GPL(nfs4_fs_type);
+
+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,
+};
+EXPORT_SYMBOL_GPL(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,
+	.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);
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 88bbebe..30e903c 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -261,20 +261,12 @@ static match_table_t nfs_local_lock_tokens = {
 	{ Opt_local_lock_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,
+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 *);
+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,
@@ -308,77 +300,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,
@@ -448,7 +369,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;
@@ -509,6 +430,7 @@ static 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
@@ -721,7 +643,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);
 
@@ -733,6 +655,7 @@ static int nfs_show_options(struct seq_file *m, struct dentry *root)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(nfs_show_options);
 
 #ifdef CONFIG_NFS_V4
 #ifdef CONFIG_NFS_V4_1
@@ -761,7 +684,7 @@ static void show_pnfs(struct seq_file *m, struct nfs_server *server) {}
 #endif
 #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;
@@ -776,17 +699,19 @@ static int nfs_show_devname(struct seq_file *m, struct dentry *root)
 	free_page((unsigned long)page);
 	return err;
 }
+EXPORT_SYMBOL_GPL(nfs_show_devname);
 
-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;
 }
+EXPORT_SYMBOL_GPL(nfs_show_path);
 
 /*
  * 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);
@@ -872,12 +797,13 @@ static 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
  * 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;
@@ -891,8 +817,9 @@ static void nfs_umount_begin(struct super_block *sb)
 	if (!IS_ERR(rpc))
 		rpc_killall_tasks(rpc);
 }
+EXPORT_SYMBOL_GPL(nfs_umount_begin);
 
-static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int version)
+struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int version)
 {
 	struct nfs_parsed_mount_data *data;
 
@@ -913,8 +840,9 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int ve
 	}
 	return data;
 }
+EXPORT_SYMBOL_GPL(nfs_alloc_parsed_mount_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);
@@ -926,6 +854,7 @@ static 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.
@@ -933,7 +862,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: {
@@ -949,6 +878,7 @@ static 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.
@@ -967,7 +897,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:
@@ -978,6 +908,7 @@ static 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
@@ -1080,8 +1011,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;
@@ -1560,6 +1490,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
@@ -1978,8 +1909,7 @@ nfs_compare_remount_data(struct nfs_server *nfss,
 	return 0;
 }
 
-static int
-nfs_remount(struct super_block *sb, int *flags, char *raw_data)
+int nfs_remount(struct super_block *sb, int *flags, char *raw_data)
 {
 	int error;
 	struct nfs_server *nfss = sb->s_fs_info;
@@ -2039,11 +1969,12 @@ out:
 	kfree(data);
 	return error;
 }
+EXPORT_SYMBOL_GPL(nfs_remount);
 
 /*
  * 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);
 
@@ -2061,6 +1992,7 @@ static 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
@@ -2143,12 +2075,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;
@@ -2162,6 +2089,7 @@ static 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)
@@ -2200,7 +2128,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);
@@ -2215,13 +2143,14 @@ static 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)
 {
 	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);
@@ -2229,13 +2158,15 @@ static int nfs_register(struct nfs_server *server)
 		nfs_mod->reference();
 	return err;
 }
+EXPORT_SYMBOL_GPL(nfs_register);
 
-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);
 	nfs_mod->unreference();
 }
+EXPORT_SYMBOL_GPL(nfs_unregister);
 
 struct dentry *_nfs_fs_mount(struct file_system_type *fs_type,
 			     struct nfs_server *server,
@@ -2352,10 +2283,11 @@ 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));
 }
+EXPORT_SYMBOL_GPL(nfs_put_super);
 
 /*
  * Destroy an NFS2/3 superblock
@@ -2452,7 +2384,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)
 {
@@ -2460,34 +2392,19 @@ 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);
 
 #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;
 
@@ -2522,484 +2439,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 */
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index b8111cb..d906336 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1607,6 +1607,7 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
 	}
 	return ret;
 }
+EXPORT_SYMBOL_GPL(nfs_write_inode);
 
 /*
  * flush the inode to disk.
-- 
1.7.9


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 12/21] NFS: module-specific submount function
  2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
                   ` (9 preceding siblings ...)
  2012-02-10 22:01 ` [RFC 11/21] NFS: Move lots of code from super.c bjschuma
@ 2012-02-10 22:01 ` bjschuma
  2012-02-10 22:01 ` [RFC 13/21] NFS: Custom alloc and free client functions for modules bjschuma
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:01 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

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 <bjschuma@netapp.com>
---
 fs/nfs/namespace.c     |   54 ++++++++++++++++++-----------------------------
 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, 60 insertions(+), 33 deletions(-)

diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 8102391..31c3fcb 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>
@@ -26,7 +27,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 +262,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;
 
@@ -302,29 +301,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
@@ -333,10 +309,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,
@@ -360,7 +337,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:
@@ -369,3 +346,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 dc1854c..dd3496a 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -27,6 +27,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 {
@@ -57,6 +58,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 474840f..c8ca918 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,
 };
 
 int __init init_nfs_v3(void)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 1147640..2328d68 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 48a9acd..92a5b9a 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 b35840e..d9bd619 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -619,6 +619,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 30e903c..c8fcec5 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -284,6 +284,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


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 13/21] NFS: Custom alloc and free client functions for modules
  2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
                   ` (10 preceding siblings ...)
  2012-02-10 22:01 ` [RFC 12/21] NFS: module-specific submount function bjschuma
@ 2012-02-10 22:01 ` bjschuma
  2012-02-10 22:01 ` [RFC 14/21] NFS: Move nfs4_set_client() and support code to nfs4client.c bjschuma
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:01 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

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 <bjschuma@netapp.com>
---
 fs/nfs/Makefile     |    2 +-
 fs/nfs/client.c     |   95 ++++++++++++--------------------------------------
 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, 129 insertions(+), 73 deletions(-)
 create mode 100644 fs/nfs/nfs4client.c

diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 92ebf2f..1961606 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 nfs4client.o
 nfs-$(CONFIG_NFS_V4_1)	+= pnfs.o pnfs_dev.o
 nfs-$(CONFIG_SYSCTL) += sysctl.o nfs4sysctl.o
 nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index a954a12..bf90169 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -54,6 +54,7 @@
 #define NFSDBG_FACILITY		NFSDBG_CLIENT
 
 DEFINE_SPINLOCK(nfs_client_lock);
+EXPORT_SYMBOL_GPL(nfs_client_lock);
 static DEFINE_SPINLOCK(nfs_version_lock);
 static LIST_HEAD(nfs_versions);
 LIST_HEAD(nfs_client_list);
@@ -66,7 +67,7 @@ static DEFINE_IDR(cb_ident_idr); /* Protected by nfs_client_lock */
  * 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;
 
@@ -82,8 +83,8 @@ retry:
 		goto retry;
 	return ret;
 }
+EXPORT_SYMBOL_GPL(nfs_get_cb_ident_idr);
 #endif /* CONFIG_NFS_V4 */
-
 /*
  * Turn off NFSv4 uid/gid mapping when using AUTH_SYS
  */
@@ -111,16 +112,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;
-};
-
 struct nfs_subversion *get_nfs_version(unsigned int version)
 {
 	struct nfs_subversion *nfs;
@@ -181,7 +172,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;
@@ -210,19 +201,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
 
 	clp->cl_proto = cl_init->proto;
 
-#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;
@@ -236,39 +214,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_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 */
@@ -284,21 +246,7 @@ static void nfs_cb_idr_remove_locked(struct nfs_client *clp)
 		idr_remove(&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(void)
 {
 }
@@ -316,11 +264,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);
 
@@ -331,13 +277,18 @@ static void nfs_free_client(struct nfs_client *clp)
 	if (clp->cl_machine_cred != NULL)
 		put_rpccred(clp->cl_machine_cred);
 
-	nfs4_deviceid_purge_client(clp);
-
 	kfree(clp->cl_hostname);
 	kfree(clp->server_scope);
 	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 dd3496a..e538207 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -16,6 +16,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 */
@@ -24,6 +34,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 *);
@@ -45,7 +57,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 c8ca918..d17ca8e 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 2328d68..9a27673 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..3f653df
--- /dev/null
+++ b/fs/nfs/nfs4client.c
@@ -0,0 +1,80 @@
+/*
+ *Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+
+#include <linux/nfs_idmap.h>
+#include "internal.h"
+#include "nfs4_fs.h"
+#include "callback.h"
+#include "pnfs.h"
+#include "nfs.h"
+
+#ifdef CONFIG_NFS_V4_1
+static void nfs4_shutdown_session(struct nfs_client *clp)
+{
+	if (nfs4_has_session(clp))
+		nfs4_destroy_session(clp->cl_session);
+}
+#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);
+	nfs4_deviceid_purge_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 d9bd619..d874d2f 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -617,6 +617,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


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 14/21] NFS: Move nfs4_set_client() and support code to nfs4client.c
  2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
                   ` (11 preceding siblings ...)
  2012-02-10 22:01 ` [RFC 13/21] NFS: Custom alloc and free client functions for modules bjschuma
@ 2012-02-10 22:01 ` bjschuma
  2012-02-10 22:01 ` [RFC 15/21] NFS: Move the nfs4_init_client() " bjschuma
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:01 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

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 <bjschuma@gmail.com>
---
 fs/nfs/client.c     |  356 +++------------------------------------------------
 fs/nfs/nfs.h        |   12 ++-
 fs/nfs/nfs4client.c |  335 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 362 insertions(+), 341 deletions(-)

diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index bf90169..69b563d 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -85,10 +85,6 @@ retry:
 }
 EXPORT_SYMBOL_GPL(nfs_get_cb_ident_idr);
 #endif /* CONFIG_NFS_V4 */
-/*
- * Turn off NFSv4 uid/gid mapping when using AUTH_SYS
- */
-static bool nfs4_disable_idmapping = true;
 
 /*
  * RPC cruft for NFS
@@ -228,11 +224,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(void)
 {
@@ -485,7 +476,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,
@@ -558,6 +549,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
@@ -587,8 +579,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;
@@ -624,6 +616,7 @@ static void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
 		BUG();
 	}
 }
+EXPORT_SYMBOL_GPL(nfs_init_timeout_values);
 
 /*
  * Create an RPC client handle
@@ -717,7 +710,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)
 {
@@ -749,6 +742,7 @@ static int nfs_init_server_rpcclient(struct nfs_server *server,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(nfs_init_server_rpcclient);
 
 /*
  * Initialise an NFS2 or NFS3 client
@@ -933,7 +927,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;
@@ -973,11 +967,12 @@ 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
  */
-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;
@@ -989,8 +984,9 @@ static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_serve
 	target->caps = source->caps;
 	target->options = source->options;
 }
+EXPORT_SYMBOL_GPL(nfs_server_copy_userdata);
 
-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;
 
@@ -1001,6 +997,7 @@ static void nfs_server_insert_lists(struct nfs_server *server)
 	spin_unlock(&nfs_client_lock);
 
 }
+EXPORT_SYMBOL_GPL(nfs_server_insert_lists);
 
 static void nfs_server_remove_lists(struct nfs_server *server)
 {
@@ -1019,7 +1016,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;
 
@@ -1056,6 +1053,7 @@ static struct nfs_server *nfs_alloc_server(void)
 
 	return server;
 }
+EXPORT_SYMBOL_GPL(nfs_alloc_server);
 
 /*
  * Free up a server record
@@ -1085,6 +1083,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
@@ -1325,325 +1324,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,
-				parent_server->client->cl_xprt->prot,
-				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 */
 
 /*
@@ -2025,7 +1705,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 e538207..1934399 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -58,9 +58,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 3f653df..7a30d0a 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -3,6 +3,8 @@
  * Written by David Howells (dhowells@redhat.com)
  */
 
+#include <linux/module.h>
+#include <linux/nfs_mount.h>
 #include <linux/nfs_idmap.h>
 #include "internal.h"
 #include "nfs4_fs.h"
@@ -10,6 +12,13 @@
 #include "pnfs.h"
 #include "nfs.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)
 {
@@ -22,6 +31,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
  */
@@ -77,4 +91,325 @@ error_cleanup:
 	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,
+				parent_server->client->cl_xprt->prot,
+				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


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 15/21] NFS: Move the nfs4_init_client() to nfs4client.c
  2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
                   ` (12 preceding siblings ...)
  2012-02-10 22:01 ` [RFC 14/21] NFS: Move nfs4_set_client() and support code to nfs4client.c bjschuma
@ 2012-02-10 22:01 ` bjschuma
  2012-02-10 22:02 ` [RFC 16/21] NFS: Move the v4 getroot code to nfs4getroot.c bjschuma
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:01 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
---
 fs/nfs/client.c     |  117 ++------------------------------------------------
 fs/nfs/nfs.h        |    2 +
 fs/nfs/nfs4client.c |  108 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 115 insertions(+), 112 deletions(-)

diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 69b563d..b709c38 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -38,7 +38,6 @@
 #include <linux/slab.h>
 #include <net/ipv6.h>
 #include <linux/nfs_xdr.h>
-#include <linux/sunrpc/bc_xprt.h>
 
 #include <asm/system.h>
 
@@ -621,10 +620,10 @@ EXPORT_SYMBOL_GPL(nfs_init_timeout_values);
 /*
  * 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 = {
@@ -657,6 +656,7 @@ static 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
@@ -1217,113 +1217,6 @@ nfs4_find_client_sessionid(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) {
-		if (nfs4_has_session(clp)) {
-			error = xprt_setup_backchannel(
-						clp->cl_rpcclient->cl_xprt,
-						NFS41_BC_MIN_CALLBACKS);
-			if (error < 0)
-				return error;
-		}
-
-		error = nfs_callback_up(clp->cl_mvops->minor_version,
-					clp->cl_rpcclient->cl_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)
-{
-	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;
-	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 1934399..38113b5 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -64,6 +64,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 7a30d0a..f3a86fc 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -6,6 +6,7 @@
 #include <linux/module.h>
 #include <linux/nfs_mount.h>
 #include <linux/nfs_idmap.h>
+#include <linux/sunrpc/bc_xprt.h>
 #include "internal.h"
 #include "nfs4_fs.h"
 #include "callback.h"
@@ -410,6 +411,113 @@ 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) {
+		if (nfs4_has_session(clp)) {
+			error = xprt_setup_backchannel(
+						clp->cl_rpcclient->cl_xprt,
+						NFS41_BC_MIN_CALLBACKS);
+			if (error < 0)
+				return error;
+		}
+
+		error = nfs_callback_up(clp->cl_mvops->minor_version,
+					clp->cl_rpcclient->cl_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)
+{
+	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;
+	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


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 16/21] NFS: Move the v4 getroot code to nfs4getroot.c
  2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
                   ` (13 preceding siblings ...)
  2012-02-10 22:01 ` [RFC 15/21] NFS: Move the nfs4_init_client() " bjschuma
@ 2012-02-10 22:02 ` bjschuma
  2012-02-10 22:02 ` [RFC 17/21] NFS: Deal with delegations bjschuma
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:02 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
---
 fs/nfs/Makefile      |    2 +-
 fs/nfs/getroot.c     |  130 +-----------------------------------------------
 fs/nfs/nfs.h         |    3 +
 fs/nfs/nfs4getroot.c |  135 ++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 141 insertions(+), 129 deletions(-)
 create mode 100644 fs/nfs/nfs4getroot.c

diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 1961606..e983eb0 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 nfs4client.o
+			   nfs4namespace.o nfs4client.o nfs4getroot.o
 nfs-$(CONFIG_NFS_V4_1)	+= pnfs.o pnfs_dev.o
 nfs-$(CONFIG_SYSCTL) += sysctl.o nfs4sysctl.o
 nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index dcb6154..637effe 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -45,7 +45,7 @@
  * 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) {
@@ -71,6 +71,7 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i
 	}
 	return 0;
 }
+EXPORT_SYMBOL_GPL(nfs_superblock_set_dummy_root);
 
 /*
  * get an NFS2/NFS3 root dentry from the root filehandle
@@ -138,130 +139,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 38113b5..0c05f14 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -85,6 +85,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 (dhowells@redhat.com)
+ */
+#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


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 17/21] NFS: Deal with delegations
  2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
                   ` (14 preceding siblings ...)
  2012-02-10 22:02 ` [RFC 16/21] NFS: Move the v4 getroot code to nfs4getroot.c bjschuma
@ 2012-02-10 22:02 ` bjschuma
  2012-02-10 22:02 ` [RFC 18/21] NFS: Use the IS_ENABLED macro for CONFIG_NFS_V4 bjschuma
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:02 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

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 <bjschuma@netapp.com>
---
 fs/nfs/delegation.c |    8 ++++----
 fs/nfs/delegation.h |    9 +++++----
 fs/nfs/inode.c      |   41 ++++++++++++++++++-----------------------
 fs/nfs/internal.h   |    3 ---
 fs/nfs/nfs.h        |    7 +++++++
 fs/nfs/nfs4proc.c   |    4 ++--
 fs/nfs/nfs4super.c  |   18 ++++++++++++++++++
 7 files changed, 54 insertions(+), 36 deletions(-)

diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 7f26540..0430513 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;
@@ -376,12 +376,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 d9322e4..0b388d7 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -9,6 +9,7 @@
 #define FS_NFS_DELEGATION_H
 
 #if defined(CONFIG_NFS_V4)
+#include "nfs.h"
 /*
  * 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);
 int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode);
 
 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 53bb916..2f48355 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -107,7 +107,7 @@ u64 nfs_compat_user_ino64(u64 fileid)
 	return ino;
 }
 
-static void nfs_clear_inode(struct inode *inode)
+void nfs_clear_inode(struct inode *inode)
 {
 	/*
 	 * The following should never happen...
@@ -118,6 +118,7 @@ static void nfs_clear_inode(struct inode *inode)
 	nfs_access_zap_cache(inode);
 	nfs_fscache_release_inode_cookie(inode);
 }
+EXPORT_SYMBOL_GPL(nfs_clear_inode);
 
 void nfs_evict_inode(struct inode *inode)
 {
@@ -207,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;
@@ -1440,28 +1457,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);
-}
-EXPORT_SYMBOL_GPL(nfs4_evict_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 cdb121d..4ea1b93 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -258,9 +258,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 0c05f14..a83e154 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -40,6 +40,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 {
@@ -88,6 +90,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 1bb0be3..3ae8485 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1028,7 +1028,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)
@@ -3694,7 +3694,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 d874d2f..2764c28 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",
-- 
1.7.9


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 18/21] NFS: Use the IS_ENABLED macro for CONFIG_NFS_V4
  2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
                   ` (15 preceding siblings ...)
  2012-02-10 22:02 ` [RFC 17/21] NFS: Deal with delegations bjschuma
@ 2012-02-10 22:02 ` bjschuma
  2012-02-10 22:02 ` [RFC 19/21] NFS: Convert v4 into a module bjschuma
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:02 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

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.  This patch
should probably be squashed with the next one before the end...

Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
---
 fs/nfs/callback.h         |    2 +-
 fs/nfs/client.c           |    6 +++---
 fs/nfs/delegation.h       |    2 +-
 fs/nfs/dir.c              |    4 ++--
 fs/nfs/direct.c           |    2 +-
 fs/nfs/file.c             |    2 +-
 fs/nfs/inode.c            |    8 ++++----
 fs/nfs/internal.h         |   14 +++++++-------
 fs/nfs/namespace.c        |    2 +-
 fs/nfs/nfs4_fs.h          |    2 +-
 fs/nfs/super.c            |   20 ++++++++++----------
 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, 45 insertions(+), 45 deletions(-)

diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index c89d3b9..8e6cf9f 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -191,7 +191,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 b709c38..6743a28 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -59,7 +59,7 @@ static LIST_HEAD(nfs_versions);
 LIST_HEAD(nfs_client_list);
 static LIST_HEAD(nfs_volume_list);
 static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 static DEFINE_IDR(cb_ident_idr); /* Protected by nfs_client_lock */
 
 /*
@@ -217,7 +217,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");
@@ -1153,7 +1153,7 @@ error:
 }
 EXPORT_SYMBOL_GPL(nfs_create_server);
 
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 /*
  * NFSv4.0 callback thread helper
  *
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 0b388d7..29d3502 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -8,7 +8,7 @@
 #ifndef FS_NFS_DELEGATION_H
 #define FS_NFS_DELEGATION_H
 
-#if defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V4)
 #include "nfs.h"
 /*
  * NFSv4 delegation
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 07ed31d..840a811 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 185e177..7aa353c 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -460,7 +460,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/file.c b/fs/nfs/file.c
index c678c00..5158bd3 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -859,7 +859,7 @@ const struct file_operations nfs_file_operations = {
 };
 EXPORT_SYMBOL_GPL(nfs_file_operations);
 
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 static int
 nfs4_file_open(struct inode *inode, struct file *filp)
 {
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 2f48355..cb645e3f 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1469,7 +1469,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;
@@ -1490,7 +1490,7 @@ EXPORT_SYMBOL_GPL(nfs_destroy_inode);
 
 static inline void nfs4_init_once(struct nfs_inode *nfsi)
 {
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 	INIT_LIST_HEAD(&nfsi->open_states);
 	nfsi->delegation = NULL;
 	nfsi->delegation_state = 0;
@@ -1637,7 +1637,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;
@@ -1670,7 +1670,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 4ea1b93..d66e660 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -181,13 +181,13 @@ static inline void nfs_fs_proc_exit(void)
 {
 }
 #endif
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 extern spinlock_t nfs_client_lock;
 extern struct list_head nfs_client_list;
 #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
@@ -224,7 +224,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
@@ -234,7 +234,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
@@ -263,7 +263,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
@@ -279,14 +279,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 31c3fcb..289560d 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -120,7 +120,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/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 9a27673..6096a8d 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 c8fcec5..427865f 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -320,7 +320,7 @@ int __init register_nfs_fs(void)
 	ret = nfs_register_sysctl();
 	if (ret < 0)
 		goto error_1;
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 	ret = register_filesystem(&nfs4_fs_type);
 	if (ret < 0)
 		goto error_2;
@@ -328,7 +328,7 @@ int __init register_nfs_fs(void)
 	register_shrinker(&acl_shrinker);
 	return 0;
 
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 error_2:
 	nfs_unregister_sysctl();
 #endif
@@ -344,7 +344,7 @@ error_0:
 void __exit unregister_nfs_fs(void)
 {
 	unregister_shrinker(&acl_shrinker);
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 	unregister_filesystem(&nfs4_fs_type);
 #endif
 	nfs_unregister_sysctl();
@@ -537,7 +537,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)
 {
@@ -658,7 +658,7 @@ int nfs_show_options(struct seq_file *m, struct dentry *root)
 }
 EXPORT_SYMBOL_GPL(nfs_show_options);
 
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 #ifdef CONFIG_NFS_V4_1
 static void show_sessions(struct seq_file *m, struct nfs_server *server)
 {
@@ -670,7 +670,7 @@ static void show_sessions(struct seq_file *m, struct nfs_server *server) {}
 #endif
 #endif
 
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 #ifdef CONFIG_NFS_V4_1
 static void show_pnfs(struct seq_file *m, struct nfs_server *server)
 {
@@ -740,7 +740,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]);
@@ -1813,7 +1813,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
@@ -1868,7 +1868,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;
@@ -2395,7 +2395,7 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,
 }
 EXPORT_SYMBOL_GPL(nfs_xdev_mount);
 
-#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 d906336..9788bee 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -431,7 +431,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)
 /*
  * Add a request to the inode's commit list.
  */
@@ -516,7 +516,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)
 {
@@ -1238,7 +1238,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
@@ -1297,7 +1297,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 766ea02..3017614 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -188,7 +188,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;
@@ -410,7 +410,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;
@@ -524,7 +524,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 c234693..50cef88 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -47,7 +47,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;
@@ -134,7 +134,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 */
@@ -192,7 +192,7 @@ struct nfs_server {
 /* maximum number of slots to use */
 #define NFS4_MAX_SLOT_TABLE RPC_MAX_SLOT_TABLE
 
-#if defined(CONFIG_NFS_V4)
+#if IS_ENABLED(CONFIG_NFS_V4)
 
 /* Sessions */
 #define SLOT_TABLE_SZ (NFS4_MAX_SLOT_TABLE/(8*sizeof(long)))
diff --git a/include/linux/nfs_idmap.h b/include/linux/nfs_idmap.h
index 3c9eeb7..7ee83d6 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 9eaa8f7..c23dee4 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -789,7 +789,7 @@ struct nfs3_getaclres {
 	struct posix_acl *	acl_default;
 };
 
-#ifdef CONFIG_NFS_V4
+#if IS_ENABLED(CONFIG_NFS_V4)
 
 typedef u64 clientid4;
 
@@ -1183,7 +1183,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


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 19/21] NFS: Convert v4 into a module
  2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
                   ` (16 preceding siblings ...)
  2012-02-10 22:02 ` [RFC 18/21] NFS: Use the IS_ENABLED macro for CONFIG_NFS_V4 bjschuma
@ 2012-02-10 22:02 ` bjschuma
  2012-02-12 18:02   ` Boaz Harrosh
  2012-02-10 22:02 ` [RFC 20/21] Export symbols for v4 module bjschuma
  2012-02-10 22:02 ` [RFC 21/21] NFS: Export v4.1 symbols back to nfs.ko bjschuma
  19 siblings, 1 reply; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:02 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

The module will be created in the same directory as nfs.ko.  You need to
run `modprobe nfs4` before you can use it.

Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
---
 fs/nfs/Kconfig     |    2 +-
 fs/nfs/Makefile    |   14 ++++++++------
 fs/nfs/inode.c     |    6 ------
 fs/nfs/nfs4super.c |    5 +++++
 4 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index 57c4b19..608b84a 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
 	help
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index e983eb0..c356cda 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -7,14 +7,10 @@ obj-$(CONFIG_NFS_FS) += nfs.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
+			   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 nfs4client.o nfs4getroot.o
 nfs-$(CONFIG_NFS_V4_1)	+= pnfs.o pnfs_dev.o
-nfs-$(CONFIG_SYSCTL) += sysctl.o nfs4sysctl.o
+nfs-$(CONFIG_SYSCTL) += sysctl.o
 nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
 
 obj-$(CONFIG_NFS_V2) += nfs2.o
@@ -24,6 +20,12 @@ obj-$(CONFIG_NFS_V3) += nfs3.o
 nfs3-y += nfs3super.o nfs3client.o nfs3proc.o nfs3xdr.o
 nfs3-y += nfs3acl.o
 
+obj-$(CONFIG_NFS_V4) += nfs4.o
+nfs4-y = nfs4super.o nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
+	 delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \
+	 nfs4namespace.o dns_resolve.o nfs4client.o nfs4getroot.o
+nfs4-$(CONFIG_SYSCTL) += nfs4sysctl.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/inode.c b/fs/nfs/inode.c
index cb645e3f..2ee6259 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1637,9 +1637,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
@@ -1670,9 +1667,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/nfs4super.c b/fs/nfs/nfs4super.c
index 2764c28..3e515db 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -669,3 +669,8 @@ void __exit exit_nfs_v4(void)
 	nfs4_unregister_sysctl();
 	nfs_idmap_quit();
 }
+
+MODULE_LICENSE("GPL");
+
+module_init(init_nfs_v4);
+module_exit(exit_nfs_v4);
-- 
1.7.9


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 20/21] Export symbols for v4 module
  2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
                   ` (17 preceding siblings ...)
  2012-02-10 22:02 ` [RFC 19/21] NFS: Convert v4 into a module bjschuma
@ 2012-02-10 22:02 ` bjschuma
  2012-02-10 22:02 ` [RFC 21/21] NFS: Export v4.1 symbols back to nfs.ko bjschuma
  19 siblings, 0 replies; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:02 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

This patch should be squashed with the previous one for everything to work.  I
also need to double check that all of these are actually needed...

Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
---
 fs/nfs/client.c    |    6 ++++++
 fs/nfs/dir.c       |    4 ++++
 fs/nfs/file.c      |    1 +
 fs/nfs/inode.c     |    5 +++++
 fs/nfs/namespace.c |    2 ++
 fs/nfs/pagelist.c  |    3 +++
 fs/nfs/pnfs.c      |   15 +++++++++++++++
 fs/nfs/pnfs_dev.c  |    1 +
 fs/nfs/read.c      |    3 +++
 fs/nfs/super.c     |    3 +++
 fs/nfs/write.c     |    4 ++++
 11 files changed, 47 insertions(+), 0 deletions(-)

diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 6743a28..abd7d86 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -57,6 +57,7 @@ EXPORT_SYMBOL_GPL(nfs_client_lock);
 static DEFINE_SPINLOCK(nfs_version_lock);
 static LIST_HEAD(nfs_versions);
 LIST_HEAD(nfs_client_list);
+EXPORT_SYMBOL_GPL(nfs_client_list);
 static LIST_HEAD(nfs_volume_list);
 static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
 #if IS_ENABLED(CONFIG_NFS_V4)
@@ -558,6 +559,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
@@ -574,6 +576,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
@@ -1171,6 +1174,7 @@ nfs4_find_client_ident(int cb_ident)
 	spin_unlock(&nfs_client_lock);
 	return clp;
 }
+EXPORT_SYMBOL_GPL(nfs4_find_client_ident);
 
 #if defined(CONFIG_NFS_V4_1)
 /*
@@ -1206,6 +1210,7 @@ nfs4_find_client_sessionid(const struct sockaddr *addr,
 	spin_unlock(&nfs_client_lock);
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(nfs4_find_client_sessionid);
 
 #else /* CONFIG_NFS_V4_1 */
 
@@ -1215,6 +1220,7 @@ nfs4_find_client_sessionid(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 840a811..39c71ed 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/file.c b/fs/nfs/file.c
index 5158bd3..219bb22 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -889,4 +889,5 @@ const struct file_operations nfs4_file_operations = {
 	.check_flags	= nfs_check_flags,
 	.setlease	= nfs_setlease,
 };
+EXPORT_SYMBOL_GPL(nfs4_file_operations);
 #endif /* CONFIG_NFS_V4 */
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 2ee6259..e2c372c 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -83,6 +83,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
@@ -421,6 +422,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)
 
@@ -686,6 +688,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)
 {
@@ -712,6 +715,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
@@ -1536,6 +1540,7 @@ static void nfs_destroy_inodecache(void)
 }
 
 struct workqueue_struct *nfsiod_workqueue;
+EXPORT_SYMBOL_GPL(nfsiod_workqueue);
 
 /*
  * start up the nfsiod workqueue
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 289560d..69ec69b 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -119,6 +119,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)
@@ -149,6 +150,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/pagelist.c b/fs/nfs/pagelist.c
index 77a184e..0864530 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -249,6 +249,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
@@ -390,6 +391,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
@@ -405,6 +407,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/pnfs.c b/fs/nfs/pnfs.c
index 9292787..f7edc4a 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -189,6 +189,7 @@ get_layout_hdr(struct pnfs_layout_hdr *lo)
 {
 	atomic_inc(&lo->plh_refcount);
 }
+EXPORT_SYMBOL_GPL(get_layout_hdr);
 
 static struct pnfs_layout_hdr *
 pnfs_alloc_layout_hdr(struct inode *ino, gfp_t gfp_flags)
@@ -232,6 +233,7 @@ put_layout_hdr(struct pnfs_layout_hdr *lo)
 		spin_unlock(&inode->i_lock);
 	}
 }
+EXPORT_SYMBOL_GPL(put_layout_hdr);
 
 static void
 init_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg)
@@ -412,6 +414,7 @@ mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo,
 	dprintk("%s:Return %i\n", __func__, invalid - removed);
 	return invalid - removed;
 }
+EXPORT_SYMBOL_GPL(mark_matching_lsegs_invalid);
 
 /* note free_me must contain lsegs from a single layout_hdr */
 void
@@ -439,6 +442,7 @@ pnfs_free_lseg_list(struct list_head *free_me)
 		free_lseg(lseg);
 	}
 }
+EXPORT_SYMBOL_GPL(pnfs_free_lseg_list);
 
 void
 pnfs_destroy_layout(struct nfs_inode *nfsi)
@@ -455,6 +459,7 @@ pnfs_destroy_layout(struct nfs_inode *nfsi)
 	spin_unlock(&nfsi->vfs_inode.i_lock);
 	pnfs_free_lseg_list(&tmp_list);
 }
+EXPORT_SYMBOL_GPL(pnfs_destroy_layout);
 
 /*
  * Called by the state manger to remove all layouts established under an
@@ -488,6 +493,7 @@ pnfs_destroy_all_layouts(struct nfs_client *clp)
 		pnfs_destroy_layout(NFS_I(lo->plh_inode));
 	}
 }
+EXPORT_SYMBOL_GPL(pnfs_destroy_all_layouts);
 
 /* update lo->plh_stateid with new if is more recent */
 void
@@ -518,6 +524,7 @@ pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, const nfs4_stateid *new,
 		}
 	}
 }
+EXPORT_SYMBOL_GPL(pnfs_set_layout_stateid);
 
 /* lget is set to 1 if called from inside send_layoutget call chain */
 static bool
@@ -558,6 +565,7 @@ pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
 	dprintk("<-- %s\n", __func__);
 	return status;
 }
+EXPORT_SYMBOL_GPL(pnfs_choose_layoutget_stateid);
 
 /*
 * Get layout from server.
@@ -693,6 +701,7 @@ out:
 	dprintk("<-- %s status: %d\n", __func__, status);
 	return status;
 }
+EXPORT_SYMBOL_GPL(_pnfs_return_layout);
 
 bool pnfs_roc(struct inode *ino)
 {
@@ -723,6 +732,7 @@ out_nolayout:
 	spin_unlock(&ino->i_lock);
 	return false;
 }
+EXPORT_SYMBOL_GPL(pnfs_roc);
 
 void pnfs_roc_release(struct inode *ino)
 {
@@ -734,6 +744,7 @@ void pnfs_roc_release(struct inode *ino)
 	put_layout_hdr_locked(lo);
 	spin_unlock(&ino->i_lock);
 }
+EXPORT_SYMBOL_GPL(pnfs_roc_release);
 
 void pnfs_roc_set_barrier(struct inode *ino, u32 barrier)
 {
@@ -745,6 +756,7 @@ void pnfs_roc_set_barrier(struct inode *ino, u32 barrier)
 		lo->plh_barrier = barrier;
 	spin_unlock(&ino->i_lock);
 }
+EXPORT_SYMBOL_GPL(pnfs_roc_set_barrier);
 
 bool pnfs_roc_drain(struct inode *ino, u32 *barrier)
 {
@@ -770,6 +782,7 @@ bool pnfs_roc_drain(struct inode *ino, u32 *barrier)
 	spin_unlock(&ino->i_lock);
 	return found;
 }
+EXPORT_SYMBOL_GPL(pnfs_roc_drain);
 
 /*
  * Compare two layout segments for sorting into layout cache.
@@ -1080,6 +1093,7 @@ out_forget_reply:
 	NFS_SERVER(ino)->pnfs_curr_ld->free_lseg(lseg);
 	goto out;
 }
+EXPORT_SYMBOL_GPL(pnfs_layout_process);
 
 void
 pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
@@ -1473,6 +1487,7 @@ void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data)
 	if (nfss->pnfs_curr_ld->cleanup_layoutcommit)
 		nfss->pnfs_curr_ld->cleanup_layoutcommit(data);
 }
+EXPORT_SYMBOL_GPL(pnfs_cleanup_layoutcommit);
 
 /*
  * For the LAYOUT4_NFSV4_1_FILES layout type, NFS_DATA_SYNC WRITEs and
diff --git a/fs/nfs/pnfs_dev.c b/fs/nfs/pnfs_dev.c
index 4f359d2..e0041f3 100644
--- a/fs/nfs/pnfs_dev.c
+++ b/fs/nfs/pnfs_dev.c
@@ -255,6 +255,7 @@ nfs4_deviceid_purge_client(const struct nfs_client *clp)
 	for (h = 0; h < NFS4_DEVICE_ID_HASH_SIZE; h++)
 		_deviceid_purge_client(clp, h);
 }
+EXPORT_SYMBOL_GPL(nfs4_deviceid_purge_client);
 
 /*
  * Stop use of all deviceids associated with an nfs_client
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 3c2540d..cdeffdc 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)
@@ -115,6 +116,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)
 {
@@ -368,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 427865f..ad5b528 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -358,6 +358,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)
 {
@@ -366,6 +367,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
@@ -2439,5 +2441,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 9788bee..87437e3 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -104,6 +104,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)
 {
@@ -1034,6 +1035,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)
 {
@@ -1058,6 +1060,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)
 {
@@ -1623,6 +1626,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


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 21/21] NFS: Export v4.1 symbols back to nfs.ko
  2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
                   ` (18 preceding siblings ...)
  2012-02-10 22:02 ` [RFC 20/21] Export symbols for v4 module bjschuma
@ 2012-02-10 22:02 ` bjschuma
  19 siblings, 0 replies; 25+ messages in thread
From: bjschuma @ 2012-02-10 22:02 UTC (permalink / raw)
  To: Trond.Myklebust; +Cc: linux-nfs, Bryan Schumaker

From: Bryan Schumaker <bjschuma@netapp.com>

pnfs is buried too deep in the generic client to make it easy to
separate out.  Instead, I just export the symbols back so when
CONFIG_V4_1 is selected nfs.ko will depend on nfs4.ko

Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
---
 fs/nfs/Makefile   |    2 +-
 fs/nfs/nfs4proc.c |    1 +
 fs/nfs/pnfs.c     |    5 +++++
 3 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index c356cda..863bf85 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 \
 			   cache_lib.o
 nfs-$(CONFIG_ROOT_NFS)	+= nfsroot.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
 
@@ -24,6 +23,7 @@ obj-$(CONFIG_NFS_V4) += nfs4.o
 nfs4-y = nfs4super.o nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
 	 delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \
 	 nfs4namespace.o dns_resolve.o nfs4client.o nfs4getroot.o
+nfs4-$(CONFIG_NFS_V4_1)	+= pnfs.o pnfs_dev.o
 nfs4-$(CONFIG_SYSCTL) += nfs4sysctl.o
 
 obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 3ae8485..1cb940b 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -631,6 +631,7 @@ out:
 	dprintk("<-- %s status=%d\n", __func__, ret);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(nfs4_setup_sequence);
 
 struct nfs41_call_sync_data {
 	const struct nfs_server *seq_server;
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index f7edc4a..ef2053f 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -84,6 +84,7 @@ unset_pnfs_layoutdriver(struct nfs_server *nfss)
 	}
 	nfss->pnfs_curr_ld = NULL;
 }
+EXPORT_SYMBOL_GPL(unset_pnfs_layoutdriver);
 
 /*
  * Try to set the server's pnfs module to the pnfs layout type specified by id.
@@ -135,6 +136,7 @@ out_no_driver:
 	dprintk("%s: Using NFSv4 I/O\n", __func__);
 	server->pnfs_curr_ld = NULL;
 }
+EXPORT_SYMBOL_GPL(set_pnfs_layoutdriver);
 
 int
 pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *ld_type)
@@ -1141,6 +1143,7 @@ pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode)
 	nfs_pageio_init(pgio, inode, ld->pg_read_ops, server->rsize, 0);
 	return true;
 }
+EXPORT_SYMBOL_GPL(pnfs_pageio_init_read);
 
 bool
 pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, int ioflags)
@@ -1153,6 +1156,7 @@ pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode,
 	nfs_pageio_init(pgio, inode, ld->pg_write_ops, server->wsize, ioflags);
 	return true;
 }
+EXPORT_SYMBOL_GPL(pnfs_pageio_init_write);
 
 bool
 pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
@@ -1567,3 +1571,4 @@ out_free:
 	kfree(data);
 	goto out;
 }
+EXPORT_SYMBOL_GPL(pnfs_layoutcommit_inode);
-- 
1.7.9


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [RFC 19/21] NFS: Convert v4 into a module
  2012-02-10 22:02 ` [RFC 19/21] NFS: Convert v4 into a module bjschuma
@ 2012-02-12 18:02   ` Boaz Harrosh
  2012-02-12 22:20     ` Myklebust, Trond
  0 siblings, 1 reply; 25+ messages in thread
From: Boaz Harrosh @ 2012-02-12 18:02 UTC (permalink / raw)
  To: bjschuma; +Cc: Trond.Myklebust, linux-nfs

On 02/11/2012 12:02 AM, bjschuma@netapp.com wrote:
> The module will be created in the same directory as nfs.ko.  You need to
> run `modprobe nfs4` before you can use it.
> 

Can we do this mod_alias and autoloading magic like we do with 
LD drivers, so if NFSv4 is requested it is automatically loaded
by Kernel. 

This way the impact on user-mode will be minimal.

Thanks
Boaz

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 19/21] NFS: Convert v4 into a module
  2012-02-12 18:02   ` Boaz Harrosh
@ 2012-02-12 22:20     ` Myklebust, Trond
  2012-02-12 23:05       ` Boaz Harrosh
  0 siblings, 1 reply; 25+ messages in thread
From: Myklebust, Trond @ 2012-02-12 22:20 UTC (permalink / raw)
  To: Boaz Harrosh; +Cc: Schumaker, Bryan, linux-nfs

T24gU3VuLCAyMDEyLTAyLTEyIGF0IDIwOjAyICswMjAwLCBCb2F6IEhhcnJvc2ggd3JvdGU6DQo+
IE9uIDAyLzExLzIwMTIgMTI6MDIgQU0sIGJqc2NodW1hQG5ldGFwcC5jb20gd3JvdGU6DQo+ID4g
VGhlIG1vZHVsZSB3aWxsIGJlIGNyZWF0ZWQgaW4gdGhlIHNhbWUgZGlyZWN0b3J5IGFzIG5mcy5r
by4gIFlvdSBuZWVkIHRvDQo+ID4gcnVuIGBtb2Rwcm9iZSBuZnM0YCBiZWZvcmUgeW91IGNhbiB1
c2UgaXQuDQo+ID4gDQo+IA0KPiBDYW4gd2UgZG8gdGhpcyBtb2RfYWxpYXMgYW5kIGF1dG9sb2Fk
aW5nIG1hZ2ljIGxpa2Ugd2UgZG8gd2l0aCANCj4gTEQgZHJpdmVycywgc28gaWYgTkZTdjQgaXMg
cmVxdWVzdGVkIGl0IGlzIGF1dG9tYXRpY2FsbHkgbG9hZGVkDQo+IGJ5IEtlcm5lbC4gDQoNCllv
dSBuZWVkIHRvIGNhbGwgcmVxdWVzdC1tb2R1bGUoKSBmcm9tIHRoZSBuZnMua28gbW9kdWxlIGFz
IHNvb24gYXMgeW91DQprbm93IHdoaWNoIHZlcnNpb24gdGhlIHVzZXIgaXMgdHJ5aW5nIHRvIGxv
YWQuLi4NCkkgZG9uJ3Qgc2VlIHdoeSB5b3UgbmVlZCBtb2RfYWxpYXM/DQoNCi0tIA0KVHJvbmQg
TXlrbGVidXN0DQpMaW51eCBORlMgY2xpZW50IG1haW50YWluZXINCg0KTmV0QXBwDQpUcm9uZC5N
eWtsZWJ1c3RAbmV0YXBwLmNvbQ0Kd3d3Lm5ldGFwcC5jb20NCg0K

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 19/21] NFS: Convert v4 into a module
  2012-02-12 22:20     ` Myklebust, Trond
@ 2012-02-12 23:05       ` Boaz Harrosh
  2012-02-13 13:29         ` Bryan Schumaker
  0 siblings, 1 reply; 25+ messages in thread
From: Boaz Harrosh @ 2012-02-12 23:05 UTC (permalink / raw)
  To: Myklebust, Trond; +Cc: Schumaker, Bryan, linux-nfs

On 02/13/2012 12:20 AM, Myklebust, Trond wrote:
> On Sun, 2012-02-12 at 20:02 +0200, Boaz Harrosh wrote:
>> On 02/11/2012 12:02 AM, bjschuma@netapp.com wrote:
>>> The module will be created in the same directory as nfs.ko.  You need to
>>> run `modprobe nfs4` before you can use it.
>>>
>>
>> Can we do this mod_alias and autoloading magic like we do with 
>> LD drivers, so if NFSv4 is requested it is automatically loaded
>> by Kernel. 
> 
> You need to call request-module() from the nfs.ko module as soon as you
> know which version the user is trying to load...
> I don't see why you need mod_alias?
> 

That will work. I can now see that it's on the todo in the [00/21] mail
Sorry for the noise

Thanks
Boaz

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 19/21] NFS: Convert v4 into a module
  2012-02-12 23:05       ` Boaz Harrosh
@ 2012-02-13 13:29         ` Bryan Schumaker
  0 siblings, 0 replies; 25+ messages in thread
From: Bryan Schumaker @ 2012-02-13 13:29 UTC (permalink / raw)
  To: Boaz Harrosh; +Cc: Myklebust, Trond, Schumaker, Bryan, linux-nfs

On 02/12/12 18:05, Boaz Harrosh wrote:

> On 02/13/2012 12:20 AM, Myklebust, Trond wrote:
>> On Sun, 2012-02-12 at 20:02 +0200, Boaz Harrosh wrote:
>>> On 02/11/2012 12:02 AM, bjschuma@netapp.com wrote:
>>>> The module will be created in the same directory as nfs.ko.  You need to
>>>> run `modprobe nfs4` before you can use it.
>>>>
>>>
>>> Can we do this mod_alias and autoloading magic like we do with 
>>> LD drivers, so if NFSv4 is requested it is automatically loaded
>>> by Kernel. 
>>
>> You need to call request-module() from the nfs.ko module as soon as you
>> know which version the user is trying to load...
>> I don't see why you need mod_alias?
>>
> 
> That will work. I can now see that it's on the todo in the [00/21] mail
> Sorry for the noise


I agree that it's important to do, so don't worry about the extra reminder!

- Bryan

> 
> Thanks
> Boaz



^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2012-02-13 13:29 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-02-10 22:01 [RFC 00/21] NFS: Create NFS Modules bjschuma
2012-02-10 22:01 ` [RFC 02/21] NFS: Make v2 configurable bjschuma
2012-02-10 22:01 ` [RFC 03/21] NFS: Add version registering framework bjschuma
2012-02-10 22:01 ` [RFC 04/21] NFS: Convert v2 into a module bjschuma
2012-02-10 22:01 ` [RFC 05/21] NFS: Break up the nfs_fs_mount function bjschuma
2012-02-10 22:01 ` [RFC 06/21] NFS: Create a single nfs_clone_super() function bjschuma
2012-02-10 22:01 ` [RFC 07/21] NFS: Version specific xdev mounting bjschuma
2012-02-10 22:01 ` [RFC 08/21] NFS: Only initialize the ACL client in the v3 case bjschuma
2012-02-10 22:01 ` [RFC 09/21] NFS: Convert v3 into a module bjschuma
2012-02-10 22:01 ` [RFC 10/21] NFS: Initialize NFS v4 from nfs4super.c bjschuma
2012-02-10 22:01 ` [RFC 11/21] NFS: Move lots of code from super.c bjschuma
2012-02-10 22:01 ` [RFC 12/21] NFS: module-specific submount function bjschuma
2012-02-10 22:01 ` [RFC 13/21] NFS: Custom alloc and free client functions for modules bjschuma
2012-02-10 22:01 ` [RFC 14/21] NFS: Move nfs4_set_client() and support code to nfs4client.c bjschuma
2012-02-10 22:01 ` [RFC 15/21] NFS: Move the nfs4_init_client() " bjschuma
2012-02-10 22:02 ` [RFC 16/21] NFS: Move the v4 getroot code to nfs4getroot.c bjschuma
2012-02-10 22:02 ` [RFC 17/21] NFS: Deal with delegations bjschuma
2012-02-10 22:02 ` [RFC 18/21] NFS: Use the IS_ENABLED macro for CONFIG_NFS_V4 bjschuma
2012-02-10 22:02 ` [RFC 19/21] NFS: Convert v4 into a module bjschuma
2012-02-12 18:02   ` Boaz Harrosh
2012-02-12 22:20     ` Myklebust, Trond
2012-02-12 23:05       ` Boaz Harrosh
2012-02-13 13:29         ` Bryan Schumaker
2012-02-10 22:02 ` [RFC 20/21] Export symbols for v4 module bjschuma
2012-02-10 22:02 ` [RFC 21/21] NFS: Export v4.1 symbols back to nfs.ko bjschuma

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.