Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2283f8d6 authored by \"Talpey, Thomas\'s avatar \"Talpey, Thomas\ Committed by Trond Myklebust
Browse files

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: default avatarTom Talpey <tmt@netapp.com>
Acked-by: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 6b18eaa0
Loading
Loading
Loading
Loading
+10 −8
Original line number Original line Diff line number Diff line
@@ -501,9 +501,9 @@ static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t
/*
/*
 * Initialise an NFS2 or NFS3 client
 * 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;
	int error;


	if (clp->cl_cons_state == NFS_CS_READY) {
	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
	 * Create a client RPC handle for doing FSSTAT with UNIX auth only
	 * - RFC 2623, sec 2.3.2
	 * - RFC 2623, sec 2.3.2
	 */
	 */
	error = nfs_create_rpc_client(clp, proto, data->timeo, data->retrans,
	error = nfs_create_rpc_client(clp, data->nfs_server.protocol,
					RPC_AUTH_UNIX, 0);
				data->timeo, data->retrans, RPC_AUTH_UNIX, 0);
	if (error < 0)
	if (error < 0)
		goto error;
		goto error;
	nfs_mark_client_ready(clp, NFS_CS_READY);
	nfs_mark_client_ready(clp, NFS_CS_READY);
@@ -538,7 +538,8 @@ static int nfs_init_client(struct nfs_client *clp, const struct nfs_mount_data *
/*
/*
 * Create a version 2 or 3 client
 * 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;
	struct nfs_client *clp;
	int error, nfsvers = 2;
	int error, nfsvers = 2;
@@ -551,7 +552,8 @@ static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_dat
#endif
#endif


	/* Allocate or find a client reference we can use */
	/* 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)) {
	if (IS_ERR(clp)) {
		dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp));
		dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp));
		return 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)
	if (error < 0)
		goto error;
		goto error;


	error = nfs_init_server_rpcclient(server, data->pseudoflavor);
	error = nfs_init_server_rpcclient(server, data->auth_flavors[0]);
	if (error < 0)
	if (error < 0)
		goto error;
		goto error;


@@ -760,7 +762,7 @@ void nfs_free_server(struct nfs_server *server)
 * Create a version 2 or 3 volume record
 * Create a version 2 or 3 volume record
 * - keyed on server and FSID
 * - 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_fh *mntfh)
{
{
	struct nfs_server *server;
	struct nfs_server *server;
+3 −3
Original line number Original line Diff line number Diff line
@@ -5,7 +5,6 @@
#include <linux/mount.h>
#include <linux/mount.h>


struct nfs_string;
struct nfs_string;
struct nfs_mount_data;
struct nfs4_mount_data;
struct nfs4_mount_data;


/* Maximum number of readahead requests
/* Maximum number of readahead requests
@@ -65,7 +64,8 @@ extern struct rpc_program nfs_program;


extern void nfs_put_client(struct nfs_client *);
extern void nfs_put_client(struct nfs_client *);
extern struct nfs_client *nfs_find_client(const struct sockaddr_in *, int);
extern struct nfs_client *nfs_find_client(const struct sockaddr_in *, int);
extern struct nfs_server *nfs_create_server(const struct nfs_mount_data *,
extern struct nfs_server *nfs_create_server(
					const struct nfs_parsed_mount_data *,
					struct nfs_fh *);
					struct nfs_fh *);
extern struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *,
extern struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *,
					     const char *,
					     const char *,
+57 −64
Original line number Original line Diff line number Diff line
@@ -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
 * XXX: as far as I can tell, changing the NFS program number is not
 *      supported in the NFS client.
 *      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,
				   struct nfs_fh *mntfh,
				   const char *dev_name)
				   const char *dev_name)
{
{
	struct nfs_mount_data *data = *options;
	struct nfs_mount_data *data = (struct nfs_mount_data *)options;


	if (data == NULL)
	if (data == NULL)
		goto out_no_data;
		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) {
	switch (data->version) {
	case 1:
	case 1:
		data->namlen = 0;
		data->namlen = 0;
@@ -1078,90 +1094,67 @@ static int nfs_validate_mount_data(struct nfs_mount_data **options,
		if (mntfh->size < sizeof(mntfh->data))
		if (mntfh->size < sizeof(mntfh->data))
			memset(mntfh->data + mntfh->size, 0,
			memset(mntfh->data + mntfh->size, 0,
			       sizeof(mntfh->data) - mntfh->size);
			       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;
		break;
	default: {
	default: {
		unsigned int len;
		unsigned int len;
		char *c;
		char *c;
		int status;
		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;
			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, ':');
		c = strchr(dev_name, ':');
		if (c == NULL)
		if (c == NULL)
			return -EINVAL;
			return -EINVAL;
		len = c - dev_name;
		len = c - dev_name;
		if (len > sizeof(data->hostname))
		/* N.B. caller will free nfs_server.hostname in all cases */
			return -ENAMETOOLONG;
		args->nfs_server.hostname = kstrndup(dev_name, len, GFP_KERNEL);
		strncpy(data->hostname, dev_name, len);
		args.nfs_server.hostname = data->hostname;


		c++;
		c++;
		if (strlen(c) > NFS_MAXPATHLEN)
		if (strlen(c) > NFS_MAXPATHLEN)
			return -ENAMETOOLONG;
			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)
		if (status)
			return 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;
		break;
		}
		}
	}
	}


	if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
	if (!(args->flags & NFS_MOUNT_SECFLAVOUR))
		data->pseudoflavor = RPC_AUTH_UNIX;
		args->auth_flavors[0] = RPC_AUTH_UNIX;


#ifndef CONFIG_NFS_V3
#ifndef CONFIG_NFS_V3
	if (data->flags & NFS_MOUNT_VER3)
	if (args->flags & NFS_MOUNT_VER3)
		goto out_v3_not_compiled;
		goto out_v3_not_compiled;
#endif /* !CONFIG_NFS_V3 */
#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;
		goto out_no_address;


	return 0;
	return 0;
@@ -1220,7 +1213,8 @@ static inline void nfs_initialise_sb(struct super_block *sb)
/*
/*
 * Finish setting up an NFS2/3 superblock
 * 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);
	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 nfs_server *server = NULL;
	struct super_block *s;
	struct super_block *s;
	struct nfs_fh mntfh;
	struct nfs_fh mntfh;
	struct nfs_mount_data *data = raw_data;
	struct nfs_parsed_mount_data data;
	struct dentry *mntroot;
	struct dentry *mntroot;
	int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
	int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
	struct nfs_sb_mountdata sb_mntdata = {
	struct nfs_sb_mountdata sb_mntdata = {
@@ -1350,12 +1344,12 @@ static int nfs_get_sb(struct file_system_type *fs_type,
	int error;
	int error;


	/* Validate the mount data */
	/* 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)
	if (error < 0)
		goto out;
		goto out;


	/* Get a volume representation */
	/* Get a volume representation */
	server = nfs_create_server(data, &mntfh);
	server = nfs_create_server(&data, &mntfh);
	if (IS_ERR(server)) {
	if (IS_ERR(server)) {
		error = PTR_ERR(server);
		error = PTR_ERR(server);
		goto out;
		goto out;
@@ -1379,7 +1373,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,


	if (!s->s_root) {
	if (!s->s_root) {
		/* initial superblock/root creation */
		/* initial superblock/root creation */
		nfs_fill_super(s, data);
		nfs_fill_super(s, &data);
	}
	}


	mntroot = nfs_get_root(s, &mntfh);
	mntroot = nfs_get_root(s, &mntfh);
@@ -1394,8 +1388,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
	error = 0;
	error = 0;


out:
out:
	if (data != raw_data)
	kfree(data.nfs_server.hostname);
		kfree(data);
	return error;
	return error;


out_err_nosb:
out_err_nosb: