NFS: use in-kernel mount argument structure for nfsv[23] mounts

The user-visible nfs_mount_data does not contain sufficient data to
describe new mount options, and also is now a legacy structure. Replace
it with the internal nfs_parsed_mount_data for nfsv[23] in-kernel use.

Signed-off-by: Tom Talpey <tmt@netapp.com>
Acked-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
\"Talpey, Thomas\ 2007-09-10 13:43:56 -04:00 committed by Trond Myklebust
parent 6b18eaa082
commit 2283f8d6ed
3 changed files with 70 additions and 75 deletions

View file

@ -501,9 +501,9 @@ static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t
/*
* Initialise an NFS2 or NFS3 client
*/
static int nfs_init_client(struct nfs_client *clp, const struct nfs_mount_data *data)
static int nfs_init_client(struct nfs_client *clp,
const struct nfs_parsed_mount_data *data)
{
int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
int error;
if (clp->cl_cons_state == NFS_CS_READY) {
@ -522,8 +522,8 @@ static int nfs_init_client(struct nfs_client *clp, const struct nfs_mount_data *
* Create a client RPC handle for doing FSSTAT with UNIX auth only
* - RFC 2623, sec 2.3.2
*/
error = nfs_create_rpc_client(clp, proto, data->timeo, data->retrans,
RPC_AUTH_UNIX, 0);
error = nfs_create_rpc_client(clp, data->nfs_server.protocol,
data->timeo, data->retrans, RPC_AUTH_UNIX, 0);
if (error < 0)
goto error;
nfs_mark_client_ready(clp, NFS_CS_READY);
@ -538,7 +538,8 @@ error:
/*
* Create a version 2 or 3 client
*/
static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_data *data)
static int nfs_init_server(struct nfs_server *server,
const struct nfs_parsed_mount_data *data)
{
struct nfs_client *clp;
int error, nfsvers = 2;
@ -551,7 +552,8 @@ static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_dat
#endif
/* Allocate or find a client reference we can use */
clp = nfs_get_client(data->hostname, &data->addr, nfsvers);
clp = nfs_get_client(data->nfs_server.hostname,
&data->nfs_server.address, nfsvers);
if (IS_ERR(clp)) {
dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp));
return PTR_ERR(clp);
@ -581,7 +583,7 @@ static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_dat
if (error < 0)
goto error;
error = nfs_init_server_rpcclient(server, data->pseudoflavor);
error = nfs_init_server_rpcclient(server, data->auth_flavors[0]);
if (error < 0)
goto error;
@ -760,7 +762,7 @@ void nfs_free_server(struct nfs_server *server)
* Create a version 2 or 3 volume record
* - keyed on server and FSID
*/
struct nfs_server *nfs_create_server(const struct nfs_mount_data *data,
struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
struct nfs_fh *mntfh)
{
struct nfs_server *server;

View file

@ -5,7 +5,6 @@
#include <linux/mount.h>
struct nfs_string;
struct nfs_mount_data;
struct nfs4_mount_data;
/* Maximum number of readahead requests
@ -65,8 +64,9 @@ extern struct rpc_program nfs_program;
extern void nfs_put_client(struct nfs_client *);
extern struct nfs_client *nfs_find_client(const struct sockaddr_in *, int);
extern struct nfs_server *nfs_create_server(const struct nfs_mount_data *,
struct nfs_fh *);
extern struct nfs_server *nfs_create_server(
const struct nfs_parsed_mount_data *,
struct nfs_fh *);
extern struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *,
const char *,
const struct sockaddr_in *,

View file

@ -1041,15 +1041,31 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
* XXX: as far as I can tell, changing the NFS program number is not
* supported in the NFS client.
*/
static int nfs_validate_mount_data(struct nfs_mount_data **options,
static int nfs_validate_mount_data(void *options,
struct nfs_parsed_mount_data *args,
struct nfs_fh *mntfh,
const char *dev_name)
{
struct nfs_mount_data *data = *options;
struct nfs_mount_data *data = (struct nfs_mount_data *)options;
if (data == NULL)
goto out_no_data;
memset(args, 0, sizeof(*args));
args->flags = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP);
args->rsize = NFS_MAX_FILE_IO_SIZE;
args->wsize = NFS_MAX_FILE_IO_SIZE;
args->timeo = 600;
args->retrans = 2;
args->acregmin = 3;
args->acregmax = 60;
args->acdirmin = 30;
args->acdirmax = 60;
args->mount_server.protocol = IPPROTO_UDP;
args->mount_server.program = NFS_MNT_PROGRAM;
args->nfs_server.protocol = IPPROTO_TCP;
args->nfs_server.program = NFS_PROGRAM;
switch (data->version) {
case 1:
data->namlen = 0;
@ -1078,90 +1094,67 @@ static int nfs_validate_mount_data(struct nfs_mount_data **options,
if (mntfh->size < sizeof(mntfh->data))
memset(mntfh->data + mntfh->size, 0,
sizeof(mntfh->data) - mntfh->size);
/*
* Translate to nfs_parsed_mount_data, which nfs_fill_super
* can deal with.
*/
args->flags = data->flags;
args->rsize = data->rsize;
args->wsize = data->wsize;
args->flags = data->flags;
args->timeo = data->timeo;
args->retrans = data->retrans;
args->acregmin = data->acregmin;
args->acregmax = data->acregmax;
args->acdirmin = data->acdirmin;
args->acdirmax = data->acdirmax;
args->nfs_server.address = data->addr;
if (!(data->flags & NFS_MOUNT_TCP))
args->nfs_server.protocol = IPPROTO_UDP;
/* N.B. caller will free nfs_server.hostname in all cases */
args->nfs_server.hostname = kstrdup(data->hostname, GFP_KERNEL);
args->namlen = data->namlen;
args->bsize = data->bsize;
args->auth_flavors[0] = data->pseudoflavor;
break;
default: {
unsigned int len;
char *c;
int status;
struct nfs_parsed_mount_data args = {
.flags = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP),
.rsize = NFS_MAX_FILE_IO_SIZE,
.wsize = NFS_MAX_FILE_IO_SIZE,
.timeo = 600,
.retrans = 2,
.acregmin = 3,
.acregmax = 60,
.acdirmin = 30,
.acdirmax = 60,
.mount_server.protocol = IPPROTO_UDP,
.mount_server.program = NFS_MNT_PROGRAM,
.nfs_server.protocol = IPPROTO_TCP,
.nfs_server.program = NFS_PROGRAM,
};
if (nfs_parse_mount_options((char *) *options, &args) == 0)
if (nfs_parse_mount_options((char *)options, args) == 0)
return -EINVAL;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
/*
* NB: after this point, caller will free "data"
* if we return an error
*/
*options = data;
c = strchr(dev_name, ':');
if (c == NULL)
return -EINVAL;
len = c - dev_name;
if (len > sizeof(data->hostname))
return -ENAMETOOLONG;
strncpy(data->hostname, dev_name, len);
args.nfs_server.hostname = data->hostname;
/* N.B. caller will free nfs_server.hostname in all cases */
args->nfs_server.hostname = kstrndup(dev_name, len, GFP_KERNEL);
c++;
if (strlen(c) > NFS_MAXPATHLEN)
return -ENAMETOOLONG;
args.nfs_server.export_path = c;
args->nfs_server.export_path = c;
status = nfs_try_mount(&args, mntfh);
status = nfs_try_mount(args, mntfh);
if (status)
return status;
/*
* Translate to nfs_mount_data, which nfs_fill_super
* can deal with.
*/
data->version = 6;
data->flags = args.flags;
data->rsize = args.rsize;
data->wsize = args.wsize;
data->timeo = args.timeo;
data->retrans = args.retrans;
data->acregmin = args.acregmin;
data->acregmax = args.acregmax;
data->acdirmin = args.acdirmin;
data->acdirmax = args.acdirmax;
data->addr = args.nfs_server.address;
data->namlen = args.namlen;
data->bsize = args.bsize;
data->pseudoflavor = args.auth_flavors[0];
break;
}
}
if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
data->pseudoflavor = RPC_AUTH_UNIX;
if (!(args->flags & NFS_MOUNT_SECFLAVOUR))
args->auth_flavors[0] = RPC_AUTH_UNIX;
#ifndef CONFIG_NFS_V3
if (data->flags & NFS_MOUNT_VER3)
if (args->flags & NFS_MOUNT_VER3)
goto out_v3_not_compiled;
#endif /* !CONFIG_NFS_V3 */
if (!nfs_verify_server_address((struct sockaddr *) &data->addr))
if (!nfs_verify_server_address((struct sockaddr *)
&args->nfs_server.address))
goto out_no_address;
return 0;
@ -1220,7 +1213,8 @@ 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_data *data)
static void nfs_fill_super(struct super_block *sb,
struct nfs_parsed_mount_data *data)
{
struct nfs_server *server = NFS_SB(sb);
@ -1341,7 +1335,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
struct nfs_server *server = NULL;
struct super_block *s;
struct nfs_fh mntfh;
struct nfs_mount_data *data = raw_data;
struct nfs_parsed_mount_data data;
struct dentry *mntroot;
int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
struct nfs_sb_mountdata sb_mntdata = {
@ -1350,12 +1344,12 @@ static int nfs_get_sb(struct file_system_type *fs_type,
int error;
/* Validate the mount data */
error = nfs_validate_mount_data(&data, &mntfh, dev_name);
error = nfs_validate_mount_data(raw_data, &data, &mntfh, dev_name);
if (error < 0)
goto out;
/* Get a volume representation */
server = nfs_create_server(data, &mntfh);
server = nfs_create_server(&data, &mntfh);
if (IS_ERR(server)) {
error = PTR_ERR(server);
goto out;
@ -1379,7 +1373,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
if (!s->s_root) {
/* initial superblock/root creation */
nfs_fill_super(s, data);
nfs_fill_super(s, &data);
}
mntroot = nfs_get_root(s, &mntfh);
@ -1394,8 +1388,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
error = 0;
out:
if (data != raw_data)
kfree(data);
kfree(data.nfs_server.hostname);
return error;
out_err_nosb: