Commit ab7017a3 authored by Bryan Schumaker's avatar Bryan Schumaker Committed by Trond Myklebust

NFS: Add version registering framework

This patch adds in the code to track multiple versions of the NFS
protocol.  I created default structures for v2, v3 and v4 so that each
version can continue to work while I convert them into kernel modules.
I also removed the const parameter from the rpc_version array so that I
can change it at runtime.
Signed-off-by: default avatarBryan Schumaker <bjschuma@netapp.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent a427b9ec
...@@ -9,8 +9,8 @@ nfs-y := client.o dir.o file.o getroot.o inode.o super.o \ ...@@ -9,8 +9,8 @@ nfs-y := client.o dir.o file.o getroot.o inode.o super.o \
write.o namespace.o mount_clnt.o \ write.o namespace.o mount_clnt.o \
dns_resolve.o cache_lib.o dns_resolve.o cache_lib.o
nfs-$(CONFIG_ROOT_NFS) += nfsroot.o nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
nfs-$(CONFIG_NFS_V2) += proc.o nfs2xdr.o nfs-$(CONFIG_NFS_V2) += nfs2super.o proc.o nfs2xdr.o
nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o nfs-$(CONFIG_NFS_V3) += nfs3super.o nfs3proc.o nfs3xdr.o
nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
nfs4super.o nfs4file.o delegation.o idmap.o \ nfs4super.o nfs4file.o delegation.o idmap.o \
......
...@@ -51,25 +51,23 @@ ...@@ -51,25 +51,23 @@
#include "internal.h" #include "internal.h"
#include "fscache.h" #include "fscache.h"
#include "pnfs.h" #include "pnfs.h"
#include "nfs.h"
#include "netns.h" #include "netns.h"
#define NFSDBG_FACILITY NFSDBG_CLIENT #define NFSDBG_FACILITY NFSDBG_CLIENT
static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
static DEFINE_SPINLOCK(nfs_version_lock);
static DEFINE_MUTEX(nfs_version_mutex);
static LIST_HEAD(nfs_versions);
/* /*
* RPC cruft for NFS * RPC cruft for NFS
*/ */
static const struct rpc_version *nfs_version[5] = { static const struct rpc_version *nfs_version[5] = {
#ifdef CONFIG_NFS_V2 [2] = NULL,
[2] = &nfs_version2, [3] = NULL,
#endif [4] = NULL,
#ifdef CONFIG_NFS_V3
[3] = &nfs_version3,
#endif
#ifdef CONFIG_NFS_V4
[4] = &nfs_version4,
#endif
}; };
const struct rpc_program nfs_program = { const struct rpc_program nfs_program = {
...@@ -101,6 +99,93 @@ const struct rpc_program nfsacl_program = { ...@@ -101,6 +99,93 @@ const struct rpc_program nfsacl_program = {
}; };
#endif /* CONFIG_NFS_V3_ACL */ #endif /* CONFIG_NFS_V3_ACL */
static struct nfs_subversion *find_nfs_version(unsigned int version)
{
struct nfs_subversion *nfs;
spin_lock(&nfs_version_lock);
list_for_each_entry(nfs, &nfs_versions, list) {
if (nfs->rpc_ops->version == version) {
spin_unlock(&nfs_version_lock);
return nfs;
}
};
spin_unlock(&nfs_version_lock);
return ERR_PTR(-EPROTONOSUPPORT);;
}
struct nfs_subversion *get_nfs_version(unsigned int version)
{
struct nfs_subversion *nfs = find_nfs_version(version);
if (IS_ERR(nfs)) {
mutex_lock(&nfs_version_mutex);
request_module("nfs%d", version);
nfs = find_nfs_version(version);
mutex_unlock(&nfs_version_mutex);
}
if (!IS_ERR(nfs))
try_module_get(nfs->owner);
return nfs;
}
void put_nfs_version(struct nfs_subversion *nfs)
{
module_put(nfs->owner);
}
void register_nfs_version(struct nfs_subversion *nfs)
{
spin_lock(&nfs_version_lock);
list_add(&nfs->list, &nfs_versions);
nfs_version[nfs->rpc_ops->version] = nfs->rpc_vers;
spin_unlock(&nfs_version_lock);
}
EXPORT_SYMBOL_GPL(register_nfs_version);
void unregister_nfs_version(struct nfs_subversion *nfs)
{
spin_lock(&nfs_version_lock);
nfs_version[nfs->rpc_ops->version] = NULL;
list_del(&nfs->list);
spin_unlock(&nfs_version_lock);
}
EXPORT_SYMBOL_GPL(unregister_nfs_version);
/*
* Preload all configured NFS versions during module init.
* This function should be edited after each protocol is converted,
* and eventually removed.
*/
int __init nfs_register_versions(void)
{
int err = init_nfs_v2();
if (err)
return err;
err = init_nfs_v3();
if (err)
return err;
return init_nfs_v4();
}
/*
* Remove each pre-loaded NFS version
*/
void nfs_unregister_versions(void)
{
exit_nfs_v2();
exit_nfs_v3();
exit_nfs_v4();
}
/* /*
* Allocate a shared client record * Allocate a shared client record
* *
...@@ -116,7 +201,10 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) ...@@ -116,7 +201,10 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
goto error_0; goto error_0;
clp->rpc_ops = cl_init->rpc_ops; clp->cl_nfs_mod = cl_init->nfs_mod;
try_module_get(clp->cl_nfs_mod->owner);
clp->rpc_ops = clp->cl_nfs_mod->rpc_ops;
atomic_set(&clp->cl_count, 1); atomic_set(&clp->cl_count, 1);
clp->cl_cons_state = NFS_CS_INITING; clp->cl_cons_state = NFS_CS_INITING;
...@@ -145,6 +233,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) ...@@ -145,6 +233,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
return clp; return clp;
error_cleanup: error_cleanup:
put_nfs_version(clp->cl_nfs_mod);
kfree(clp); kfree(clp);
error_0: error_0:
return ERR_PTR(err); return ERR_PTR(err);
...@@ -205,6 +294,7 @@ void nfs_free_client(struct nfs_client *clp) ...@@ -205,6 +294,7 @@ void nfs_free_client(struct nfs_client *clp)
put_rpccred(clp->cl_machine_cred); put_rpccred(clp->cl_machine_cred);
put_net(clp->cl_net); put_net(clp->cl_net);
put_nfs_version(clp->cl_nfs_mod);
kfree(clp->cl_hostname); kfree(clp->cl_hostname);
kfree(clp); kfree(clp);
...@@ -362,7 +452,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat ...@@ -362,7 +452,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
continue; continue;
/* Different NFS versions cannot share the same nfs_client */ /* Different NFS versions cannot share the same nfs_client */
if (clp->rpc_ops != data->rpc_ops) if (clp->rpc_ops != data->nfs_mod->rpc_ops)
continue; continue;
if (clp->cl_proto != data->proto) if (clp->cl_proto != data->proto)
...@@ -431,9 +521,10 @@ nfs_get_client(const struct nfs_client_initdata *cl_init, ...@@ -431,9 +521,10 @@ nfs_get_client(const struct nfs_client_initdata *cl_init,
{ {
struct nfs_client *clp, *new = NULL; struct nfs_client *clp, *new = NULL;
struct nfs_net *nn = net_generic(cl_init->net, nfs_net_id); struct nfs_net *nn = net_generic(cl_init->net, nfs_net_id);
const struct nfs_rpc_ops *rpc_ops = cl_init->nfs_mod->rpc_ops;
dprintk("--> nfs_get_client(%s,v%u)\n", dprintk("--> nfs_get_client(%s,v%u)\n",
cl_init->hostname ?: "", cl_init->rpc_ops->version); cl_init->hostname ?: "", rpc_ops->version);
/* see if the client already exists */ /* see if the client already exists */
do { do {
...@@ -450,14 +541,13 @@ nfs_get_client(const struct nfs_client_initdata *cl_init, ...@@ -450,14 +541,13 @@ nfs_get_client(const struct nfs_client_initdata *cl_init,
list_add(&new->cl_share_link, &nn->nfs_client_list); list_add(&new->cl_share_link, &nn->nfs_client_list);
spin_unlock(&nn->nfs_client_lock); spin_unlock(&nn->nfs_client_lock);
new->cl_flags = cl_init->init_flags; new->cl_flags = cl_init->init_flags;
return cl_init->rpc_ops->init_client(new, return rpc_ops->init_client(new, timeparms, ip_addr,
timeparms, ip_addr, authflavour);
authflavour);
} }
spin_unlock(&nn->nfs_client_lock); spin_unlock(&nn->nfs_client_lock);
new = cl_init->rpc_ops->alloc_client(cl_init); new = rpc_ops->alloc_client(cl_init);
} while (!IS_ERR(new)); } while (!IS_ERR(new));
dprintk("<-- nfs_get_client() Failed to find %s (%ld)\n", dprintk("<-- nfs_get_client() Failed to find %s (%ld)\n",
...@@ -714,13 +804,14 @@ struct nfs_client *nfs_init_client(struct nfs_client *clp, ...@@ -714,13 +804,14 @@ struct nfs_client *nfs_init_client(struct nfs_client *clp,
* Create a version 2 or 3 client * Create a version 2 or 3 client
*/ */
static int nfs_init_server(struct nfs_server *server, static int nfs_init_server(struct nfs_server *server,
const struct nfs_parsed_mount_data *data) const struct nfs_parsed_mount_data *data,
struct nfs_subversion *nfs_mod)
{ {
struct nfs_client_initdata cl_init = { struct nfs_client_initdata cl_init = {
.hostname = data->nfs_server.hostname, .hostname = data->nfs_server.hostname,
.addr = (const struct sockaddr *)&data->nfs_server.address, .addr = (const struct sockaddr *)&data->nfs_server.address,
.addrlen = data->nfs_server.addrlen, .addrlen = data->nfs_server.addrlen,
.rpc_ops = NULL, .nfs_mod = nfs_mod,
.proto = data->nfs_server.protocol, .proto = data->nfs_server.protocol,
.net = data->net, .net = data->net,
}; };
...@@ -730,21 +821,6 @@ static int nfs_init_server(struct nfs_server *server, ...@@ -730,21 +821,6 @@ static int nfs_init_server(struct nfs_server *server,
dprintk("--> nfs_init_server()\n"); dprintk("--> nfs_init_server()\n");
switch (data->version) {
#ifdef CONFIG_NFS_V2
case 2:
cl_init.rpc_ops = &nfs_v2_clientops;
break;
#endif
#ifdef CONFIG_NFS_V3
case 3:
cl_init.rpc_ops = &nfs_v3_clientops;
break;
#endif
default:
return -EPROTONOSUPPORT;
}
nfs_init_timeout_values(&timeparms, data->nfs_server.protocol, nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
data->timeo, data->retrans); data->timeo, data->retrans);
if (data->flags & NFS_MOUNT_NORESVPORT) if (data->flags & NFS_MOUNT_NORESVPORT)
...@@ -1033,7 +1109,8 @@ void nfs_free_server(struct nfs_server *server) ...@@ -1033,7 +1109,8 @@ void nfs_free_server(struct nfs_server *server)
* - keyed on server and FSID * - keyed on server and FSID
*/ */
struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data, struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
struct nfs_fh *mntfh) struct nfs_fh *mntfh,
struct nfs_subversion *nfs_mod)
{ {
struct nfs_server *server; struct nfs_server *server;
struct nfs_fattr *fattr; struct nfs_fattr *fattr;
...@@ -1049,7 +1126,7 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data, ...@@ -1049,7 +1126,7 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
goto error; goto error;
/* Get a client representation */ /* Get a client representation */
error = nfs_init_server(server, data); error = nfs_init_server(server, data, nfs_mod);
if (error < 0) if (error < 0)
goto error; goto error;
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#include "fscache.h" #include "fscache.h"
#include "dns_resolve.h" #include "dns_resolve.h"
#include "pnfs.h" #include "pnfs.h"
#include "nfs.h"
#include "netns.h" #include "netns.h"
#define NFSDBG_FACILITY NFSDBG_VFS #define NFSDBG_FACILITY NFSDBG_VFS
...@@ -1671,21 +1672,17 @@ static int __init init_nfs_fs(void) ...@@ -1671,21 +1672,17 @@ static int __init init_nfs_fs(void)
rpc_proc_register(&init_net, &nfs_rpcstat); rpc_proc_register(&init_net, &nfs_rpcstat);
#endif #endif
#ifdef CONFIG_NFS_V4 err = nfs_register_versions();
err = init_nfs_v4();
if (err) if (err)
goto out1; goto out1;
#endif
if ((err = register_nfs_fs()) != 0) if ((err = register_nfs_fs()) != 0)
goto out0; goto out0;
return 0; return 0;
out0: out0:
#ifdef CONFIG_NFS_V4 nfs_unregister_versions();
exit_nfs_v4();
out1: out1:
#endif
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
rpc_proc_unregister(&init_net, "nfs"); rpc_proc_unregister(&init_net, "nfs");
#endif #endif
......
...@@ -90,7 +90,7 @@ struct nfs_client_initdata { ...@@ -90,7 +90,7 @@ struct nfs_client_initdata {
const char *hostname; const char *hostname;
const struct sockaddr *addr; const struct sockaddr *addr;
size_t addrlen; size_t addrlen;
const struct nfs_rpc_ops *rpc_ops; struct nfs_subversion *nfs_mod;
int proto; int proto;
u32 minorversion; u32 minorversion;
struct net *net; struct net *net;
...@@ -189,7 +189,8 @@ nfs4_find_client_sessionid(struct net *, const struct sockaddr *, ...@@ -189,7 +189,8 @@ nfs4_find_client_sessionid(struct net *, const struct sockaddr *,
struct nfs4_sessionid *); struct nfs4_sessionid *);
extern struct nfs_server *nfs_create_server( extern struct nfs_server *nfs_create_server(
const struct nfs_parsed_mount_data *, const struct nfs_parsed_mount_data *,
struct nfs_fh *); struct nfs_fh *,
struct nfs_subversion *);
extern struct nfs_server *nfs4_create_server( extern struct nfs_server *nfs4_create_server(
const struct nfs_parsed_mount_data *, const struct nfs_parsed_mount_data *,
struct nfs_fh *); struct nfs_fh *);
...@@ -321,6 +322,7 @@ void nfs_zap_acl_cache(struct inode *inode); ...@@ -321,6 +322,7 @@ void nfs_zap_acl_cache(struct inode *inode);
extern int nfs_wait_bit_killable(void *word); extern int nfs_wait_bit_killable(void *word);
/* super.c */ /* super.c */
extern struct file_system_type nfs_fs_type;
extern struct file_system_type nfs_xdev_fs_type; extern struct file_system_type nfs_xdev_fs_type;
#ifdef CONFIG_NFS_V4 #ifdef CONFIG_NFS_V4
extern struct file_system_type nfs4_xdev_fs_type; extern struct file_system_type nfs4_xdev_fs_type;
...@@ -329,8 +331,8 @@ extern struct file_system_type nfs4_referral_fs_type; ...@@ -329,8 +331,8 @@ extern struct file_system_type nfs4_referral_fs_type;
void nfs_initialise_sb(struct super_block *); void nfs_initialise_sb(struct super_block *);
int nfs_set_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *); 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 *); 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 *, struct dentry *nfs_fs_mount_common(struct nfs_server *, int, const char *,
int, const char *, struct nfs_mount_info *); struct nfs_mount_info *, struct nfs_subversion *);
struct dentry *nfs_fs_mount(struct file_system_type *, int, const char *, void *); struct dentry *nfs_fs_mount(struct file_system_type *, int, const char *, void *);
struct dentry * nfs_xdev_mount_common(struct file_system_type *, int, struct dentry * nfs_xdev_mount_common(struct file_system_type *, int,
const char *, struct nfs_mount_info *); const char *, struct nfs_mount_info *);
......
/*
* Copyright (c) 2012 Netapp, Inc. All rights reserved.
*
* Function and structures exported by the NFS module
* for use by NFS version-specific modules.
*/
#ifndef __LINUX_INTERNAL_NFS_H
#define __LINUX_INTERNAL_NFS_H
#include <linux/fs.h>
#include <linux/sunrpc/sched.h>
#include <linux/nfs_xdr.h>
struct nfs_subversion {
struct module *owner; /* THIS_MODULE pointer */
struct file_system_type *nfs_fs; /* NFS filesystem type */
const struct rpc_version *rpc_vers; /* NFS version information */
const struct nfs_rpc_ops *rpc_ops; /* NFS operations */
struct list_head list; /* List of NFS versions */
};
int nfs_register_versions(void);
void nfs_unregister_versions(void);
#ifdef CONFIG_NFS_V2
int init_nfs_v2(void);
void exit_nfs_v2(void);
#else /* CONFIG_NFS_V2 */
static inline int __init init_nfs_v2(void)
{
return 0;
}
static inline void exit_nfs_v2(void)
{
}
#endif /* CONFIG_NFS_V2 */
#ifdef CONFIG_NFS_V3
int init_nfs_v3(void);
void exit_nfs_v3(void);
#else /* CONFIG_NFS_V3 */
static inline int __init init_nfs_v3(void)
{
return 0;
}
static inline void exit_nfs_v3(void)
{
}
#endif /* CONFIG_NFS_V3 */
#ifdef CONFIG_NFS_V4
int init_nfs_v4(void);
void exit_nfs_v4(void);
#else /* CONFIG_NFS_V4 */
static inline int __init init_nfs_v4(void)
{
return 0;
}
static inline void exit_nfs_v4(void)
{
}
#endif /* CONFIG_NFS_V4 */
struct nfs_subversion *get_nfs_version(unsigned int);
void put_nfs_version(struct nfs_subversion *);
void register_nfs_version(struct nfs_subversion *);
void unregister_nfs_version(struct nfs_subversion *);
#endif /* __LINUX_INTERNAL_NFS_H */
/*
* Copyright (c) 2012 Netapp, Inc. All rights reserved.
*/
#include <linux/module.h>
#include <linux/nfs_fs.h>
#include "internal.h"
#include "nfs.h"
static struct nfs_subversion nfs_v2 = {
.owner = THIS_MODULE,
.nfs_fs = &nfs_fs_type,
.rpc_vers = &nfs_version2,
.rpc_ops = &nfs_v2_clientops,
};
int __init init_nfs_v2(void)
{
register_nfs_version(&nfs_v2);
return 0;
}
void exit_nfs_v2(void)
{
unregister_nfs_version(&nfs_v2);
}
/*
* Copyright (c) 2012 Netapp, Inc. All rights reserved.
*/
#include <linux/module.h>
#include <linux/nfs_fs.h>
#include "internal.h"
#include "nfs.h"
static struct nfs_subversion nfs_v3 = {
.owner = THIS_MODULE,
.nfs_fs = &nfs_fs_type,
.rpc_vers = &nfs_version3,
.rpc_ops = &nfs_v3_clientops,
};
int __init init_nfs_v3(void)
{
register_nfs_version(&nfs_v3);
return 0;
}
void exit_nfs_v3(void)
{
unregister_nfs_version(&nfs_v3);
}
...@@ -366,6 +366,7 @@ extern const nfs4_stateid zero_stateid; ...@@ -366,6 +366,7 @@ extern const nfs4_stateid zero_stateid;
/* nfs4super.c */ /* nfs4super.c */
struct nfs_mount_info; struct nfs_mount_info;
extern struct nfs_subversion nfs_v4;
struct dentry *nfs4_try_mount(int, const char *, struct nfs_mount_info *); struct dentry *nfs4_try_mount(int, const char *, struct nfs_mount_info *);
int init_nfs_v4(void); int init_nfs_v4(void);
void exit_nfs_v4(void); void exit_nfs_v4(void);
......
...@@ -357,7 +357,7 @@ static int nfs4_set_client(struct nfs_server *server, ...@@ -357,7 +357,7 @@ static int nfs4_set_client(struct nfs_server *server,
.hostname = hostname, .hostname = hostname,
.addr = addr, .addr = addr,
.addrlen = addrlen, .addrlen = addrlen,
.rpc_ops = &nfs_v4_clientops, .nfs_mod = &nfs_v4,
.proto = proto, .proto = proto,
.minorversion = minorversion, .minorversion = minorversion,
.net = net, .net = net,
...@@ -411,7 +411,7 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp, ...@@ -411,7 +411,7 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
struct nfs_client_initdata cl_init = { struct nfs_client_initdata cl_init = {
.addr = ds_addr, .addr = ds_addr,
.addrlen = ds_addrlen, .addrlen = ds_addrlen,
.rpc_ops = &nfs_v4_clientops, .nfs_mod = &nfs_v4,
.proto = ds_proto, .proto = ds_proto,
.minorversion = mds_clp->cl_minorversion, .minorversion = mds_clp->cl_minorversion,
.net = mds_clp->cl_net, .net = mds_clp->cl_net,
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/nfs_fs.h> #include <linux/nfs_fs.h>
#include "internal.h" #include "internal.h"
#include "nfs4_fs.h" #include "nfs4_fs.h"
#include "nfs.h"
#define NFSDBG_FACILITY NFSDBG_VFS #define NFSDBG_FACILITY NFSDBG_VFS
...@@ -75,6 +76,13 @@ static const struct super_operations nfs4_sops = { ...@@ -75,6 +76,13 @@ static const struct super_operations nfs4_sops = {
.remount_fs = nfs_remount, .remount_fs = nfs_remount,
}; };
struct nfs_subversion nfs_v4 = {
.owner = THIS_MODULE,
.nfs_fs = &nfs4_fs_type,
.rpc_vers = &nfs_version4,
.rpc_ops = &nfs_v4_clientops,
};
/* /*
* Set up an NFS4 superblock * Set up an NFS4 superblock
*/ */
...@@ -113,7 +121,7 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags, ...@@ -113,7 +121,7 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags,
goto out; goto out;
} }
mntroot = nfs_fs_mount_common(fs_type, server, flags, dev_name, mount_info); mntroot = nfs_fs_mount_common(server, flags, dev_name, mount_info, &nfs_v4);
out: out:
return mntroot; return mntroot;
...@@ -293,7 +301,7 @@ nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags, ...@@ -293,7 +301,7 @@ nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
goto out; goto out;
} }
mntroot = nfs_fs_mount_common(&nfs4_fs_type, server, flags, dev_name, &mount_info); mntroot = nfs_fs_mount_common(server, flags, dev_name, &mount_info, &nfs_v4);
out: out:
nfs_free_fhandle(mount_info.mntfh); nfs_free_fhandle(mount_info.mntfh);
return mntroot; return mntroot;
...@@ -343,6 +351,7 @@ int __init init_nfs_v4(void) ...@@ -343,6 +351,7 @@ int __init init_nfs_v4(void)
if (err < 0) if (err < 0)
goto out2; goto out2;
register_nfs_version(&nfs_v4);
return 0; return 0;
out2: out2:
nfs4_unregister_sysctl(); nfs4_unregister_sysctl();
...@@ -354,6 +363,7 @@ int __init init_nfs_v4(void) ...@@ -354,6 +363,7 @@ int __init init_nfs_v4(void)
void exit_nfs_v4(void) void exit_nfs_v4(void)
{ {
unregister_nfs_version(&nfs_v4);
unregister_filesystem(&nfs4_fs_type); unregister_filesystem(&nfs4_fs_type);
nfs4_unregister_sysctl(); nfs4_unregister_sysctl();
nfs_idmap_quit(); nfs_idmap_quit();
......
...@@ -64,6 +64,7 @@ ...@@ -64,6 +64,7 @@
#include "internal.h" #include "internal.h"
#include "fscache.h" #include "fscache.h"
#include "pnfs.h" #include "pnfs.h"
#include "nfs.h"
#define NFSDBG_FACILITY NFSDBG_VFS #define NFSDBG_FACILITY NFSDBG_VFS
#define NFS_TEXT_DATA 1 #define NFS_TEXT_DATA 1
...@@ -281,7 +282,7 @@ static match_table_t nfs_vers_tokens = { ...@@ -281,7 +282,7 @@ static match_table_t nfs_vers_tokens = {
static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type, static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data); int flags, const char *dev_name, void *raw_data);
static struct file_system_type nfs_fs_type = { struct file_system_type nfs_fs_type = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "nfs", .name = "nfs",
.mount = nfs_fs_mount, .mount = nfs_fs_mount,
...@@ -1650,7 +1651,8 @@ static int nfs_request_mount(struct nfs_parsed_mount_data *args, ...@@ -1650,7 +1651,8 @@ static int nfs_request_mount(struct nfs_parsed_mount_data *args,
} }
static struct dentry *nfs_try_mount(int flags, const char *dev_name, static struct dentry *nfs_try_mount(int flags, const char *dev_name,
struct nfs_mount_info *mount_info) struct nfs_mount_info *mount_info,
struct nfs_subversion *nfs_mod)
{ {
int status; int status;
struct nfs_server *server; struct nfs_server *server;
...@@ -1662,11 +1664,11 @@ static struct dentry *nfs_try_mount(int flags, const char *dev_name, ...@@ -1662,11 +1664,11 @@ static struct dentry *nfs_try_mount(int flags, const char *dev_name,
} }
/* Get a volume representation */ /* Get a volume representation */
server = nfs_create_server(mount_info->parsed, mount_info->mntfh); server = nfs_create_server(mount_info->parsed, mount_info->mntfh, nfs_mod);
if (IS_ERR(server)) if (IS_ERR(server))
return ERR_CAST(server); return ERR_CAST(server);
return nfs_fs_mount_common(&nfs_fs_type, server, flags, dev_name, mount_info); return nfs_fs_mount_common(server, flags, dev_name, mount_info, nfs_mod);
} }
/* /*
...@@ -2297,10 +2299,10 @@ int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot, ...@@ -2297,10 +2299,10 @@ int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot,
return 0; return 0;
} }
struct dentry *nfs_fs_mount_common(struct file_system_type *fs_type, struct dentry *nfs_fs_mount_common(struct nfs_server *server,
struct nfs_server *server,
int flags, const char *dev_name, int flags, const char *dev_name,
struct nfs_mount_info *mount_info) struct nfs_mount_info *mount_info,
struct nfs_subversion *nfs_mod)
{ {
struct super_block *s; struct super_block *s;
struct dentry *mntroot = ERR_PTR(-ENOMEM); struct dentry *mntroot = ERR_PTR(-ENOMEM);
...@@ -2319,7 +2321,7 @@ struct dentry *nfs_fs_mount_common(struct file_system_type *fs_type, ...@@ -2319,7 +2321,7 @@ struct dentry *nfs_fs_mount_common(struct file_system_type *fs_type,
sb_mntdata.mntflags |= MS_SYNCHRONOUS; sb_mntdata.mntflags |= MS_SYNCHRONOUS;
/* Get a superblock - note that we may end up sharing one that already exists */ /* Get a superblock - note that we may end up sharing one that already exists */
s = sget(fs_type, compare_super, nfs_set_super, flags, &sb_mntdata); s = sget(nfs_mod->nfs_fs, compare_super, nfs_set_super, flags, &sb_mntdata);
if (IS_ERR(s)) { if (IS_ERR(s)) {
mntroot = ERR_CAST(s); mntroot = ERR_CAST(s);
goto out_err_nosb; goto out_err_nosb;
...@@ -2378,6 +2380,7 @@ struct dentry *nfs_fs_mount(struct file_system_type *fs_type, ...@@ -2378,6 +2380,7 @@ struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
.set_security = nfs_set_sb_security, .set_security = nfs_set_sb_security,
}; };
struct dentry *mntroot = ERR_PTR(-ENOMEM); struct dentry *mntroot = ERR_PTR(-ENOMEM);
struct nfs_subversion *nfs_mod;
int error; int error;
mount_info.parsed = nfs_alloc_parsed_mount_data(); mount_info.parsed = nfs_alloc_parsed_mount_data();
...@@ -2394,12 +2397,20 @@ struct dentry *nfs_fs_mount(struct file_system_type *fs_type, ...@@ -2394,12 +2397,20 @@ struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
goto out; goto out;
} }
nfs_mod = get_nfs_version(mount_info.parsed->version);
if (IS_ERR(nfs_mod)) {
mntroot = ERR_CAST(nfs_mod);
goto out;
}
#ifdef CONFIG_NFS_V4 #ifdef CONFIG_NFS_V4
if (mount_info.parsed->version == 4) if (mount_info.parsed->version == 4)
mntroot = nfs4_try_mount(flags, dev_name, &mount_info); mntroot = nfs4_try_mount(flags, dev_name, &mount_info);
else else
#endif /* CONFIG_NFS_V4 */ #endif /* CONFIG_NFS_V4 */
mntroot = nfs_try_mount(flags, dev_name, &mount_info); mntroot = nfs_try_mount(flags, dev_name, &mount_info, nfs_mod);
put_nfs_version(nfs_mod);
out: out:
nfs_free_parsed_mount_data(mount_info.parsed); nfs_free_parsed_mount_data(mount_info.parsed);
...@@ -2440,6 +2451,7 @@ nfs_xdev_mount_common(struct file_system_type *fs_type, int flags, ...@@ -2440,6 +2451,7 @@ nfs_xdev_mount_common(struct file_system_type *fs_type, int flags,
struct nfs_clone_mount *data = mount_info->cloned; struct nfs_clone_mount *data = mount_info->cloned;
struct nfs_server *server; struct nfs_server *server;
struct dentry *mntroot = ERR_PTR(-ENOMEM); struct dentry *mntroot = ERR_PTR(-ENOMEM);
struct nfs_subversion *nfs_mod = NFS_SB(data->sb)->nfs_client->cl_nfs_mod;
int error; int error;
dprintk("--> nfs_xdev_mount_common()\n"); dprintk("--> nfs_xdev_mount_common()\n");
...@@ -2453,7 +2465,7 @@ nfs_xdev_mount_common(struct file_system_type *fs_type, int flags, ...@@ -2453,7 +2465,7 @@ nfs_xdev_mount_common(struct file_system_type *fs_type, int flags,
goto out_err; goto out_err;
} }
mntroot = nfs_fs_mount_common(fs_type, server, flags, dev_name, mount_info); mntroot = nfs_fs_mount_common(server, flags, dev_name, mount_info, nfs_mod);
dprintk("<-- nfs_xdev_mount_common() = 0\n"); dprintk("<-- nfs_xdev_mount_common() = 0\n");
out: out:
return mntroot; return mntroot;
......
...@@ -48,6 +48,7 @@ struct nfs_client { ...@@ -48,6 +48,7 @@ struct nfs_client {
struct rpc_clnt * cl_rpcclient; struct rpc_clnt * cl_rpcclient;
const struct nfs_rpc_ops *rpc_ops; /* NFS protocol vector */ const struct nfs_rpc_ops *rpc_ops; /* NFS protocol vector */
int cl_proto; /* Network transport protocol */ int cl_proto; /* Network transport protocol */
struct nfs_subversion * cl_nfs_mod; /* pointer to nfs version module */
u32 cl_minorversion;/* NFSv4 minorversion */ u32 cl_minorversion;/* NFSv4 minorversion */
struct rpc_cred *cl_machine_cred; struct rpc_cred *cl_machine_cred;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment