2012-07-16 20:39:23

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v200/12] NFS: Split out version-specific code

From: Bryan Schumaker <[email protected]>

These patches split out most NFS version-specific code into files based on the
NFS version it belongs to. The first two patches make all the NFS v2 and v3
changes that are needed, the rest carefully split out NFS v4 code from the
generic client. I apologize for the amount of flux caused by these patches
but after this the rest of my modularization changes are really, really easy.

I would appreciate it if lots of people could take the time to look at these
patches. I think the changes are fairly straightforward, but the large amount
of code changed means I could have easily missed something. I expect there
will be conflicts with Chuck's recent TEST_STATEID changes, I'm willing to
update and resubmit these patches if Chuck's changes are merged into Trond's
git tree first.

When creating new files with moved code I tried to preserve the copyright of
the original file. Right now fs/nfs/sysctl.c doesn't have a copyright line so
I used `git annotate` to guess that Trond wrote the code in 2006 when creating
fs/nfs/nfs4sysctl.c. If I got something wrong, please let me know!

Changes in v2:
- Rebase against Trond's nfs-for-bryan tree, which includes recent VFS changes
and other patches affecting code that I touch.

Thanks,
- Bryan

Bryan Schumaker (12):
NFS: Split out NFS v2 inode operations
NFS: Split out NFS v3 inode operations
NFS: Split out NFS v4 inode operations
NFS: Create an init_nfs_v4() function
NFS: Initialize v4 sysctls from nfs_init_v4()
NFS: Split out NFS v4 file operations
NFS: Move the v4 getroot code to nfs4getroot.c
NFS: Initialize the NFS v4 client from init_nfs_v4()
NFS: Split out NFS v4 server creating code
NFS: Create a single nfs_clone_super() function
NFS: Split out the NFS v4 filesystem types
NFS: Split out NFS v4 client functions

fs/nfs/Makefile | 11 +-
fs/nfs/client.c | 687 +------------------------------------------------
fs/nfs/dir.c | 97 +------
fs/nfs/file.c | 169 ++----------
fs/nfs/getroot.c | 50 ----
fs/nfs/inode.c | 67 ++---
fs/nfs/internal.h | 81 ++++++
fs/nfs/nfs3proc.c | 29 +++
fs/nfs/nfs4_fs.h | 26 +-
fs/nfs/nfs4client.c | 663 +++++++++++++++++++++++++++++++++++++++++++++++
fs/nfs/nfs4file.c | 126 +++++++++
fs/nfs/nfs4getroot.c | 49 ++++
fs/nfs/nfs4proc.c | 20 ++
fs/nfs/nfs4super.c | 360 ++++++++++++++++++++++++++
fs/nfs/nfs4sysctl.c | 68 +++++
fs/nfs/proc.c | 21 ++
fs/nfs/super.c | 425 ++----------------------------
fs/nfs/sysctl.c | 26 --
include/linux/nfs_fs.h | 8 -
19 files changed, 1554 insertions(+), 1429 deletions(-)
create mode 100644 fs/nfs/nfs4client.c
create mode 100644 fs/nfs/nfs4file.c
create mode 100644 fs/nfs/nfs4getroot.c
create mode 100644 fs/nfs/nfs4super.c
create mode 100644 fs/nfs/nfs4sysctl.c

--
1.7.11.2



2012-07-17 19:11:37

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v3 04/12] NFS: Create an init_nfs_v4() function

This patch should work better, thanks Fengguang!

- Bryan



I want to initialize all of NFS v4 in a single function that will
eventually be used as the v4 module init function.

Signed-off-by: Bryan Schumaker <[email protected]>
Signed-off-by: Trond Myklebust <[email protected]>
---
v3: Don't declare exit_nfs_v4() as an __exit function
fs/nfs/Makefile | 2 +-
fs/nfs/inode.c | 67 ++++++++++++++++++++++++++++++------------------------
fs/nfs/nfs4_fs.h | 4 ++++
fs/nfs/nfs4super.c | 23 +++++++++++++++++++
4 files changed, 65 insertions(+), 31 deletions(-)
create mode 100644 fs/nfs/nfs4super.c

diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 7ddd45d..162a699 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -13,7 +13,7 @@ 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 \
- 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/inode.c b/fs/nfs/inode.c
index 28c9ebb..35f7e4b 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -32,7 +32,6 @@
#include <linux/lockd/bind.h>
#include <linux/seq_file.h>
#include <linux/mount.h>
-#include <linux/nfs_idmap.h>
#include <linux/vfs.h>
#include <linux/inet.h>
#include <linux/nfs_xdr.h>
@@ -1628,87 +1627,96 @@ 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;
+ goto out11;

err = register_pernet_subsys(&nfs_net_ops);
if (err < 0)
- goto out8;
+ goto out10;

err = nfs_fscache_register();
if (err < 0)
- goto out7;
+ goto out9;

err = nfsiod_start();
if (err)
- goto out6;
+ goto out8;

err = nfs_fs_proc_init();
if (err)
- goto out5;
+ goto out7;

err = nfs_init_nfspagecache();
if (err)
- goto out4;
+ goto out6;

err = nfs_init_inodecache();
if (err)
- goto out3;
+ goto out5;

err = nfs_init_readpagecache();
if (err)
- goto out2;
+ goto out4;

err = nfs_init_writepagecache();
if (err)
- goto out1;
+ goto out3;
- goto out0;
+ goto out2;

#ifdef CONFIG_PROC_FS
rpc_proc_register(&init_net, &nfs_rpcstat);
#endif
+
+#ifdef CONFIG_NFS_V4
+ err = init_nfs_v4();
+ if (err)
+ goto out1;
+#endif
+
if ((err = register_nfs_fs()) != 0)
- goto out;
+ goto out0;
+
return 0;
-out:
+out0:
+#ifdef CONFIG_NFS_V4
+ exit_nfs_v4();
+out1:
+#endif
#ifdef CONFIG_PROC_FS
rpc_proc_unregister(&init_net, "nfs");
#endif
nfs_destroy_directcache();
-out0:
- nfs_destroy_writepagecache();
-out1:
- nfs_destroy_readpagecache();
out2:
- nfs_destroy_inodecache();
+ nfs_destroy_writepagecache();
out3:
- nfs_destroy_nfspagecache();
+ nfs_destroy_readpagecache();
out4:
- nfs_fs_proc_exit();
+ nfs_destroy_inodecache();
out5:
- nfsiod_stop();
+ nfs_destroy_nfspagecache();
out6:
- nfs_fscache_unregister();
+ nfs_fs_proc_exit();
out7:
- unregister_pernet_subsys(&nfs_net_ops);
+ nfsiod_stop();
out8:
- nfs_dns_resolver_destroy();
+ nfs_fscache_unregister();
out9:
- nfs_idmap_quit();
+ unregister_pernet_subsys(&nfs_net_ops);
out10:
+ nfs_dns_resolver_destroy();
+out11:
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();
@@ -1717,7 +1725,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/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index e2c4c72..1a6ed3f 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -364,6 +364,10 @@ extern void nfs4_free_lock_state(struct nfs_server *server, struct nfs4_lock_sta

extern const nfs4_stateid zero_stateid;

+/* nfs4super.c */
+int init_nfs_v4(void);
+void exit_nfs_v4(void);
+
/* nfs4xdr.c */
extern struct rpc_procinfo nfs4_procedures[];

diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
new file mode 100644
index 0000000..baa14d5
--- /dev/null
+++ b/fs/nfs/nfs4super.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2012 Bryan Schumaker <[email protected]>
+ */
+#include <linux/init.h>
+#include <linux/nfs_idmap.h>
+
+int __init init_nfs_v4(void)
+{
+ int err;
+
+ err = nfs_idmap_init();
+ if (err)
+ goto out;
+
+ return 0;
+out:
+ return err;
+}
+
+void exit_nfs_v4(void)
+{
+ nfs_idmap_quit();
+}
--
1.7.11.2



On 07/16/2012 04:39 PM, [email protected] wrote:
> From: Bryan Schumaker <[email protected]>
>
> I want to initialize all of NFS v4 in a single function that will
> eventually be used as the v4 module init function.
>
> Signed-off-by: Bryan Schumaker <[email protected]>
> ---
> fs/nfs/Makefile | 2 +-
> fs/nfs/inode.c | 67 ++++++++++++++++++++++++++++++------------------------
> fs/nfs/nfs4_fs.h | 4 ++++
> fs/nfs/nfs4super.c | 23 +++++++++++++++++++
> 4 files changed, 65 insertions(+), 31 deletions(-)
> create mode 100644 fs/nfs/nfs4super.c
>
> diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
> index 7ddd45d..162a699 100644
> --- a/fs/nfs/Makefile
> +++ b/fs/nfs/Makefile
> @@ -13,7 +13,7 @@ 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 \
> - 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/inode.c b/fs/nfs/inode.c
> index 28c9ebb..35f7e4b 100644
> --- a/fs/nfs/inode.c
> +++ b/fs/nfs/inode.c
> @@ -32,7 +32,6 @@
> #include <linux/lockd/bind.h>
> #include <linux/seq_file.h>
> #include <linux/mount.h>
> -#include <linux/nfs_idmap.h>
> #include <linux/vfs.h>
> #include <linux/inet.h>
> #include <linux/nfs_xdr.h>
> @@ -1628,87 +1627,96 @@ 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;
> + goto out11;
>
> err = register_pernet_subsys(&nfs_net_ops);
> if (err < 0)
> - goto out8;
> + goto out10;
>
> err = nfs_fscache_register();
> if (err < 0)
> - goto out7;
> + goto out9;
>
> err = nfsiod_start();
> if (err)
> - goto out6;
> + goto out8;
>
> err = nfs_fs_proc_init();
> if (err)
> - goto out5;
> + goto out7;
>
> err = nfs_init_nfspagecache();
> if (err)
> - goto out4;
> + goto out6;
>
> err = nfs_init_inodecache();
> if (err)
> - goto out3;
> + goto out5;
>
> err = nfs_init_readpagecache();
> if (err)
> - goto out2;
> + goto out4;
>
> err = nfs_init_writepagecache();
> if (err)
> - goto out1;
> + goto out3;
>
> err = nfs_init_directcache();
> if (err)
> - goto out0;
> + goto out2;
>
> #ifdef CONFIG_PROC_FS
> rpc_proc_register(&init_net, &nfs_rpcstat);
> #endif
> +
> +#ifdef CONFIG_NFS_V4
> + err = init_nfs_v4();
> + if (err)
> + goto out1;
> +#endif
> +
> if ((err = register_nfs_fs()) != 0)
> - goto out;
> + goto out0;
> +
> return 0;
> -out:
> +out0:
> +#ifdef CONFIG_NFS_V4
> + exit_nfs_v4();
> +out1:
> +#endif
> #ifdef CONFIG_PROC_FS
> rpc_proc_unregister(&init_net, "nfs");
> #endif
> nfs_destroy_directcache();
> -out0:
> - nfs_destroy_writepagecache();
> -out1:
> - nfs_destroy_readpagecache();
> out2:
> - nfs_destroy_inodecache();
> + nfs_destroy_writepagecache();
> out3:
> - nfs_destroy_nfspagecache();
> + nfs_destroy_readpagecache();
> out4:
> - nfs_fs_proc_exit();
> + nfs_destroy_inodecache();
> out5:
> - nfsiod_stop();
> + nfs_destroy_nfspagecache();
> out6:
> - nfs_fscache_unregister();
> + nfs_fs_proc_exit();
> out7:
> - unregister_pernet_subsys(&nfs_net_ops);
> + nfsiod_stop();
> out8:
> - nfs_dns_resolver_destroy();
> + nfs_fscache_unregister();
> out9:
> - nfs_idmap_quit();
> + unregister_pernet_subsys(&nfs_net_ops);
> out10:
> + nfs_dns_resolver_destroy();
> +out11:
> 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();
> @@ -1717,7 +1725,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/nfs4_fs.h b/fs/nfs/nfs4_fs.h
> index e2c4c72..1a6ed3f 100644
> --- a/fs/nfs/nfs4_fs.h
> +++ b/fs/nfs/nfs4_fs.h
> @@ -364,6 +364,10 @@ extern void nfs4_free_lock_state(struct nfs_server *server, struct nfs4_lock_sta
>
> extern const nfs4_stateid zero_stateid;
>
> +/* nfs4super.c */
> +int init_nfs_v4(void);
> +void exit_nfs_v4(void);
> +
> /* nfs4xdr.c */
> extern struct rpc_procinfo nfs4_procedures[];
>
> diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
> new file mode 100644
> index 0000000..366e414
> --- /dev/null
> +++ b/fs/nfs/nfs4super.c
> @@ -0,0 +1,23 @@
> +/*
> + * Copyright (c) 2012 Bryan Schumaker <[email protected]>
> + */
> +#include <linux/init.h>
> +#include <linux/nfs_idmap.h>
> +
> +int __init init_nfs_v4(void)
> +{
> + int err;
> +
> + err = nfs_idmap_init();
> + if (err)
> + goto out;
> +
> + return 0;
> +out:
> + return err;
> +}
> +
> +void __exit exit_nfs_v4(void)
> +{
> + nfs_idmap_quit();
> +}
>



2012-07-16 20:39:27

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v2 05/12] NFS: Initialize v4 sysctls from nfs_init_v4()

From: Bryan Schumaker <[email protected]>

And split them out of the generic client into their own file.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Makefile | 7 +++++-
fs/nfs/nfs4_fs.h | 15 ++++++++++++
fs/nfs/nfs4super.c | 9 +++++++
fs/nfs/nfs4sysctl.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/nfs/sysctl.c | 26 --------------------
5 files changed, 98 insertions(+), 27 deletions(-)
create mode 100644 fs/nfs/nfs4sysctl.c

diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 162a699..4a78e76 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -17,7 +17,12 @@ 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
+
+ifeq ($(CONFIG_SYSCTL), y)
+nfs-y += sysctl.o
+nfs-$(CONFIG_NFS_V4) += nfs4sysctl.o
+endif
+
nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o

obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 1a6ed3f..b508fef 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -368,6 +368,21 @@ extern const nfs4_stateid zero_stateid;
int init_nfs_v4(void);
void exit_nfs_v4(void);

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

diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 366e414..70c394e 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -3,6 +3,8 @@
*/
#include <linux/init.h>
#include <linux/nfs_idmap.h>
+#include <linux/nfs_fs.h>
+#include "nfs4_fs.h"

int __init init_nfs_v4(void)
{
@@ -12,12 +14,19 @@ int __init init_nfs_v4(void)
if (err)
goto out;

+ err = nfs4_register_sysctl();
+ if (err)
+ goto out1;
+
return 0;
+out1:
+ nfs_idmap_quit();
out:
return err;
}

void __exit exit_nfs_v4(void)
{
+ nfs4_unregister_sysctl();
nfs_idmap_quit();
}
diff --git a/fs/nfs/nfs4sysctl.c b/fs/nfs/nfs4sysctl.c
new file mode 100644
index 0000000..5729bc8
--- /dev/null
+++ b/fs/nfs/nfs4sysctl.c
@@ -0,0 +1,68 @@
+/*
+ * linux/fs/nfs/nfs4sysctl.c
+ *
+ * Sysctl interface to NFS v4 parameters
+ *
+ * Copyright (c) 2006 Trond Myklebust <[email protected]>
+ */
+#include <linux/sysctl.h>
+#include <linux/nfs_idmap.h>
+#include <linux/nfs_fs.h>
+
+#include "callback.h"
+
+static const int nfs_set_port_min = 0;
+static const int nfs_set_port_max = 65535;
+static struct ctl_table_header *nfs4_callback_sysctl_table;
+
+static ctl_table nfs4_cb_sysctls[] = {
+ {
+ .procname = "nfs_callback_tcpport",
+ .data = &nfs_callback_set_tcpport,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = (int *)&nfs_set_port_min,
+ .extra2 = (int *)&nfs_set_port_max,
+ },
+ {
+ .procname = "idmap_cache_timeout",
+ .data = &nfs_idmap_cache_timeout,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_jiffies,
+ },
+ { }
+};
+
+static ctl_table nfs4_cb_sysctl_dir[] = {
+ {
+ .procname = "nfs",
+ .mode = 0555,
+ .child = nfs4_cb_sysctls,
+ },
+ { }
+};
+
+static ctl_table nfs4_cb_sysctl_root[] = {
+ {
+ .procname = "fs",
+ .mode = 0555,
+ .child = nfs4_cb_sysctl_dir,
+ },
+ { }
+};
+
+int nfs4_register_sysctl(void)
+{
+ nfs4_callback_sysctl_table = register_sysctl_table(nfs4_cb_sysctl_root);
+ if (nfs4_callback_sysctl_table == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+void nfs4_unregister_sysctl(void)
+{
+ 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 ad4d2e7..6b3f253 100644
--- a/fs/nfs/sysctl.c
+++ b/fs/nfs/sysctl.c
@@ -9,37 +9,11 @@
#include <linux/fs.h>
#include <linux/sysctl.h>
#include <linux/module.h>
-#include <linux/nfs4.h>
-#include <linux/nfs_idmap.h>
#include <linux/nfs_fs.h>

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

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


2012-07-16 20:39:26

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v2 03/12] NFS: Split out NFS v4 inode operations

From: Bryan Schumaker <[email protected]>

The NFS v4 file inode operations are already already in nfs4proc.c, so
this patch just needs to move the directory operations to the same file.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/dir.c | 33 +++------------------------------
fs/nfs/nfs4_fs.h | 5 ++++-
fs/nfs/nfs4proc.c | 20 ++++++++++++++++++++
3 files changed, 27 insertions(+), 31 deletions(-)

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index e75f2aa..d49f1b9 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -63,33 +63,6 @@ const struct address_space_operations nfs_dir_aops = {
.freepage = nfs_readdir_clear_array,
};

-#ifdef CONFIG_NFS_V4
-
-static int nfs_atomic_open(struct inode *, struct dentry *,
- struct file *, unsigned, umode_t,
- int *);
-const struct inode_operations nfs4_dir_inode_operations = {
- .create = nfs_create,
- .lookup = nfs_lookup,
- .atomic_open = nfs_atomic_open,
- .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,
- .getxattr = generic_getxattr,
- .setxattr = generic_setxattr,
- .listxattr = generic_listxattr,
- .removexattr = generic_removexattr,
-};
-
-#endif /* CONFIG_NFS_V4 */
-
static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir, struct rpc_cred *cred)
{
struct nfs_open_dir_context *ctx;
@@ -1352,9 +1325,9 @@ out:
return err;
}

-static int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
- struct file *file, unsigned open_flags,
- umode_t mode, int *opened)
+int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
+ struct file *file, unsigned open_flags,
+ umode_t mode, int *opened)
{
struct nfs_open_context *ctx;
struct dentry *res;
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 3696ca7..e2c4c72 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -200,7 +200,10 @@ struct nfs4_state_maintenance_ops {
};

extern const struct dentry_operations nfs4_dentry_operations;
-extern const struct inode_operations nfs4_dir_inode_operations;
+
+/* dir.c */
+int nfs_atomic_open(struct inode *, struct dentry *, struct file *,
+ unsigned, umode_t, int *);

/* write.c */
int nfs4_write_inode(struct inode *, struct writeback_control *);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 80bb505..689cb43 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -6813,6 +6813,26 @@ const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = {
#endif
};

+const struct inode_operations nfs4_dir_inode_operations = {
+ .create = nfs_create,
+ .lookup = nfs_lookup,
+ .atomic_open = nfs_atomic_open,
+ .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,
+ .getxattr = generic_getxattr,
+ .setxattr = generic_setxattr,
+ .listxattr = generic_listxattr,
+ .removexattr = generic_removexattr,
+};
+
static const struct inode_operations nfs4_file_inode_operations = {
.permission = nfs_permission,
.getattr = nfs_getattr,
--
1.7.11.2


2012-07-16 20:39:29

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v2 07/12] NFS: Move the v4 getroot code to nfs4getroot.c

From: Bryan Schumaker <[email protected]>

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

diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index e882a38..ec13afe 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -15,7 +15,7 @@ nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
nfs4super.o nfs4file.o delegation.o idmap.o \
callback.o callback_xdr.o callback_proc.o \
- nfs4namespace.o
+ nfs4namespace.o nfs4getroot.o
nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o

ifeq ($(CONFIG_SYSCTL), y)
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index a67990f..4654ced 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -23,21 +23,15 @@
#include <linux/sunrpc/stats.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_mount.h>
-#include <linux/nfs4_mount.h>
#include <linux/lockd/bind.h>
#include <linux/seq_file.h>
#include <linux/mount.h>
-#include <linux/nfs_idmap.h>
#include <linux/vfs.h>
#include <linux/namei.h>
#include <linux/security.h>

#include <asm/uaccess.h>

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

/*
@@ -135,47 +129,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 = nfs4_proc_get_rootfh(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;
-}
-
-#endif /* CONFIG_NFS_V4 */
diff --git a/fs/nfs/nfs4getroot.c b/fs/nfs/nfs4getroot.c
new file mode 100644
index 0000000..6a83780
--- /dev/null
+++ b/fs/nfs/nfs4getroot.c
@@ -0,0 +1,49 @@
+/*
+* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+* Written by David Howells ([email protected])
+*/
+
+#include <linux/nfs_fs.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 = nfs4_proc_get_rootfh(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;
+}
--
1.7.11.2


2012-07-16 20:39:25

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v2 02/12] NFS: Split out NFS v3 inode operations

From: Bryan Schumaker <[email protected]>

This patch moves the NFS v3 file and directory inode functions into
files that are only compiled whet CONFIG_NFS_V3 is enabled.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/dir.c | 21 ---------------------
fs/nfs/file.c | 12 ------------
fs/nfs/nfs3proc.c | 29 +++++++++++++++++++++++++++++
include/linux/nfs_fs.h | 6 ------
4 files changed, 29 insertions(+), 39 deletions(-)

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 9ae329d..e75f2aa 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -63,27 +63,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 int nfs_atomic_open(struct inode *, struct dentry *,
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 7da8745..7623917 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -41,18 +41,6 @@

static const struct vm_operations_struct nfs_file_vm_ops;

-#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/nfs3proc.c b/fs/nfs/nfs3proc.c
index f580358..65d23eb 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -888,6 +888,35 @@ static int nfs3_return_delegation(struct inode *inode)
return 0;
}

+static 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 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 nfs_rpc_ops nfs_v3_clientops = {
.version = 3, /* protocol version */
.dentry_ops = &nfs_dentry_operations,
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 6c38bc9..4b6043c 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -427,9 +427,6 @@ extern __be32 root_nfs_parse_addr(char *name); /*__init*/
/*
* linux/fs/nfs/file.c
*/
-#ifdef CONFIG_NFS_V3
-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
extern const struct file_operations nfs4_file_operations;
@@ -484,9 +481,6 @@ extern ssize_t nfs_file_direct_write(struct kiocb *iocb,
/*
* linux/fs/nfs/dir.c
*/
-#ifdef CONFIG_NFS_V3
-extern const struct inode_operations nfs3_dir_inode_operations;
-#endif /* CONFIG_NFS_V3 */
extern const struct file_operations nfs_dir_operations;
extern const struct dentry_operations nfs_dentry_operations;

--
1.7.11.2


2012-07-16 20:39:28

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v2 06/12] NFS: Split out NFS v4 file operations

From: Bryan Schumaker <[email protected]>

This patch moves the NFS v4 file functions into a new file that is only
compiled when CONFIG_NFS_V4 is enabled.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Makefile | 2 +-
fs/nfs/file.c | 151 ++++++------------------------------------------------
fs/nfs/internal.h | 17 ++++++
fs/nfs/nfs4file.c | 126 +++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 160 insertions(+), 136 deletions(-)
create mode 100644 fs/nfs/nfs4file.c

diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 4a78e76..e882a38 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -13,7 +13,7 @@ nfs-$(CONFIG_NFS_V2) += proc.o nfs2xdr.o
nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o
nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
- nfs4super.o delegation.o idmap.o \
+ nfs4super.o nfs4file.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/file.c b/fs/nfs/file.c
index 7623917..70d124a 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -35,7 +35,6 @@
#include "internal.h"
#include "iostat.h"
#include "fscache.h"
-#include "pnfs.h"

#define NFSDBG_FACILITY NFSDBG_FILE

@@ -46,7 +45,7 @@ static const struct vm_operations_struct nfs_file_vm_ops;
# define IS_SWAPFILE(inode) (0)
#endif

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

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

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

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

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

-static int
+int
nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
{
struct dentry *dentry = file->f_path.dentry;
@@ -246,7 +245,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
* nfs_file_write() that a write error occurred, and hence cause it to
* fall back to doing a synchronous write.
*/
-static int
+int
nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync)
{
struct dentry *dentry = file->f_path.dentry;
@@ -561,8 +560,8 @@ static int nfs_need_sync_write(struct file *filp, struct inode *inode)
return 0;
}

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

-static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
- struct file *filp, loff_t *ppos,
- size_t count, unsigned int flags)
+ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
+ struct file *filp, loff_t *ppos,
+ size_t count, unsigned int flags)
{
struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
@@ -767,7 +766,7 @@ out:
/*
* Lock a (portion of) a file
*/
-static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
+int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
{
struct inode *inode = filp->f_mapping->host;
int ret = -ENOLCK;
@@ -807,7 +806,7 @@ out_err:
/*
* Lock a (portion of) a file
*/
-static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
+int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
{
struct inode *inode = filp->f_mapping->host;
int is_local = 0;
@@ -837,7 +836,7 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
* There is no protocol support for leases, so we have no way to implement
* them correctly in the face of opens by other clients.
*/
-static int nfs_setlease(struct file *file, long arg, struct file_lock **fl)
+int nfs_setlease(struct file *file, long arg, struct file_lock **fl)
{
dprintk("NFS: setlease(%s/%s, arg=%ld)\n",
file->f_path.dentry->d_parent->d_name.name,
@@ -863,121 +862,3 @@ const struct file_operations nfs_file_operations = {
.check_flags = nfs_check_flags,
.setlease = nfs_setlease,
};
-
-#ifdef CONFIG_NFS_V4
-static int
-nfs4_file_open(struct inode *inode, struct file *filp)
-{
- struct nfs_open_context *ctx;
- struct dentry *dentry = filp->f_path.dentry;
- struct dentry *parent = NULL;
- struct inode *dir;
- unsigned openflags = filp->f_flags;
- struct iattr attr;
- int err;
-
- BUG_ON(inode != dentry->d_inode);
- /*
- * If no cached dentry exists or if it's negative, NFSv4 handled the
- * opens in ->lookup() or ->create().
- *
- * We only get this far for a cached positive dentry. We skipped
- * revalidation, so handle it here by dropping the dentry and returning
- * -EOPENSTALE. The VFS will retry the lookup/create/open.
- */
-
- dprintk("NFS: open file(%s/%s)\n",
- dentry->d_parent->d_name.name,
- dentry->d_name.name);
-
- if ((openflags & O_ACCMODE) == 3)
- openflags--;
-
- /* We can't create new files here */
- openflags &= ~(O_CREAT|O_EXCL);
-
- parent = dget_parent(dentry);
- dir = parent->d_inode;
-
- ctx = alloc_nfs_open_context(filp->f_path.dentry, filp->f_mode);
- err = PTR_ERR(ctx);
- if (IS_ERR(ctx))
- goto out;
-
- attr.ia_valid = ATTR_OPEN;
- if (openflags & O_TRUNC) {
- attr.ia_valid |= ATTR_SIZE;
- attr.ia_size = 0;
- nfs_wb_all(inode);
- }
-
- inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr);
- if (IS_ERR(inode)) {
- err = PTR_ERR(inode);
- switch (err) {
- case -EPERM:
- case -EACCES:
- case -EDQUOT:
- case -ENOSPC:
- case -EROFS:
- goto out_put_ctx;
- default:
- goto out_drop;
- }
- }
- iput(inode);
- if (inode != dentry->d_inode)
- goto out_drop;
-
- nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
- nfs_file_set_open_context(filp, ctx);
- err = 0;
-
-out_put_ctx:
- put_nfs_open_context(ctx);
-out:
- dput(parent);
- return err;
-
-out_drop:
- d_drop(dentry);
- err = -EOPENSTALE;
- goto out_put_ctx;
-}
-
-static int
-nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
-{
- int ret;
- struct inode *inode = file->f_path.dentry->d_inode;
-
- ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
- mutex_lock(&inode->i_mutex);
- ret = nfs_file_fsync_commit(file, start, end, datasync);
- if (!ret && !datasync)
- /* application has asked for meta-data sync */
- ret = pnfs_layoutcommit_inode(inode, true);
- mutex_unlock(&inode->i_mutex);
-
- return ret;
-}
-
-const struct file_operations nfs4_file_operations = {
- .llseek = nfs_file_llseek,
- .read = do_sync_read,
- .write = do_sync_write,
- .aio_read = nfs_file_read,
- .aio_write = nfs_file_write,
- .mmap = nfs_file_mmap,
- .open = nfs4_file_open,
- .flush = nfs_file_flush,
- .release = nfs_file_release,
- .fsync = nfs4_file_fsync,
- .lock = nfs_lock,
- .flock = nfs_flock,
- .splice_read = nfs_file_splice_read,
- .splice_write = nfs_file_splice_write,
- .check_flags = nfs_check_flags,
- .setlease = nfs_setlease,
-};
-#endif /* CONFIG_NFS_V4 */
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 35a8ffe..ca7200a 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -257,6 +257,23 @@ int nfs_link(struct dentry *, struct inode *, struct dentry *);
int nfs_mknod(struct inode *, struct dentry *, umode_t, dev_t);
int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);

+/* file.c */
+int nfs_file_fsync_commit(struct file *, loff_t, loff_t, int);
+loff_t nfs_file_llseek(struct file *, loff_t, int);
+int nfs_file_flush(struct file *, fl_owner_t);
+ssize_t nfs_file_read(struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ssize_t nfs_file_splice_read(struct file *, loff_t *, struct pipe_inode_info *,
+ size_t, unsigned int);
+int nfs_file_mmap(struct file *, struct vm_area_struct *);
+ssize_t nfs_file_write(struct kiocb *, const struct iovec *, unsigned long, loff_t);
+int nfs_file_release(struct inode *, struct file *);
+int nfs_lock(struct file *, int, struct file_lock *);
+int nfs_flock(struct file *, int, struct file_lock *);
+ssize_t nfs_file_splice_write(struct pipe_inode_info *, struct file *, loff_t *,
+ size_t, unsigned int);
+int nfs_check_flags(int);
+int nfs_setlease(struct file *, long, struct file_lock **);
+
/* inode.c */
extern struct workqueue_struct *nfsiod_workqueue;
extern struct inode *nfs_alloc_inode(struct super_block *sb);
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
new file mode 100644
index 0000000..acb65e7
--- /dev/null
+++ b/fs/nfs/nfs4file.c
@@ -0,0 +1,126 @@
+/*
+ * linux/fs/nfs/file.c
+ *
+ * Copyright (C) 1992 Rick Sladkey
+ */
+#include <linux/nfs_fs.h>
+#include "internal.h"
+#include "pnfs.h"
+
+#define NFSDBG_FACILITY NFSDBG_FILE
+
+static int
+nfs4_file_open(struct inode *inode, struct file *filp)
+{
+ struct nfs_open_context *ctx;
+ struct dentry *dentry = filp->f_path.dentry;
+ struct dentry *parent = NULL;
+ struct inode *dir;
+ unsigned openflags = filp->f_flags;
+ struct iattr attr;
+ int err;
+
+ BUG_ON(inode != dentry->d_inode);
+ /*
+ * If no cached dentry exists or if it's negative, NFSv4 handled the
+ * opens in ->lookup() or ->create().
+ *
+ * We only get this far for a cached positive dentry. We skipped
+ * revalidation, so handle it here by dropping the dentry and returning
+ * -EOPENSTALE. The VFS will retry the lookup/create/open.
+ */
+
+ dprintk("NFS: open file(%s/%s)\n",
+ dentry->d_parent->d_name.name,
+ dentry->d_name.name);
+
+ if ((openflags & O_ACCMODE) == 3)
+ openflags--;
+
+ /* We can't create new files here */
+ openflags &= ~(O_CREAT|O_EXCL);
+
+ parent = dget_parent(dentry);
+ dir = parent->d_inode;
+
+ ctx = alloc_nfs_open_context(filp->f_path.dentry, filp->f_mode);
+ err = PTR_ERR(ctx);
+ if (IS_ERR(ctx))
+ goto out;
+
+ attr.ia_valid = ATTR_OPEN;
+ if (openflags & O_TRUNC) {
+ attr.ia_valid |= ATTR_SIZE;
+ attr.ia_size = 0;
+ nfs_wb_all(inode);
+ }
+
+ inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ switch (err) {
+ case -EPERM:
+ case -EACCES:
+ case -EDQUOT:
+ case -ENOSPC:
+ case -EROFS:
+ goto out_put_ctx;
+ default:
+ goto out_drop;
+ }
+ }
+ iput(inode);
+ if (inode != dentry->d_inode)
+ goto out_drop;
+
+ nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+ nfs_file_set_open_context(filp, ctx);
+ err = 0;
+
+out_put_ctx:
+ put_nfs_open_context(ctx);
+out:
+ dput(parent);
+ return err;
+
+out_drop:
+ d_drop(dentry);
+ err = -EOPENSTALE;
+ goto out_put_ctx;
+}
+
+static int
+nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
+{
+ int ret;
+ struct inode *inode = file->f_path.dentry->d_inode;
+
+ ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+ mutex_lock(&inode->i_mutex);
+ ret = nfs_file_fsync_commit(file, start, end, datasync);
+ if (!ret && !datasync)
+ /* application has asked for meta-data sync */
+ ret = pnfs_layoutcommit_inode(inode, true);
+ mutex_unlock(&inode->i_mutex);
+
+ return ret;
+}
+
+const struct file_operations nfs4_file_operations = {
+ .llseek = nfs_file_llseek,
+ .read = do_sync_read,
+ .write = do_sync_write,
+ .aio_read = nfs_file_read,
+ .aio_write = nfs_file_write,
+ .mmap = nfs_file_mmap,
+ .open = nfs4_file_open,
+ .flush = nfs_file_flush,
+ .release = nfs_file_release,
+ .fsync = nfs4_file_fsync,
+ .lock = nfs_lock,
+ .flock = nfs_flock,
+ .splice_read = nfs_file_splice_read,
+ .splice_write = nfs_file_splice_write,
+ .check_flags = nfs_check_flags,
+ .setlease = nfs_setlease,
+};
--
1.7.11.2


2012-07-16 20:39:30

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v2 08/12] NFS: Initialize the NFS v4 client from init_nfs_v4()

From: Bryan Schumaker <[email protected]>

And split these functions out of the generic client into a v4 specific
file.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Makefile | 2 +-
fs/nfs/client.c | 137 ++-----------------------------------------------
fs/nfs/internal.h | 1 +
fs/nfs/nfs4client.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 149 insertions(+), 135 deletions(-)
create mode 100644 fs/nfs/nfs4client.c

diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index ec13afe..0b96c20 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -15,7 +15,7 @@ nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
nfs4super.o nfs4file.o delegation.o idmap.o \
callback.o callback_xdr.o callback_proc.o \
- nfs4namespace.o nfs4getroot.o
+ nfs4namespace.o nfs4getroot.o nfs4client.o
nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o

ifeq ($(CONFIG_SYSCTL), y)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 254719c..5664c7b 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -662,9 +662,9 @@ static void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
/*
* Create an RPC client handle
*/
-static int nfs_create_rpc_client(struct nfs_client *clp,
- const struct rpc_timeout *timeparms,
- rpc_authflavor_t flavor)
+int nfs_create_rpc_client(struct nfs_client *clp,
+ const struct rpc_timeout *timeparms,
+ rpc_authflavor_t flavor)
{
struct rpc_clnt *clnt = NULL;
struct rpc_create_args args = {
@@ -1305,137 +1305,6 @@ nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr,
#endif /* CONFIG_NFS_V4_1 */

/*
- * Initialize the NFS4 callback service
- */
-static int nfs4_init_callback(struct nfs_client *clp)
-{
- int error;
-
- if (clp->rpc_ops->version == 4) {
- struct rpc_xprt *xprt;
-
- xprt = rcu_dereference_raw(clp->cl_rpcclient->cl_xprt);
-
- if (nfs4_has_session(clp)) {
- error = xprt_setup_backchannel(xprt,
- NFS41_BC_MIN_CALLBACKS);
- if (error < 0)
- return error;
- }
-
- error = nfs_callback_up(clp->cl_mvops->minor_version, xprt);
- if (error < 0) {
- dprintk("%s: failed to start callback. Error = %d\n",
- __func__, error);
- return error;
- }
- __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
- }
- return 0;
-}
-
-/*
- * Initialize the minor version specific parts of an NFS4 client record
- */
-static int nfs4_init_client_minor_version(struct nfs_client *clp)
-{
-#if defined(CONFIG_NFS_V4_1)
- if (clp->cl_mvops->minor_version) {
- struct nfs4_session *session = NULL;
- /*
- * Create the session and mark it expired.
- * When a SEQUENCE operation encounters the expired session
- * it will do session recovery to initialize it.
- */
- session = nfs4_alloc_session(clp);
- if (!session)
- return -ENOMEM;
-
- clp->cl_session = session;
- /*
- * The create session reply races with the server back
- * channel probe. Mark the client NFS_CS_SESSION_INITING
- * so that the client back channel can find the
- * nfs_client struct
- */
- nfs_mark_client_ready(clp, NFS_CS_SESSION_INITING);
- }
-#endif /* CONFIG_NFS_V4_1 */
-
- return nfs4_init_callback(clp);
-}
-
-/**
- * nfs4_init_client - Initialise an NFS4 client record
- *
- * @clp: nfs_client to initialise
- * @timeparms: timeout parameters for underlying RPC transport
- * @ip_addr: callback IP address in presentation format
- * @authflavor: authentication flavor for underlying RPC transport
- *
- * Returns pointer to an NFS client, or an ERR_PTR value.
- */
-struct nfs_client *nfs4_init_client(struct nfs_client *clp,
- const struct rpc_timeout *timeparms,
- const char *ip_addr,
- rpc_authflavor_t authflavour)
-{
- char buf[INET6_ADDRSTRLEN + 1];
- int error;
-
- if (clp->cl_cons_state == NFS_CS_READY) {
- /* the client is initialised already */
- dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp);
- return clp;
- }
-
- /* Check NFS protocol revision and initialize RPC op vector */
- clp->rpc_ops = &nfs_v4_clientops;
-
- __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags);
- error = nfs_create_rpc_client(clp, timeparms, authflavour);
- if (error < 0)
- goto error;
-
- /* If no clientaddr= option was specified, find a usable cb address */
- if (ip_addr == NULL) {
- struct sockaddr_storage cb_addr;
- struct sockaddr *sap = (struct sockaddr *)&cb_addr;
-
- error = rpc_localaddr(clp->cl_rpcclient, sap, sizeof(cb_addr));
- if (error < 0)
- goto error;
- error = rpc_ntop(sap, buf, sizeof(buf));
- if (error < 0)
- goto error;
- ip_addr = (const char *)buf;
- }
- strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
-
- error = nfs_idmap_new(clp);
- if (error < 0) {
- dprintk("%s: failed to create idmapper. Error = %d\n",
- __func__, error);
- goto error;
- }
- __set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
-
- error = nfs4_init_client_minor_version(clp);
- if (error < 0)
- goto error;
-
- if (!nfs4_has_session(clp))
- nfs_mark_client_ready(clp, NFS_CS_READY);
- return clp;
-
-error:
- nfs_mark_client_ready(clp, error);
- nfs_put_client(clp);
- dprintk("<-- nfs4_init_client() = xerror %d\n", error);
- return ERR_PTR(error);
-}
-
-/*
* Set up an NFS4 client
*/
static int nfs4_set_client(struct nfs_server *server,
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index ca7200a..10df28d 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -149,6 +149,7 @@ extern void nfs_umount(const struct nfs_mount_request *info);
extern const struct rpc_program nfs_program;
extern void nfs_clients_init(struct net *net);
extern struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *);
+int nfs_create_rpc_client(struct nfs_client *, const struct rpc_timeout *, rpc_authflavor_t);

extern void nfs_cleanup_cb_ident_idr(struct net *);
extern void nfs_put_client(struct nfs_client *);
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
new file mode 100644
index 0000000..c5234b5
--- /dev/null
+++ b/fs/nfs/nfs4client.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells ([email protected])
+ */
+#include <linux/nfs_fs.h>
+#include <linux/nfs_idmap.h>
+#include <linux/sunrpc/auth.h>
+#include <linux/sunrpc/xprt.h>
+#include <linux/sunrpc/bc_xprt.h>
+#include "internal.h"
+#include "callback.h"
+
+#define NFSDBG_FACILITY NFSDBG_CLIENT
+
+/*
+ * Initialize the NFS4 callback service
+ */
+static int nfs4_init_callback(struct nfs_client *clp)
+{
+ int error;
+
+ if (clp->rpc_ops->version == 4) {
+ struct rpc_xprt *xprt;
+
+ xprt = rcu_dereference_raw(clp->cl_rpcclient->cl_xprt);
+
+ if (nfs4_has_session(clp)) {
+ error = xprt_setup_backchannel(xprt,
+ NFS41_BC_MIN_CALLBACKS);
+ if (error < 0)
+ return error;
+ }
+
+ error = nfs_callback_up(clp->cl_mvops->minor_version, xprt);
+ if (error < 0) {
+ dprintk("%s: failed to start callback. Error = %d\n",
+ __func__, error);
+ return error;
+ }
+ __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
+ }
+ return 0;
+}
+
+/*
+ * Initialize the minor version specific parts of an NFS4 client record
+ */
+static int nfs4_init_client_minor_version(struct nfs_client *clp)
+{
+#if defined(CONFIG_NFS_V4_1)
+ if (clp->cl_mvops->minor_version) {
+ struct nfs4_session *session = NULL;
+ /*
+ * Create the session and mark it expired.
+ * When a SEQUENCE operation encounters the expired session
+ * it will do session recovery to initialize it.
+ */
+ session = nfs4_alloc_session(clp);
+ if (!session)
+ return -ENOMEM;
+
+ clp->cl_session = session;
+ /*
+ * The create session reply races with the server back
+ * channel probe. Mark the client NFS_CS_SESSION_INITING
+ * so that the client back channel can find the
+ * nfs_client struct
+ */
+ nfs_mark_client_ready(clp, NFS_CS_SESSION_INITING);
+ }
+#endif /* CONFIG_NFS_V4_1 */
+
+ return nfs4_init_callback(clp);
+}
+
+/**
+ * nfs4_init_client - Initialise an NFS4 client record
+ *
+ * @clp: nfs_client to initialise
+ * @timeparms: timeout parameters for underlying RPC transport
+ * @ip_addr: callback IP address in presentation format
+ * @authflavor: authentication flavor for underlying RPC transport
+ *
+ * Returns pointer to an NFS client, or an ERR_PTR value.
+ */
+struct nfs_client *nfs4_init_client(struct nfs_client *clp,
+ const struct rpc_timeout *timeparms,
+ const char *ip_addr,
+ rpc_authflavor_t authflavour)
+{
+ char buf[INET6_ADDRSTRLEN + 1];
+ int error;
+
+ if (clp->cl_cons_state == NFS_CS_READY) {
+ /* the client is initialised already */
+ dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp);
+ return clp;
+ }
+
+ /* Check NFS protocol revision and initialize RPC op vector */
+ clp->rpc_ops = &nfs_v4_clientops;
+
+ __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags);
+ error = nfs_create_rpc_client(clp, timeparms, authflavour);
+ if (error < 0)
+ goto error;
+
+ /* If no clientaddr= option was specified, find a usable cb address */
+ if (ip_addr == NULL) {
+ struct sockaddr_storage cb_addr;
+ struct sockaddr *sap = (struct sockaddr *)&cb_addr;
+
+ error = rpc_localaddr(clp->cl_rpcclient, sap, sizeof(cb_addr));
+ if (error < 0)
+ goto error;
+ error = rpc_ntop(sap, buf, sizeof(buf));
+ if (error < 0)
+ goto error;
+ ip_addr = (const char *)buf;
+ }
+ strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
+
+ error = nfs_idmap_new(clp);
+ if (error < 0) {
+ dprintk("%s: failed to create idmapper. Error = %d\n",
+ __func__, error);
+ goto error;
+ }
+ __set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
+
+ error = nfs4_init_client_minor_version(clp);
+ if (error < 0)
+ goto error;
+
+ if (!nfs4_has_session(clp))
+ nfs_mark_client_ready(clp, NFS_CS_READY);
+ return clp;
+
+error:
+ nfs_mark_client_ready(clp, error);
+ nfs_put_client(clp);
+ dprintk("<-- nfs4_init_client() = xerror %d\n", error);
+ return ERR_PTR(error);
+}
--
1.7.11.2


2012-07-16 20:39:24

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v2 01/12] NFS: Split out NFS v2 inode operations

From: Bryan Schumaker <[email protected]>

This patch moves the NFS v2 file and directory inode functions into
files that are only compiled whet CONFIG_NFS_V2 is enabled.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/dir.c | 43 +++++++++----------------------------------
fs/nfs/file.c | 6 ------
fs/nfs/internal.h | 9 +++++++++
fs/nfs/proc.c | 21 +++++++++++++++++++++
include/linux/nfs_fs.h | 2 --
5 files changed, 39 insertions(+), 42 deletions(-)

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index b713685..9ae329d 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -46,16 +46,6 @@
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 *, unsigned int);
-static int nfs_create(struct inode *, struct dentry *, umode_t, bool);
-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*);
@@ -69,21 +59,6 @@ const struct file_operations nfs_dir_operations = {
.fsync = nfs_fsync_dir,
};

-const struct inode_operations nfs_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,
-};
-
const struct address_space_operations nfs_dir_aops = {
.freepage = nfs_readdir_clear_array,
};
@@ -1270,7 +1245,7 @@ const struct dentry_operations nfs_dentry_operations = {
.d_release = nfs_d_release,
};

-static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
+struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
{
struct dentry *res;
struct dentry *parent;
@@ -1588,7 +1563,7 @@ out_error:
* 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, bool excl)
{
struct iattr attr;
@@ -1613,7 +1588,7 @@ out_err:
/*
* See comments for nfs_proc_create regarding failed operations.
*/
-static int
+int
nfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
{
struct iattr attr;
@@ -1640,7 +1615,7 @@ out_err:
/*
* 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;
@@ -1666,7 +1641,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;

@@ -1725,7 +1700,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;
@@ -1769,7 +1744,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;
@@ -1824,7 +1799,7 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym
return 0;
}

-static int
+int
nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
{
struct inode *inode = old_dentry->d_inode;
@@ -1869,7 +1844,7 @@ 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,
+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;
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 57a22a1..7da8745 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -41,12 +41,6 @@

static const struct vm_operations_struct nfs_file_vm_ops;

-const struct inode_operations nfs_file_inode_operations = {
- .permission = nfs_permission,
- .getattr = nfs_getattr,
- .setattr = nfs_setattr,
-};
-
#ifdef CONFIG_NFS_V3
const struct inode_operations nfs3_file_inode_operations = {
.permission = nfs_permission,
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 7edc172..35a8ffe 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -247,6 +247,15 @@ extern struct nfs_client *nfs_init_client(struct nfs_client *clp,
/* dir.c */
extern int nfs_access_cache_shrinker(struct shrinker *shrink,
struct shrink_control *sc);
+struct dentry *nfs_lookup(struct inode *, struct dentry *, unsigned int);
+int nfs_create(struct inode *, struct dentry *, umode_t, bool);
+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 *);

/* inode.c */
extern struct workqueue_struct *nfsiod_workqueue;
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index c5ed1c0..4d3356af 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -745,6 +745,27 @@ static int nfs_return_delegation(struct inode *inode)
return 0;
}

+static const struct inode_operations nfs_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,
+};
+
+static const struct inode_operations nfs_file_inode_operations = {
+ .permission = nfs_permission,
+ .getattr = nfs_getattr,
+ .setattr = nfs_setattr,
+};
+
const struct nfs_rpc_ops nfs_v2_clientops = {
.version = 2, /* protocol version */
.dentry_ops = &nfs_dentry_operations,
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index b23cfc1..6c38bc9 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -427,7 +427,6 @@ 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
extern const struct inode_operations nfs3_file_inode_operations;
#endif /* CONFIG_NFS_V3 */
@@ -485,7 +484,6 @@ 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
extern const struct inode_operations nfs3_dir_inode_operations;
#endif /* CONFIG_NFS_V3 */
--
1.7.11.2


2012-07-17 19:13:38

by Myklebust, Trond

[permalink] [raw]
Subject: Re: [PATCH v3 04/12] NFS: Create an init_nfs_v4() function

T24gVHVlLCAyMDEyLTA3LTE3IGF0IDE1OjExIC0wNDAwLCBCcnlhbiBTY2h1bWFrZXIgd3JvdGU6
DQo+IFRoaXMgcGF0Y2ggc2hvdWxkIHdvcmsgYmV0dGVyLCB0aGFua3MgRmVuZ2d1YW5nIQ0KPiAN
Cj4gLSBCcnlhbg0KPiANCj4gDQo+IA0KPiBJIHdhbnQgdG8gaW5pdGlhbGl6ZSBhbGwgb2YgTkZT
IHY0IGluIGEgc2luZ2xlIGZ1bmN0aW9uIHRoYXQgd2lsbA0KPiBldmVudHVhbGx5IGJlIHVzZWQg
YXMgdGhlIHY0IG1vZHVsZSBpbml0IGZ1bmN0aW9uLg0KPiANCj4gU2lnbmVkLW9mZi1ieTogQnJ5
YW4gU2NodW1ha2VyIDxianNjaHVtYUBuZXRhcHAuY29tPg0KPiBTaWduZWQtb2ZmLWJ5OiBUcm9u
ZCBNeWtsZWJ1c3QgPFRyb25kLk15a2xlYnVzdEBuZXRhcHAuY29tPg0KPiAtLS0NCj4gdjM6ICBE
b24ndCBkZWNsYXJlIGV4aXRfbmZzX3Y0KCkgYXMgYW4gX19leGl0ICBmdW5jdGlvbg0KDQpQbGVh
c2UgcmVkbyB0aGlzIGFzIGFuIGluY3JlbWVudGFsIHBhdGNoIHRvIHRoZSBmaXJzdCBvbmUuLi4u
DQoNCi0tIA0KVHJvbmQgTXlrbGVidXN0DQpMaW51eCBORlMgY2xpZW50IG1haW50YWluZXINCg0K
TmV0QXBwDQpUcm9uZC5NeWtsZWJ1c3RAbmV0YXBwLmNvbQ0Kd3d3Lm5ldGFwcC5jb20NCg0K

2012-07-16 20:39:26

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v2 04/12] NFS: Create an init_nfs_v4() function

From: Bryan Schumaker <[email protected]>

I want to initialize all of NFS v4 in a single function that will
eventually be used as the v4 module init function.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/Makefile | 2 +-
fs/nfs/inode.c | 67 ++++++++++++++++++++++++++++++------------------------
fs/nfs/nfs4_fs.h | 4 ++++
fs/nfs/nfs4super.c | 23 +++++++++++++++++++
4 files changed, 65 insertions(+), 31 deletions(-)
create mode 100644 fs/nfs/nfs4super.c

diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 7ddd45d..162a699 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -13,7 +13,7 @@ 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 \
- 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/inode.c b/fs/nfs/inode.c
index 28c9ebb..35f7e4b 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -32,7 +32,6 @@
#include <linux/lockd/bind.h>
#include <linux/seq_file.h>
#include <linux/mount.h>
-#include <linux/nfs_idmap.h>
#include <linux/vfs.h>
#include <linux/inet.h>
#include <linux/nfs_xdr.h>
@@ -1628,87 +1627,96 @@ 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;
+ goto out11;

err = register_pernet_subsys(&nfs_net_ops);
if (err < 0)
- goto out8;
+ goto out10;

err = nfs_fscache_register();
if (err < 0)
- goto out7;
+ goto out9;

err = nfsiod_start();
if (err)
- goto out6;
+ goto out8;

err = nfs_fs_proc_init();
if (err)
- goto out5;
+ goto out7;

err = nfs_init_nfspagecache();
if (err)
- goto out4;
+ goto out6;

err = nfs_init_inodecache();
if (err)
- goto out3;
+ goto out5;

err = nfs_init_readpagecache();
if (err)
- goto out2;
+ goto out4;

err = nfs_init_writepagecache();
if (err)
- goto out1;
+ goto out3;

err = nfs_init_directcache();
if (err)
- goto out0;
+ goto out2;

#ifdef CONFIG_PROC_FS
rpc_proc_register(&init_net, &nfs_rpcstat);
#endif
+
+#ifdef CONFIG_NFS_V4
+ err = init_nfs_v4();
+ if (err)
+ goto out1;
+#endif
+
if ((err = register_nfs_fs()) != 0)
- goto out;
+ goto out0;
+
return 0;
-out:
+out0:
+#ifdef CONFIG_NFS_V4
+ exit_nfs_v4();
+out1:
+#endif
#ifdef CONFIG_PROC_FS
rpc_proc_unregister(&init_net, "nfs");
#endif
nfs_destroy_directcache();
-out0:
- nfs_destroy_writepagecache();
-out1:
- nfs_destroy_readpagecache();
out2:
- nfs_destroy_inodecache();
+ nfs_destroy_writepagecache();
out3:
- nfs_destroy_nfspagecache();
+ nfs_destroy_readpagecache();
out4:
- nfs_fs_proc_exit();
+ nfs_destroy_inodecache();
out5:
- nfsiod_stop();
+ nfs_destroy_nfspagecache();
out6:
- nfs_fscache_unregister();
+ nfs_fs_proc_exit();
out7:
- unregister_pernet_subsys(&nfs_net_ops);
+ nfsiod_stop();
out8:
- nfs_dns_resolver_destroy();
+ nfs_fscache_unregister();
out9:
- nfs_idmap_quit();
+ unregister_pernet_subsys(&nfs_net_ops);
out10:
+ nfs_dns_resolver_destroy();
+out11:
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();
@@ -1717,7 +1725,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/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index e2c4c72..1a6ed3f 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -364,6 +364,10 @@ extern void nfs4_free_lock_state(struct nfs_server *server, struct nfs4_lock_sta

extern const nfs4_stateid zero_stateid;

+/* nfs4super.c */
+int init_nfs_v4(void);
+void exit_nfs_v4(void);
+
/* nfs4xdr.c */
extern struct rpc_procinfo nfs4_procedures[];

diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
new file mode 100644
index 0000000..366e414
--- /dev/null
+++ b/fs/nfs/nfs4super.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2012 Bryan Schumaker <[email protected]>
+ */
+#include <linux/init.h>
+#include <linux/nfs_idmap.h>
+
+int __init init_nfs_v4(void)
+{
+ int err;
+
+ err = nfs_idmap_init();
+ if (err)
+ goto out;
+
+ return 0;
+out:
+ return err;
+}
+
+void __exit exit_nfs_v4(void)
+{
+ nfs_idmap_quit();
+}
--
1.7.11.2


2012-07-16 20:39:32

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v2 10/12] NFS: Create a single nfs_clone_super() function

From: Bryan Schumaker <[email protected]>

v2 and v3 shared a function for this, but v4 implemented something only
slightly different. Might as well share code whenever possible...

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

diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 9bad4e7..ca3c0e8 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2218,7 +2218,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,
struct nfs_mount_info *mount_info)
@@ -2229,16 +2229,17 @@ 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);
}

@@ -2580,27 +2581,6 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,
#ifdef CONFIG_NFS_V4

/*
- * Finish setting up a cloned NFS4 superblock
- */
-static void nfs4_clone_super(struct super_block *sb,
- struct nfs_mount_info *mount_info)
-{
- const struct super_block *old_sb = mount_info->cloned->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,
@@ -2883,7 +2863,7 @@ nfs4_xdev_mount(struct file_system_type *fs_type, int flags,
const char *dev_name, void *raw_data)
{
struct nfs_mount_info mount_info = {
- .fill_super = nfs4_clone_super,
+ .fill_super = nfs_clone_super,
.set_security = nfs_clone_sb_security,
.cloned = raw_data,
};
--
1.7.11.2


2012-07-16 20:39:33

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v2 11/12] NFS: Split out the NFS v4 filesystem types

From: Bryan Schumaker <[email protected]>

This allows me to move the v4 mounting and unmounting functions out of
the generic client and into a file that is only compiled when CONFIG_NFS_V4
is enabled.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/internal.h | 29 ++++
fs/nfs/nfs4_fs.h | 2 +
fs/nfs/nfs4super.c | 328 ++++++++++++++++++++++++++++++++++++++++++++
fs/nfs/super.c | 395 +++--------------------------------------------------
4 files changed, 381 insertions(+), 373 deletions(-)

diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index b4a3570..cfafd13 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -153,6 +153,14 @@ struct nfs_mount_request {
struct net *net;
};

+struct nfs_mount_info {
+ void (*fill_super)(struct super_block *, struct nfs_mount_info *);
+ int (*set_security)(struct super_block *, struct dentry *, struct nfs_mount_info *);
+ struct nfs_parsed_mount_data *parsed;
+ struct nfs_clone_mount *cloned;
+ struct nfs_fh *mntfh;
+};
+
extern int nfs_mount(struct nfs_mount_request *info);
extern void nfs_umount(const struct nfs_mount_request *info);

@@ -318,6 +326,16 @@ extern struct file_system_type nfs_xdev_fs_type;
extern struct file_system_type nfs4_xdev_fs_type;
extern struct file_system_type nfs4_referral_fs_type;
#endif
+void nfs_initialise_sb(struct super_block *);
+int nfs_set_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *);
+int nfs_clone_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *);
+struct dentry *nfs_fs_mount_common(struct file_system_type *, struct nfs_server *,
+ int, const char *, struct nfs_mount_info *);
+struct dentry *nfs_fs_mount(struct file_system_type *, int, const char *, void *);
+struct dentry * nfs_xdev_mount_common(struct file_system_type *, int,
+ const char *, struct nfs_mount_info *);
+void nfs_kill_super(struct super_block *);
+void nfs_fill_super(struct super_block *, struct nfs_mount_info *);

extern struct rpc_stat nfs_rpcstat;

@@ -364,6 +382,17 @@ extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);
extern void nfs_readdata_release(struct nfs_read_data *rdata);

+/* super.c */
+void nfs_clone_super(struct super_block *, struct nfs_mount_info *);
+void nfs_umount_begin(struct super_block *);
+int nfs_statfs(struct dentry *, struct kstatfs *);
+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 *);
+void nfs_put_super(struct super_block *);
+int nfs_remount(struct super_block *sb, int *flags, char *raw_data);
+
/* write.c */
extern void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
struct inode *inode, int ioflags,
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index b508fef..b1ecacd 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -365,6 +365,8 @@ extern void nfs4_free_lock_state(struct nfs_server *server, struct nfs4_lock_sta
extern const nfs4_stateid zero_stateid;

/* nfs4super.c */
+struct nfs_mount_info;
+struct dentry *nfs4_try_mount(int, const char *, struct nfs_mount_info *);
int init_nfs_v4(void);
void exit_nfs_v4(void);

diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 70c394e..2af2691 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -2,10 +2,331 @@
* Copyright (c) 2012 Bryan Schumaker <[email protected]>
*/
#include <linux/init.h>
+#include <linux/module.h>
#include <linux/nfs_idmap.h>
+#include <linux/nfs4_mount.h>
#include <linux/nfs_fs.h>
+#include "internal.h"
#include "nfs4_fs.h"

+#define NFSDBG_FACILITY NFSDBG_VFS
+
+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 struct file_system_type nfs4_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "nfs4",
+ .mount = nfs_fs_mount,
+ .kill_sb = nfs_kill_super,
+ .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+};
+
+static struct file_system_type nfs4_remote_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "nfs4",
+ .mount = nfs4_remote_mount,
+ .kill_sb = nfs_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 = nfs4_xdev_mount,
+ .kill_sb = nfs_kill_super,
+ .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+};
+
+static struct file_system_type nfs4_remote_referral_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "nfs4",
+ .mount = nfs4_remote_referral_mount,
+ .kill_sb = nfs_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 = nfs_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 = nfs4_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,
+ struct nfs_mount_info *mount_info)
+{
+ 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 *info)
+{
+ struct nfs_mount_info *mount_info = info;
+ struct nfs_server *server;
+ struct dentry *mntroot = ERR_PTR(-ENOMEM);
+
+ mount_info->fill_super = nfs4_fill_super;
+ mount_info->set_security = nfs_set_sb_security;
+
+ /* Get a volume representation */
+ server = nfs4_create_server(mount_info->parsed, mount_info->mntfh);
+ if (IS_ERR(server)) {
+ mntroot = ERR_CAST(server);
+ goto out;
+ }
+
+ mntroot = nfs_fs_mount_common(fs_type, server, flags, dev_name, mount_info);
+
+out:
+ return mntroot;
+}
+
+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) + 5;
+ root_devname = kmalloc(len, GFP_KERNEL);
+ if (root_devname == NULL)
+ return ERR_PTR(-ENOMEM);
+ /* Does hostname needs to be enclosed in brackets? */
+ if (strchr(hostname, ':'))
+ snprintf(root_devname, len, "[%s]:/", hostname);
+ else
+ 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_mount_info *mount_info)
+{
+ char *export_path;
+ struct vfsmount *root_mnt;
+ struct dentry *res;
+ struct nfs_parsed_mount_data *data = mount_info->parsed;
+
+ dfprintk(MOUNT, "--> nfs4_try_mount()\n");
+
+ mount_info->fill_super = nfs4_fill_super;
+
+ export_path = data->nfs_server.export_path;
+ data->nfs_server.export_path = "/";
+ root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, mount_info,
+ 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;
+}
+
+/*
+ * Clone an NFS4 server record on xdev traversal (FSID-change)
+ */
+static struct dentry *
+nfs4_xdev_mount(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *raw_data)
+{
+ struct nfs_mount_info mount_info = {
+ .fill_super = nfs_clone_super,
+ .set_security = nfs_clone_sb_security,
+ .cloned = raw_data,
+ };
+ return nfs_xdev_mount_common(&nfs4_fs_type, flags, dev_name, &mount_info);
+}
+
+static struct dentry *
+nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *raw_data)
+{
+ struct nfs_mount_info mount_info = {
+ .fill_super = nfs4_fill_super,
+ .set_security = nfs_clone_sb_security,
+ .cloned = raw_data,
+ };
+ struct nfs_server *server;
+ struct dentry *mntroot = ERR_PTR(-ENOMEM);
+
+ dprintk("--> nfs4_referral_get_sb()\n");
+
+ mount_info.mntfh = nfs_alloc_fhandle();
+ if (mount_info.cloned == NULL || mount_info.mntfh == NULL)
+ goto out;
+
+ /* create a new volume representation */
+ server = nfs4_create_referral_server(mount_info.cloned, mount_info.mntfh);
+ if (IS_ERR(server)) {
+ mntroot = ERR_CAST(server);
+ goto out;
+ }
+
+ mntroot = nfs_fs_mount_common(&nfs4_fs_type, server, flags, dev_name, &mount_info);
+out:
+ nfs_free_fhandle(mount_info.mntfh);
+ return mntroot;
+}
+
+/*
+ * 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;
+}
+
+
int __init init_nfs_v4(void)
{
int err;
@@ -18,7 +339,13 @@ int __init init_nfs_v4(void)
if (err)
goto out1;

+ err = register_filesystem(&nfs4_fs_type);
+ if (err < 0)
+ goto out2;
+
return 0;
+out2:
+ nfs4_unregister_sysctl();
out1:
nfs_idmap_quit();
out:
@@ -27,6 +354,7 @@ out:

void __exit exit_nfs_v4(void)
{
+ unregister_filesystem(&nfs4_fs_type);
nfs4_unregister_sysctl();
nfs_idmap_quit();
}
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index ca3c0e8..95866a8 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -278,29 +278,8 @@ static match_table_t nfs_vers_tokens = {
{ Opt_vers_err, NULL }
};

-struct nfs_mount_info {
- void (*fill_super)(struct super_block *, struct nfs_mount_info *);
- int (*set_security)(struct super_block *, struct dentry *, struct nfs_mount_info *);
- struct nfs_parsed_mount_data *parsed;
- struct nfs_clone_mount *cloned;
- struct nfs_fh *mntfh;
-};
-
-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_common(struct file_system_type *,
- struct nfs_server *, int, const char *, struct nfs_mount_info *);
-static struct dentry *nfs_fs_mount(struct file_system_type *,
- int, const char *, void *);
static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data);
-static void nfs_put_super(struct super_block *);
-static void nfs_kill_super(struct super_block *);
-static int nfs_remount(struct super_block *sb, int *flags, char *raw_data);

static struct file_system_type nfs_fs_type = {
.owner = THIS_MODULE,
@@ -337,71 +316,6 @@ static const struct super_operations nfs_sops = {
static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *);
static int nfs4_validate_mount_data(void *options,
struct nfs_parsed_mount_data *args, const char *dev_name);
-static struct dentry *nfs4_try_mount(int flags, const char *dev_name,
- struct nfs_mount_info *mount_info);
-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 struct file_system_type nfs4_fs_type = {
- .owner = THIS_MODULE,
- .name = "nfs4",
- .mount = nfs_fs_mount,
- .kill_sb = nfs_kill_super,
- .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
-};
-
-static struct file_system_type nfs4_remote_fs_type = {
- .owner = THIS_MODULE,
- .name = "nfs4",
- .mount = nfs4_remote_mount,
- .kill_sb = nfs_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 = nfs4_xdev_mount,
- .kill_sb = nfs_kill_super,
- .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
-};
-
-static struct file_system_type nfs4_remote_referral_fs_type = {
- .owner = THIS_MODULE,
- .name = "nfs4",
- .mount = nfs4_remote_referral_mount,
- .kill_sb = nfs_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 = nfs_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 = nfs4_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 = {
@@ -423,18 +337,9 @@ int __init register_nfs_fs(void)
ret = nfs_register_sysctl();
if (ret < 0)
goto error_1;
-#ifdef CONFIG_NFS_V4
- ret = register_filesystem(&nfs4_fs_type);
- if (ret < 0)
- goto error_2;
-#endif
register_shrinker(&acl_shrinker);
return 0;

-#ifdef CONFIG_NFS_V4
-error_2:
- nfs_unregister_sysctl();
-#endif
error_1:
unregister_filesystem(&nfs_fs_type);
error_0:
@@ -447,9 +352,6 @@ error_0:
void __exit unregister_nfs_fs(void)
{
unregister_shrinker(&acl_shrinker);
-#ifdef CONFIG_NFS_V4
- unregister_filesystem(&nfs4_fs_type);
-#endif
nfs_unregister_sysctl();
unregister_filesystem(&nfs_fs_type);
}
@@ -473,7 +375,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;
@@ -756,7 +658,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);

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

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

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

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

@@ -2194,8 +2096,7 @@ static inline void nfs_initialise_sb(struct super_block *sb)
/*
* Finish setting up an NFS2/3 superblock
*/
-static void nfs_fill_super(struct super_block *sb,
- struct nfs_mount_info *mount_info)
+void nfs_fill_super(struct super_block *sb, struct nfs_mount_info *mount_info)
{
struct nfs_parsed_mount_data *data = mount_info->parsed;
struct nfs_server *server = NFS_SB(sb);
@@ -2220,8 +2121,7 @@ static void nfs_fill_super(struct super_block *sb,
/*
* Finish setting up a cloned NFS2/3/4 superblock
*/
-static void nfs_clone_super(struct super_block *sb,
- struct nfs_mount_info *mount_info)
+void nfs_clone_super(struct super_block *sb, struct nfs_mount_info *mount_info)
{
const struct super_block *old_sb = mount_info->cloned->sb;
struct nfs_server *server = NFS_SB(sb);
@@ -2381,14 +2281,14 @@ static int nfs_bdi_register(struct nfs_server *server)
return bdi_register_dev(&server->backing_dev_info, server->s_dev);
}

-static int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot,
- struct nfs_mount_info *mount_info)
+int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot,
+ struct nfs_mount_info *mount_info)
{
return security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts);
}

-static int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot,
- struct nfs_mount_info *mount_info)
+int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot,
+ struct nfs_mount_info *mount_info)
{
/* clone any lsm security options from the parent to the new sb */
security_sb_clone_mnt_opts(mount_info->cloned->sb, s);
@@ -2397,10 +2297,10 @@ static int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot,
return 0;
}

-static struct dentry *nfs_fs_mount_common(struct file_system_type *fs_type,
- struct nfs_server *server,
- int flags, const char *dev_name,
- struct nfs_mount_info *mount_info)
+struct dentry *nfs_fs_mount_common(struct file_system_type *fs_type,
+ struct nfs_server *server,
+ int flags, const char *dev_name,
+ struct nfs_mount_info *mount_info)
{
struct super_block *s;
struct dentry *mntroot = ERR_PTR(-ENOMEM);
@@ -2470,7 +2370,7 @@ error_splat_bdi:
goto out;
}

-static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
+struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data)
{
struct nfs_mount_info mount_info = {
@@ -2511,7 +2411,7 @@ out:
* Ensure that we unregister the bdi before kill_anon_super
* releases the device name
*/
-static void nfs_put_super(struct super_block *s)
+void nfs_put_super(struct super_block *s)
{
struct nfs_server *server = NFS_SB(s);

@@ -2521,7 +2421,7 @@ static void nfs_put_super(struct super_block *s)
/*
* Destroy an NFS2/3 superblock
*/
-static void nfs_kill_super(struct super_block *s)
+void nfs_kill_super(struct super_block *s)
{
struct nfs_server *server = NFS_SB(s);

@@ -2533,7 +2433,7 @@ static void nfs_kill_super(struct super_block *s)
/*
* Clone an NFS2/3/4 server record on xdev traversal (FSID-change)
*/
-static struct dentry *
+struct dentry *
nfs_xdev_mount_common(struct file_system_type *fs_type, int flags,
const char *dev_name, struct nfs_mount_info *mount_info)
{
@@ -2580,23 +2480,6 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,

#ifdef CONFIG_NFS_V4

-/*
- * Set up an NFS4 superblock
- */
-static void nfs4_fill_super(struct super_block *sb,
- struct nfs_mount_info *mount_info)
-{
- 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|
@@ -2694,238 +2577,4 @@ out_no_address:
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 *info)
-{
- struct nfs_mount_info *mount_info = info;
- struct nfs_server *server;
- struct dentry *mntroot = ERR_PTR(-ENOMEM);
-
- mount_info->fill_super = nfs4_fill_super;
- mount_info->set_security = nfs_set_sb_security;
-
- /* Get a volume representation */
- server = nfs4_create_server(mount_info->parsed, mount_info->mntfh);
- if (IS_ERR(server)) {
- mntroot = ERR_CAST(server);
- goto out;
- }
-
- mntroot = nfs_fs_mount_common(fs_type, server, flags, dev_name, mount_info);
-
-out:
- return mntroot;
-}
-
-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) + 5;
- root_devname = kmalloc(len, GFP_KERNEL);
- if (root_devname == NULL)
- return ERR_PTR(-ENOMEM);
- /* Does hostname needs to be enclosed in brackets? */
- if (strchr(hostname, ':'))
- snprintf(root_devname, len, "[%s]:/", hostname);
- else
- 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;
-}
-
-static struct dentry *nfs4_try_mount(int flags, const char *dev_name,
- struct nfs_mount_info *mount_info)
-{
- char *export_path;
- struct vfsmount *root_mnt;
- struct dentry *res;
- struct nfs_parsed_mount_data *data = mount_info->parsed;
-
- dfprintk(MOUNT, "--> nfs4_try_mount()\n");
-
- mount_info->fill_super = nfs4_fill_super;
-
- export_path = data->nfs_server.export_path;
- data->nfs_server.export_path = "/";
- root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, mount_info,
- 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;
-}
-
-/*
- * Clone an NFS4 server record on xdev traversal (FSID-change)
- */
-static struct dentry *
-nfs4_xdev_mount(struct file_system_type *fs_type, int flags,
- const char *dev_name, void *raw_data)
-{
- struct nfs_mount_info mount_info = {
- .fill_super = nfs_clone_super,
- .set_security = nfs_clone_sb_security,
- .cloned = raw_data,
- };
- return nfs_xdev_mount_common(&nfs4_fs_type, flags, dev_name, &mount_info);
-}
-
-static struct dentry *
-nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
- const char *dev_name, void *raw_data)
-{
- struct nfs_mount_info mount_info = {
- .fill_super = nfs4_fill_super,
- .set_security = nfs_clone_sb_security,
- .cloned = raw_data,
- };
- struct nfs_server *server;
- struct dentry *mntroot = ERR_PTR(-ENOMEM);
-
- dprintk("--> nfs4_referral_get_sb()\n");
-
- mount_info.mntfh = nfs_alloc_fhandle();
- if (mount_info.cloned == NULL || mount_info.mntfh == NULL)
- goto out;
-
- /* create a new volume representation */
- server = nfs4_create_referral_server(mount_info.cloned, mount_info.mntfh);
- if (IS_ERR(server)) {
- mntroot = ERR_CAST(server);
- goto out;
- }
-
- mntroot = nfs_fs_mount_common(&nfs4_fs_type, server, flags, dev_name, &mount_info);
-out:
- nfs_free_fhandle(mount_info.mntfh);
- return mntroot;
-}
-
-/*
- * Create an NFS4 server record on referral traversal
- */
-static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *raw_data)
-{
- struct nfs_clone_mount *data = raw_data;
- char *export_path;
- struct vfsmount *root_mnt;
- struct dentry *res;
-
- dprintk("--> nfs4_referral_mount()\n");
-
- export_path = data->mnt_path;
- data->mnt_path = "/";
-
- root_mnt = nfs_do_root_mount(&nfs4_remote_referral_fs_type,
- flags, data, data->hostname);
- data->mnt_path = export_path;
-
- res = nfs_follow_remote_path(root_mnt, export_path);
- dprintk("<-- nfs4_referral_mount() = %ld%s\n",
- IS_ERR(res) ? PTR_ERR(res) : 0,
- IS_ERR(res) ? " [error]" : "");
- return res;
-}
-
#endif /* CONFIG_NFS_V4 */
--
1.7.11.2


2012-07-16 20:39:34

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v2 12/12] NFS: Split out NFS v4 client functions

From: Bryan Schumaker <[email protected]>

These functions are only needed by NFS v4, so they can be moved into a
v4 specific file.

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

diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 0d50629..65afa38 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -56,30 +56,6 @@
#define NFSDBG_FACILITY NFSDBG_CLIENT

static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
-#ifdef CONFIG_NFS_V4
-
-/*
- * Get a unique NFSv4.0 callback identifier which will be used
- * by the V4.0 callback service to lookup the nfs_client struct
- */
-static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
-{
- int ret = 0;
- struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
-
- if (clp->rpc_ops->version != 4 || minorversion != 0)
- return ret;
-retry:
- if (!idr_pre_get(&nn->cb_ident_idr, GFP_KERNEL))
- return -ENOMEM;
- spin_lock(&nn->nfs_client_lock);
- ret = idr_get_new(&nn->cb_ident_idr, clp, &clp->cl_cb_ident);
- spin_unlock(&nn->nfs_client_lock);
- if (ret == -EAGAIN)
- goto retry;
- return ret;
-}
-#endif /* CONFIG_NFS_V4 */

/*
* RPC cruft for NFS
@@ -175,75 +151,6 @@ error_0:
}

#ifdef CONFIG_NFS_V4
-#ifdef CONFIG_NFS_V4_1
-static void nfs4_shutdown_session(struct nfs_client *clp)
-{
- if (nfs4_has_session(clp)) {
- nfs4_destroy_session(clp->cl_session);
- nfs4_destroy_clientid(clp);
- }
-
-}
-#else /* CONFIG_NFS_V4_1 */
-static void nfs4_shutdown_session(struct nfs_client *clp)
-{
-}
-#endif /* CONFIG_NFS_V4_1 */
-
-struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init)
-{
- int err;
- struct nfs_client *clp = nfs_alloc_client(cl_init);
- if (IS_ERR(clp))
- return clp;
-
- err = nfs_get_cb_ident_idr(clp, cl_init->minorversion);
- if (err)
- goto error;
-
- spin_lock_init(&clp->cl_lock);
- INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
- rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
- clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
- clp->cl_minorversion = cl_init->minorversion;
- clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion];
- return clp;
-
-error:
- kfree(clp);
- return ERR_PTR(err);
-}
-
-/*
- * Destroy the NFS4 callback service
- */
-static void nfs4_destroy_callback(struct nfs_client *clp)
-{
- if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
- nfs_callback_down(clp->cl_mvops->minor_version);
-}
-
-static void nfs4_shutdown_client(struct nfs_client *clp)
-{
- if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
- nfs4_kill_renewd(clp);
- nfs4_shutdown_session(clp);
- nfs4_destroy_callback(clp);
- if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
- nfs_idmap_delete(clp);
-
- rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
- kfree(clp->cl_serverowner);
- kfree(clp->cl_serverscope);
- kfree(clp->cl_implid);
-}
-
-void nfs4_free_client(struct nfs_client *clp)
-{
- nfs4_shutdown_client(clp);
- nfs_free_client(clp);
-}
-
/* idr_remove_all is not needed as all id's are removed by nfs_put_client */
void nfs_cleanup_cb_ident_idr(struct net *net)
{
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index a71d95e..1c3f13c 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -23,6 +23,97 @@
static bool nfs4_disable_idmapping = true;

/*
+ * Get a unique NFSv4.0 callback identifier which will be used
+ * by the V4.0 callback service to lookup the nfs_client struct
+ */
+static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
+{
+ int ret = 0;
+ struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
+
+ if (clp->rpc_ops->version != 4 || minorversion != 0)
+ return ret;
+retry:
+ if (!idr_pre_get(&nn->cb_ident_idr, GFP_KERNEL))
+ return -ENOMEM;
+ spin_lock(&nn->nfs_client_lock);
+ ret = idr_get_new(&nn->cb_ident_idr, clp, &clp->cl_cb_ident);
+ spin_unlock(&nn->nfs_client_lock);
+ if (ret == -EAGAIN)
+ goto retry;
+ return ret;
+}
+
+#ifdef CONFIG_NFS_V4_1
+static void nfs4_shutdown_session(struct nfs_client *clp)
+{
+ if (nfs4_has_session(clp)) {
+ nfs4_destroy_session(clp->cl_session);
+ nfs4_destroy_clientid(clp);
+ }
+
+}
+#else /* CONFIG_NFS_V4_1 */
+static void nfs4_shutdown_session(struct nfs_client *clp)
+{
+}
+#endif /* CONFIG_NFS_V4_1 */
+
+struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init)
+{
+ int err;
+ struct nfs_client *clp = nfs_alloc_client(cl_init);
+ if (IS_ERR(clp))
+ return clp;
+
+ err = nfs_get_cb_ident_idr(clp, cl_init->minorversion);
+ if (err)
+ goto error;
+
+ spin_lock_init(&clp->cl_lock);
+ INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
+ rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
+ clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
+ clp->cl_minorversion = cl_init->minorversion;
+ clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion];
+ return clp;
+
+error:
+ kfree(clp);
+ return ERR_PTR(err);
+}
+
+/*
+ * Destroy the NFS4 callback service
+ */
+static void nfs4_destroy_callback(struct nfs_client *clp)
+{
+ if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
+ nfs_callback_down(clp->cl_mvops->minor_version);
+}
+
+static void nfs4_shutdown_client(struct nfs_client *clp)
+{
+ if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
+ nfs4_kill_renewd(clp);
+ nfs4_shutdown_session(clp);
+ nfs4_destroy_callback(clp);
+ if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
+ nfs_idmap_delete(clp);
+
+ rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
+ kfree(clp->cl_serverowner);
+ kfree(clp->cl_serverscope);
+ kfree(clp->cl_implid);
+}
+
+void nfs4_free_client(struct nfs_client *clp)
+{
+ nfs4_shutdown_client(clp);
+ nfs_free_client(clp);
+}
+
+/*
* Initialize the NFS4 callback service
*/
static int nfs4_init_callback(struct nfs_client *clp)
--
1.7.11.2


2012-07-16 20:39:31

by Anna Schumaker

[permalink] [raw]
Subject: [PATCH v2 09/12] NFS: Split out NFS v4 server creating code

From: Bryan Schumaker <[email protected]>

These functions are specific to NFS v4 and can be moved to nfs4client.c
to keep them out of the generic client.

Signed-off-by: Bryan Schumaker <[email protected]>
---
fs/nfs/client.c | 457 ++--------------------------------------------------
fs/nfs/internal.h | 25 +++
fs/nfs/nfs4client.c | 428 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 462 insertions(+), 448 deletions(-)

diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 5664c7b..0d50629 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -82,11 +82,6 @@ retry:
#endif /* CONFIG_NFS_V4 */

/*
- * Turn off NFSv4 uid/gid mapping when using AUTH_SYS
- */
-static bool nfs4_disable_idmapping = true;
-
-/*
* RPC cruft for NFS
*/
static const struct rpc_version *nfs_version[5] = {
@@ -130,17 +125,6 @@ const struct rpc_program nfsacl_program = {
};
#endif /* CONFIG_NFS_V3_ACL */

-struct nfs_client_initdata {
- unsigned long init_flags;
- const char *hostname;
- const struct sockaddr *addr;
- size_t addrlen;
- const struct nfs_rpc_ops *rpc_ops;
- int proto;
- u32 minorversion;
- struct net *net;
-};
-
/*
* Allocate a shared client record
*
@@ -282,13 +266,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)
-{
- nfs_server_return_all_delegations(server);
- unset_pnfs_layoutdriver(server);
- nfs4_purge_state_owners(server);
-}
-
#else
void nfs_cleanup_cb_ident_idr(struct net *net)
{
@@ -426,8 +403,8 @@ static int nfs_sockaddr_cmp_ip4(const struct sockaddr *sa1,
* Test if two socket addresses represent the same actual socket,
* by comparing (only) relevant fields, excluding the port number.
*/
-static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
- const struct sockaddr *sa2)
+int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
+ const struct sockaddr *sa2)
{
if (sa1->sa_family != sa2->sa_family)
return 0;
@@ -461,33 +438,6 @@ static int nfs_sockaddr_cmp(const struct sockaddr *sa1,
return 0;
}

-#if defined(CONFIG_NFS_V4_1)
-/* Common match routine for v4.0 and v4.1 callback services */
-static bool nfs4_cb_match_client(const struct sockaddr *addr,
- struct nfs_client *clp, u32 minorversion)
-{
- struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
-
- /* Don't match clients that failed to initialise */
- if (!(clp->cl_cons_state == NFS_CS_READY ||
- clp->cl_cons_state == NFS_CS_SESSION_INITING))
- return false;
-
- smp_rmb();
-
- /* Match the version and minorversion */
- if (clp->rpc_ops->version != 4 ||
- clp->cl_minorversion != minorversion)
- return false;
-
- /* Match only the IP address, not the port number */
- if (!nfs_sockaddr_match_ipaddr(addr, clap))
- return false;
-
- return true;
-}
-#endif /* CONFIG_NFS_V4_1 */
-
/*
* Find an nfs_client on the list that matches the initialisation data
* that is supplied.
@@ -566,7 +516,7 @@ nfs_found_client(const struct nfs_client_initdata *cl_init,
* Look up a client by IP address and protocol version
* - creates a new record if one doesn't yet exist
*/
-static struct nfs_client *
+struct nfs_client *
nfs_get_client(const struct nfs_client_initdata *cl_init,
const struct rpc_timeout *timeparms,
const char *ip_addr,
@@ -621,7 +571,7 @@ void nfs_mark_client_ready(struct nfs_client *clp, int state)
/*
* Initialise the timeout values for a connection
*/
-static void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
+void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
unsigned int timeo, unsigned int retrans)
{
to->to_initval = timeo * HZ / 10;
@@ -781,7 +731,7 @@ static inline void nfs_init_server_aclclient(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)
{
@@ -1014,7 +964,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;
@@ -1058,7 +1008,7 @@ out_error:
/*
* Copy useful information when duplicating a server record
*/
-static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source)
+void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source)
{
target->flags = source->flags;
target->rsize = source->rsize;
@@ -1071,7 +1021,7 @@ static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_serve
target->options = source->options;
}

-static void nfs_server_insert_lists(struct nfs_server *server)
+void nfs_server_insert_lists(struct nfs_server *server)
{
struct nfs_client *clp = server->nfs_client;
struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
@@ -1105,7 +1055,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;

@@ -1238,391 +1188,6 @@ error:
return ERR_PTR(error);
}

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

#endif /* CONFIG_PROC_FS */
-
-module_param(nfs4_disable_idmapping, bool, 0644);
-MODULE_PARM_DESC(nfs4_disable_idmapping,
- "Turn off NFSv4 idmapping when using 'sec=sys'");
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 10df28d..b4a3570 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -85,6 +85,17 @@ struct nfs_clone_mount {
*/
#define NFS_MAX_READDIR_PAGES 8

+struct nfs_client_initdata {
+ unsigned long init_flags;
+ const char *hostname;
+ const struct sockaddr *addr;
+ size_t addrlen;
+ const struct nfs_rpc_ops *rpc_ops;
+ int proto;
+ u32 minorversion;
+ struct net *net;
+};
+
/*
* In-kernel mount arguments
*/
@@ -150,6 +161,16 @@ extern const struct rpc_program nfs_program;
extern void nfs_clients_init(struct net *net);
extern struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *);
int nfs_create_rpc_client(struct nfs_client *, const struct rpc_timeout *, rpc_authflavor_t);
+struct nfs_client *nfs_get_client(const struct nfs_client_initdata *,
+ const struct rpc_timeout *, const char *,
+ rpc_authflavor_t);
+int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *, struct nfs_fattr *);
+void nfs_server_insert_lists(struct nfs_server *);
+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 *t,
+ rpc_authflavor_t);
+struct nfs_server *nfs_alloc_server(void);
+void nfs_server_copy_userdata(struct nfs_server *, struct nfs_server *);

extern void nfs_cleanup_cb_ident_idr(struct net *);
extern void nfs_put_client(struct nfs_client *);
@@ -191,6 +212,10 @@ static inline void nfs_fs_proc_exit(void)
}
#endif

+#ifdef CONFIG_NFS_V4_1
+int nfs_sockaddr_match_ipaddr(const struct sockaddr *, const struct sockaddr *);
+#endif
+
/* callback_xdr.c */
extern struct svc_version nfs4_callback_version1;
extern struct svc_version nfs4_callback_version4;
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index c5234b5..a71d95e 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -2,17 +2,27 @@
* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
* Written by David Howells ([email protected])
*/
+#include <linux/module.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_idmap.h>
+#include <linux/nfs_mount.h>
#include <linux/sunrpc/auth.h>
#include <linux/sunrpc/xprt.h>
#include <linux/sunrpc/bc_xprt.h>
#include "internal.h"
#include "callback.h"
+#include "delegation.h"
+#include "pnfs.h"
+#include "netns.h"

#define NFSDBG_FACILITY NFSDBG_CLIENT

/*
+ * Turn off NFSv4 uid/gid mapping when using AUTH_SYS
+ */
+static bool nfs4_disable_idmapping = true;
+
+/*
* Initialize the NFS4 callback service
*/
static int nfs4_init_callback(struct nfs_client *clp)
@@ -142,3 +152,421 @@ error:
dprintk("<-- nfs4_init_client() = xerror %d\n", error);
return ERR_PTR(error);
}
+
+static void nfs4_destroy_server(struct nfs_server *server)
+{
+ nfs_server_return_all_delegations(server);
+ unset_pnfs_layoutdriver(server);
+ nfs4_purge_state_owners(server);
+}
+
+/*
+ * NFSv4.0 callback thread helper
+ *
+ * Find a client by callback identifier
+ */
+struct nfs_client *
+nfs4_find_client_ident(struct net *net, int cb_ident)
+{
+ struct nfs_client *clp;
+ struct nfs_net *nn = net_generic(net, nfs_net_id);
+
+ spin_lock(&nn->nfs_client_lock);
+ clp = idr_find(&nn->cb_ident_idr, cb_ident);
+ if (clp)
+ atomic_inc(&clp->cl_count);
+ spin_unlock(&nn->nfs_client_lock);
+ return clp;
+}
+
+#if defined(CONFIG_NFS_V4_1)
+/* Common match routine for v4.0 and v4.1 callback services */
+static bool nfs4_cb_match_client(const struct sockaddr *addr,
+ struct nfs_client *clp, u32 minorversion)
+{
+ struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
+
+ /* Don't match clients that failed to initialise */
+ if (!(clp->cl_cons_state == NFS_CS_READY ||
+ clp->cl_cons_state == NFS_CS_SESSION_INITING))
+ return false;
+
+ smp_rmb();
+
+ /* Match the version and minorversion */
+ if (clp->rpc_ops->version != 4 ||
+ clp->cl_minorversion != minorversion)
+ return false;
+
+ /* Match only the IP address, not the port number */
+ if (!nfs_sockaddr_match_ipaddr(addr, clap))
+ return false;
+
+ return true;
+}
+
+/*
+ * NFSv4.1 callback thread helper
+ * For CB_COMPOUND calls, find a client by IP address, protocol version,
+ * minorversion, and sessionID
+ *
+ * Returns NULL if no such client
+ */
+struct nfs_client *
+nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr,
+ struct nfs4_sessionid *sid)
+{
+ struct nfs_client *clp;
+ struct nfs_net *nn = net_generic(net, nfs_net_id);
+
+ spin_lock(&nn->nfs_client_lock);
+ list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) {
+ if (nfs4_cb_match_client(addr, clp, 1) == false)
+ continue;
+
+ if (!nfs4_has_session(clp))
+ continue;
+
+ /* Match sessionid*/
+ if (memcmp(clp->cl_session->sess_id.data,
+ sid->data, NFS4_MAX_SESSIONID_LEN) != 0)
+ continue;
+
+ atomic_inc(&clp->cl_count);
+ spin_unlock(&nn->nfs_client_lock);
+ return clp;
+ }
+ spin_unlock(&nn->nfs_client_lock);
+ return NULL;
+}
+
+#else /* CONFIG_NFS_V4_1 */
+
+struct nfs_client *
+nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr,
+ struct nfs4_sessionid *sid)
+{
+ return NULL;
+}
+#endif /* CONFIG_NFS_V4_1 */
+
+/*
+ * Set up an NFS4 client
+ */
+static int nfs4_set_client(struct nfs_server *server,
+ const char *hostname,
+ const struct sockaddr *addr,
+ const size_t addrlen,
+ const char *ip_addr,
+ rpc_authflavor_t authflavour,
+ int proto, const struct rpc_timeout *timeparms,
+ u32 minorversion, struct net *net)
+{
+ struct nfs_client_initdata cl_init = {
+ .hostname = hostname,
+ .addr = addr,
+ .addrlen = addrlen,
+ .rpc_ops = &nfs_v4_clientops,
+ .proto = proto,
+ .minorversion = minorversion,
+ .net = net,
+ };
+ struct nfs_client *clp;
+ int error;
+
+ dprintk("--> nfs4_set_client()\n");
+
+ if (server->flags & NFS_MOUNT_NORESVPORT)
+ set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
+
+ /* Allocate or find a client reference we can use */
+ clp = nfs_get_client(&cl_init, timeparms, ip_addr, authflavour);
+ if (IS_ERR(clp)) {
+ error = PTR_ERR(clp);
+ goto error;
+ }
+
+ /*
+ * Query for the lease time on clientid setup or renewal
+ *
+ * Note that this will be set on nfs_clients that were created
+ * only for the DS role and did not set this bit, but now will
+ * serve a dual role.
+ */
+ set_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state);
+
+ server->nfs_client = clp;
+ dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp);
+ return 0;
+error:
+ dprintk("<-- nfs4_set_client() = xerror %d\n", error);
+ return error;
+}
+
+/*
+ * Set up a pNFS Data Server client.
+ *
+ * Return any existing nfs_client that matches server address,port,version
+ * and minorversion.
+ *
+ * For a new nfs_client, use a soft mount (default), a low retrans and a
+ * low timeout interval so that if a connection is lost, we retry through
+ * the MDS.
+ */
+struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
+ const struct sockaddr *ds_addr, int ds_addrlen,
+ int ds_proto, unsigned int ds_timeo, unsigned int ds_retrans)
+{
+ struct nfs_client_initdata cl_init = {
+ .addr = ds_addr,
+ .addrlen = ds_addrlen,
+ .rpc_ops = &nfs_v4_clientops,
+ .proto = ds_proto,
+ .minorversion = mds_clp->cl_minorversion,
+ .net = mds_clp->cl_net,
+ };
+ struct rpc_timeout ds_timeout;
+ struct nfs_client *clp;
+
+ /*
+ * Set an authflavor equual to the MDS value. Use the MDS nfs_client
+ * cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS
+ * (section 13.1 RFC 5661).
+ */
+ nfs_init_timeout_values(&ds_timeout, ds_proto, ds_timeo, ds_retrans);
+ clp = nfs_get_client(&cl_init, &ds_timeout, mds_clp->cl_ipaddr,
+ mds_clp->cl_rpcclient->cl_auth->au_flavor);
+
+ dprintk("<-- %s %p\n", __func__, clp);
+ return clp;
+}
+EXPORT_SYMBOL_GPL(nfs4_set_ds_client);
+
+/*
+ * Session has been established, and the client marked ready.
+ * Set the mount rsize and wsize with negotiated fore channel
+ * attributes which will be bound checked in nfs_server_set_fsinfo.
+ */
+static void nfs4_session_set_rwsize(struct nfs_server *server)
+{
+#ifdef CONFIG_NFS_V4_1
+ struct nfs4_session *sess;
+ u32 server_resp_sz;
+ u32 server_rqst_sz;
+
+ if (!nfs4_has_session(server->nfs_client))
+ return;
+ sess = server->nfs_client->cl_session;
+ server_resp_sz = sess->fc_attrs.max_resp_sz - nfs41_maxread_overhead;
+ server_rqst_sz = sess->fc_attrs.max_rqst_sz - nfs41_maxwrite_overhead;
+
+ if (server->rsize > server_resp_sz)
+ server->rsize = server_resp_sz;
+ if (server->wsize > server_rqst_sz)
+ server->wsize = server_rqst_sz;
+#endif /* CONFIG_NFS_V4_1 */
+}
+
+static int nfs4_server_common_setup(struct nfs_server *server,
+ struct nfs_fh *mntfh)
+{
+ struct nfs_fattr *fattr;
+ int error;
+
+ BUG_ON(!server->nfs_client);
+ BUG_ON(!server->nfs_client->rpc_ops);
+ BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
+
+ /* data servers support only a subset of NFSv4.1 */
+ if (is_ds_only_client(server->nfs_client))
+ return -EPROTONOSUPPORT;
+
+ fattr = nfs_alloc_fattr();
+ if (fattr == NULL)
+ return -ENOMEM;
+
+ /* We must ensure the session is initialised first */
+ error = nfs4_init_session(server);
+ if (error < 0)
+ goto out;
+
+ /* Probe the root fh to retrieve its FSID and filehandle */
+ error = nfs4_get_rootfh(server, mntfh);
+ if (error < 0)
+ goto out;
+
+ dprintk("Server FSID: %llx:%llx\n",
+ (unsigned long long) server->fsid.major,
+ (unsigned long long) server->fsid.minor);
+ dprintk("Mount FH: %d\n", mntfh->size);
+
+ nfs4_session_set_rwsize(server);
+
+ error = nfs_probe_fsinfo(server, mntfh, fattr);
+ if (error < 0)
+ goto out;
+
+ if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
+ server->namelen = NFS4_MAXNAMLEN;
+
+ nfs_server_insert_lists(server);
+ server->mount_time = jiffies;
+ server->destroy = nfs4_destroy_server;
+out:
+ nfs_free_fattr(fattr);
+ return error;
+}
+
+/*
+ * Create a version 4 volume record
+ */
+static int nfs4_init_server(struct nfs_server *server,
+ const struct nfs_parsed_mount_data *data)
+{
+ struct rpc_timeout timeparms;
+ int error;
+
+ dprintk("--> nfs4_init_server()\n");
+
+ nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
+ data->timeo, data->retrans);
+
+ /* Initialise the client representation from the mount data */
+ server->flags = data->flags;
+ server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR|NFS_CAP_POSIX_LOCK;
+ if (!(data->flags & NFS_MOUNT_NORDIRPLUS))
+ server->caps |= NFS_CAP_READDIRPLUS;
+ server->options = data->options;
+
+ /* Get a client record */
+ error = nfs4_set_client(server,
+ data->nfs_server.hostname,
+ (const struct sockaddr *)&data->nfs_server.address,
+ data->nfs_server.addrlen,
+ data->client_address,
+ data->auth_flavors[0],
+ data->nfs_server.protocol,
+ &timeparms,
+ data->minorversion,
+ data->net);
+ if (error < 0)
+ goto error;
+
+ /*
+ * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower
+ * authentication.
+ */
+ if (nfs4_disable_idmapping && data->auth_flavors[0] == RPC_AUTH_UNIX)
+ server->caps |= NFS_CAP_UIDGID_NOMAP;
+
+ if (data->rsize)
+ server->rsize = nfs_block_size(data->rsize, NULL);
+ if (data->wsize)
+ server->wsize = nfs_block_size(data->wsize, NULL);
+
+ server->acregmin = data->acregmin * HZ;
+ server->acregmax = data->acregmax * HZ;
+ server->acdirmin = data->acdirmin * HZ;
+ server->acdirmax = data->acdirmax * HZ;
+
+ server->port = data->nfs_server.port;
+
+ error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]);
+
+error:
+ /* Done */
+ dprintk("<-- nfs4_init_server() = %d\n", error);
+ return error;
+}
+
+/*
+ * Create a version 4 volume record
+ * - keyed on server and FSID
+ */
+struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
+ struct nfs_fh *mntfh)
+{
+ struct nfs_server *server;
+ int error;
+
+ dprintk("--> nfs4_create_server()\n");
+
+ server = nfs_alloc_server();
+ if (!server)
+ return ERR_PTR(-ENOMEM);
+
+ /* set up the general RPC client */
+ error = nfs4_init_server(server, data);
+ if (error < 0)
+ goto error;
+
+ error = nfs4_server_common_setup(server, mntfh);
+ if (error < 0)
+ goto error;
+
+ dprintk("<-- nfs4_create_server() = %p\n", server);
+ return server;
+
+error:
+ nfs_free_server(server);
+ dprintk("<-- nfs4_create_server() = error %d\n", error);
+ return ERR_PTR(error);
+}
+
+/*
+ * Create an NFS4 referral server record
+ */
+struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
+ struct nfs_fh *mntfh)
+{
+ struct nfs_client *parent_client;
+ struct nfs_server *server, *parent_server;
+ int error;
+
+ dprintk("--> nfs4_create_referral_server()\n");
+
+ server = nfs_alloc_server();
+ if (!server)
+ return ERR_PTR(-ENOMEM);
+
+ parent_server = NFS_SB(data->sb);
+ parent_client = parent_server->nfs_client;
+
+ /* Initialise the client representation from the parent server */
+ nfs_server_copy_userdata(server, parent_server);
+ server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR;
+
+ /* Get a client representation.
+ * Note: NFSv4 always uses TCP, */
+ error = nfs4_set_client(server, data->hostname,
+ data->addr,
+ data->addrlen,
+ parent_client->cl_ipaddr,
+ data->authflavor,
+ rpc_protocol(parent_server->client),
+ parent_server->client->cl_timeout,
+ parent_client->cl_mvops->minor_version,
+ parent_client->cl_net);
+ if (error < 0)
+ goto error;
+
+ error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout, data->authflavor);
+ if (error < 0)
+ goto error;
+
+ error = nfs4_server_common_setup(server, mntfh);
+ if (error < 0)
+ goto error;
+
+ dprintk("<-- nfs_create_referral_server() = %p\n", server);
+ return server;
+
+error:
+ nfs_free_server(server);
+ dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
+ return ERR_PTR(error);
+}
+
+module_param(nfs4_disable_idmapping, bool, 0644);
+MODULE_PARM_DESC(nfs4_disable_idmapping,
+ "Turn off NFSv4 idmapping when using 'sec=sys'");
--
1.7.11.2