From: Bryan Schumaker <bjschuma@xxxxxxxxxx> I set up a common _nfs_xdev_mount() function that can be called by v2, v3 and v4 with different parameters. This also gives each version a chance to do their own thing both before and after the call. Signed-off-by: Bryan Schumaker <bjschuma@xxxxxxxxxx> --- fs/nfs/nfs.h | 4 ++ fs/nfs/nfs2super.c | 10 ++++- fs/nfs/nfs3super.c | 8 +++ fs/nfs/nfs4_fs.h | 1 + fs/nfs/nfs4super.c | 11 +++++ fs/nfs/super.c | 126 +++++++++------------------------------------------ 6 files changed, 56 insertions(+), 104 deletions(-) diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h index dc7d047..a813d00 100644 --- a/fs/nfs/nfs.h +++ b/fs/nfs/nfs.h @@ -14,6 +14,7 @@ #include <linux/nfs_xdr.h> struct nfs_parsed_mount_data; +struct nfs_clone_mount; struct nfs_subversion { unsigned int version; /* Protocol number */ @@ -25,6 +26,7 @@ struct nfs_subversion { void (*unreference)(void); /* Also for reference counting */ struct dentry *(*fs_mount)(struct file_system_type *, int, const char *, struct nfs_fh *, struct nfs_parsed_mount_data *); + struct dentry *(*xdev_mount)(int, const char *, struct nfs_clone_mount *); }; void nfs_register_versions(void); @@ -41,9 +43,11 @@ void unregister_nfs_version(struct nfs_subversion *); struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *, struct nfs_fh *); /* Exported in super.c */ +extern struct file_system_type nfs_fs_type; struct dentry *_nfs_fs_mount(struct file_system_type *, struct nfs_server *, int, const char *, struct nfs_fh *, struct nfs_parsed_mount_data *); +struct dentry *_nfs_xdev_mount(struct file_system_type *, int, const char *, void *, int); #endif /* __LINUX_INTERNAL_NFS_H */ diff --git a/fs/nfs/nfs2super.c b/fs/nfs/nfs2super.c index 8f92f5d..d1074a9 100644 --- a/fs/nfs/nfs2super.c +++ b/fs/nfs/nfs2super.c @@ -1,10 +1,11 @@ /* * Copyright (c) 2012 Netapp, Inc. All rights reserved. * - * Initialize the NFS v2 module + Initialize[* Initialize the NFS v2 module */ #include <linux/module.h> #include <linux/nfs_fs.h> +#include <linux/nfs_mount.h> #include "nfs.h" static void nfs2_reference(void) @@ -28,6 +29,12 @@ static struct dentry *nfs2_fs_mount(struct file_system_type *fs_type, return _nfs_fs_mount(fs_type, server, flags, dev_name, mntfh, data); } +static struct dentry *nfs2_xdev_mount(int flags, const char *dev_name, + struct nfs_clone_mount *data) +{ + return _nfs_xdev_mount(&nfs_fs_type, flags, dev_name, data, NFS_MOUNT_UNSHARED); +} + static struct nfs_subversion nfs_v2 = { .version = 2, .rpc_vers = &nfs_version2, @@ -36,6 +43,7 @@ static struct nfs_subversion nfs_v2 = { .reference = nfs2_reference, .unreference = nfs2_unreference, .fs_mount = nfs2_fs_mount, + .xdev_mount = nfs2_xdev_mount, }; static int __init init_nfs_v2(void) diff --git a/fs/nfs/nfs3super.c b/fs/nfs/nfs3super.c index 2048460..7bdd388 100644 --- a/fs/nfs/nfs3super.c +++ b/fs/nfs/nfs3super.c @@ -3,6 +3,7 @@ */ #include <linux/module.h> #include <linux/nfs_fs.h> +#include <linux/nfs_mount.h> #include "nfs.h" static void nfs3_reference(void) @@ -26,6 +27,12 @@ struct dentry *nfs3_fs_mount(struct file_system_type *fs_type, return _nfs_fs_mount(fs_type, server, flags, dev_name, mntfh, data); } +static struct dentry *nfs3_xdev_mount(int flags, const char *dev_name, + struct nfs_clone_mount *data) +{ + return _nfs_xdev_mount(&nfs_fs_type, flags, dev_name, data, NFS_MOUNT_UNSHARED); +} + static struct nfs_subversion nfs_v3 = { .version = 3, .rpc_vers = &nfs_version3, @@ -34,6 +41,7 @@ static struct nfs_subversion nfs_v3 = { .reference = nfs3_reference, .unreference = nfs3_unreference, .fs_mount = nfs3_fs_mount, + .xdev_mount = nfs3_xdev_mount, }; int __init init_nfs_v3(void) diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index b888151..449b943 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -207,6 +207,7 @@ extern const struct dentry_operations nfs4_dentry_operations; extern const struct inode_operations nfs4_dir_inode_operations; /* super.c */ +extern struct file_system_type nfs4_fs_type; struct dentry *nfs4_try_mount(int flags, const char *dev_name, struct nfs_parsed_mount_data *); /* nfs4proc.c */ diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index 0cc67b6..8a297c5 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c @@ -3,6 +3,7 @@ */ #include <linux/module.h> #include <linux/nfs_fs.h> +#include <linux/nfs4_mount.h> #include "nfs4_fs.h" #include "nfs.h" @@ -24,6 +25,15 @@ struct dentry *nfs4_fs_mount(struct file_system_type *fs_type, return nfs4_try_mount(flags, dev_name, data); } +/* + * Clone an NFS4 server record on xdev traversal (FSID-change) + */ +struct dentry *nfs4_xdev_mount(int flags, const char *dev_name, + struct nfs_clone_mount *data) +{ + return _nfs_xdev_mount(&nfs4_fs_type, flags, dev_name, data, NFS4_MOUNT_UNSHARED); +} + static struct nfs_subversion nfs_v4 = { .version = 4, .rpc_vers = &nfs_version4, @@ -32,6 +42,7 @@ static struct nfs_subversion nfs_v4 = { .reference = nfs4_reference, .unreference = nfs4_unreference, .fs_mount = nfs4_fs_mount, + .xdev_mount = nfs4_xdev_mount, }; int __init init_nfs_v4(void) diff --git a/fs/nfs/super.c b/fs/nfs/super.c index ea1d932..e6c62b5 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -276,13 +276,14 @@ static void nfs_put_super(struct super_block *); static void nfs_kill_super(struct super_block *); static int nfs_remount(struct super_block *sb, int *flags, char *raw_data); -static struct file_system_type nfs_fs_type = { +struct file_system_type nfs_fs_type = { .owner = THIS_MODULE, .name = "nfs", .mount = nfs_fs_mount, .kill_sb = nfs_kill_super, .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, }; +EXPORT_SYMBOL_GPL(nfs_fs_type); struct file_system_type nfs_xdev_fs_type = { .owner = THIS_MODULE, @@ -316,15 +317,13 @@ static struct dentry *nfs4_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data); static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data); -static struct dentry *nfs4_xdev_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *raw_data); static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data); static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data); static void nfs4_kill_super(struct super_block *sb); -static struct file_system_type nfs4_fs_type = { +struct file_system_type nfs4_fs_type = { .owner = THIS_MODULE, .name = "nfs4", .mount = nfs4_mount, @@ -343,7 +342,7 @@ static struct file_system_type nfs4_remote_fs_type = { struct file_system_type nfs4_xdev_fs_type = { .owner = THIS_MODULE, .name = "nfs4", - .mount = nfs4_xdev_mount, + .mount = nfs_xdev_mount, .kill_sb = nfs4_kill_super, .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, }; @@ -2373,9 +2372,9 @@ static void nfs_kill_super(struct super_block *s) /* * Clone an NFS2/3 server record on xdev traversal (FSID-change) */ -static struct dentry * -nfs_xdev_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *raw_data) +struct dentry * +_nfs_xdev_mount(struct file_system_type *fs_type, int flags, + const char *dev_name, void *raw_data, int unshared_flag) { struct nfs_clone_mount *data = raw_data; struct super_block *s; @@ -2387,7 +2386,7 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags, }; int error; - dprintk("--> nfs_xdev_mount()\n"); + dprintk("--> _nfs_xdev_mount()\n"); /* create a new volume representation */ server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr); @@ -2397,7 +2396,7 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags, } sb_mntdata.server = server; - if (server->flags & NFS_MOUNT_UNSHARED) + if (server->flags & unshared_flag) compare_super = NULL; /* -o noac implies -o sync */ @@ -2405,7 +2404,7 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags, sb_mntdata.mntflags |= MS_SYNCHRONOUS; /* Get a superblock - note that we may end up sharing one that already exists */ - s = sget(&nfs_fs_type, compare_super, nfs_set_super, &sb_mntdata); + s = sget(fs_type, compare_super, nfs_set_super, &sb_mntdata); if (IS_ERR(s)) { error = PTR_ERR(s); goto out_err_nosb; @@ -2442,13 +2441,13 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags, /* clone any lsm security options from the parent to the new sb */ security_sb_clone_mnt_opts(data->sb, s); - dprintk("<-- nfs_xdev_mount() = 0\n"); + dprintk("<-- _nfs_xdev_mount() = 0\n"); return mntroot; out_err_nosb: nfs_free_server(server); out_err_noserver: - dprintk("<-- nfs_xdev_mount() = %d [error]\n", error); + dprintk("<-- _nfs_xdev_mount() = %d [error]\n", error); return ERR_PTR(error); error_splat_super: @@ -2456,9 +2455,19 @@ error_splat_super: nfs_unregister(server); error_splat_bdi: deactivate_locked_super(s); - dprintk("<-- nfs_xdev_mount() = %d [splat]\n", error); + dprintk("<-- _nfs_xdev_mount() = %d [splat]\n", error); return ERR_PTR(error); } +EXPORT_SYMBOL_GPL(_nfs_xdev_mount); + +static struct dentry * +nfs_xdev_mount(struct file_system_type *fs_type, int flags, + const char *dev_name, void *raw_data) +{ + struct nfs_clone_mount *data = raw_data; + struct nfs_subversion *nfs_mod = get_nfs_server_version(NFS_SB(data->sb)); + return nfs_mod->xdev_mount(flags, dev_name, data); +} #ifdef CONFIG_NFS_V4 @@ -2879,95 +2888,6 @@ static void nfs4_kill_super(struct super_block *sb) dprintk("<-- %s\n", __func__); } -/* - * Clone an NFS4 server record on xdev traversal (FSID-change) - */ -static struct dentry * -nfs4_xdev_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *raw_data) -{ - struct nfs_clone_mount *data = raw_data; - struct super_block *s; - struct nfs_server *server; - struct dentry *mntroot; - int (*compare_super)(struct super_block *, void *) = nfs_compare_super; - struct nfs_sb_mountdata sb_mntdata = { - .mntflags = flags, - }; - int error; - - dprintk("--> nfs4_xdev_mount()\n"); - - /* create a new volume representation */ - server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr); - if (IS_ERR(server)) { - error = PTR_ERR(server); - goto out_err_noserver; - } - sb_mntdata.server = server; - - if (server->flags & NFS4_MOUNT_UNSHARED) - compare_super = NULL; - - /* -o noac implies -o sync */ - if (server->flags & NFS_MOUNT_NOAC) - sb_mntdata.mntflags |= MS_SYNCHRONOUS; - - /* Get a superblock - note that we may end up sharing one that already exists */ - s = sget(&nfs4_fs_type, compare_super, nfs_set_super, &sb_mntdata); - if (IS_ERR(s)) { - error = PTR_ERR(s); - goto out_err_nosb; - } - - if (s->s_fs_info != server) { - nfs_free_server(server); - server = NULL; - } else { - error = nfs_register(server); - if (error) - goto error_splat_bdi; - } - - if (!s->s_root) { - /* initial superblock/root creation */ - nfs_clone_super(s, data->sb); - nfs_fscache_get_super_cookie(s, NULL, data); - } - - mntroot = nfs4_get_root(s, data->fh, dev_name); - if (IS_ERR(mntroot)) { - error = PTR_ERR(mntroot); - goto error_splat_super; - } - if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) { - dput(mntroot); - error = -ESTALE; - goto error_splat_super; - } - - s->s_flags |= MS_ACTIVE; - - security_sb_clone_mnt_opts(data->sb, s); - - dprintk("<-- nfs4_xdev_mount() = 0\n"); - return mntroot; - -out_err_nosb: - nfs_free_server(server); -out_err_noserver: - dprintk("<-- nfs4_xdev_mount() = %d [error]\n", error); - return ERR_PTR(error); - -error_splat_super: - if (server && !s->s_root) - nfs_unregister(server); -error_splat_bdi: - deactivate_locked_super(s); - dprintk("<-- nfs4_xdev_mount() = %d [splat]\n", error); - return ERR_PTR(error); -} - static struct dentry * nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data) -- 1.7.9 -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html