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

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

NFS: use in-kernel mount argument structure for nfsv4 mounts



The user-visible nfs4_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 nfsv4 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 2283f8d6
Loading
Loading
Loading
Loading
+12 −12
Original line number Original line Diff line number Diff line
@@ -908,7 +908,7 @@ static int nfs4_set_client(struct nfs_server *server,
 * Create a version 4 volume record
 * Create a version 4 volume record
 */
 */
static int nfs4_init_server(struct nfs_server *server,
static int nfs4_init_server(struct nfs_server *server,
		const struct nfs4_mount_data *data, rpc_authflavor_t authflavour)
		const struct nfs_parsed_mount_data *data)
{
{
	int error;
	int error;


@@ -928,7 +928,7 @@ static int nfs4_init_server(struct nfs_server *server,
	server->acdirmin = data->acdirmin * HZ;
	server->acdirmin = data->acdirmin * HZ;
	server->acdirmax = data->acdirmax * HZ;
	server->acdirmax = data->acdirmax * HZ;


	error = nfs_init_server_rpcclient(server, authflavour);
	error = nfs_init_server_rpcclient(server, data->auth_flavors[0]);


	/* Done */
	/* Done */
	dprintk("<-- nfs4_init_server() = %d\n", error);
	dprintk("<-- nfs4_init_server() = %d\n", error);
@@ -939,12 +939,7 @@ static int nfs4_init_server(struct nfs_server *server,
 * Create a version 4 volume record
 * Create a version 4 volume record
 * - keyed on server and FSID
 * - keyed on server and FSID
 */
 */
struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data,
struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
				      const char *hostname,
				      const struct sockaddr_in *addr,
				      const char *mntpath,
				      const char *ip_addr,
				      rpc_authflavor_t authflavour,
				      struct nfs_fh *mntfh)
				      struct nfs_fh *mntfh)
{
{
	struct nfs_fattr fattr;
	struct nfs_fattr fattr;
@@ -958,13 +953,18 @@ struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data,
		return ERR_PTR(-ENOMEM);
		return ERR_PTR(-ENOMEM);


	/* Get a client record */
	/* Get a client record */
	error = nfs4_set_client(server, hostname, addr, ip_addr, authflavour,
	error = nfs4_set_client(server,
			data->proto, data->timeo, data->retrans);
			data->nfs_server.hostname,
			&data->nfs_server.address,
			data->client_address,
			data->auth_flavors[0],
			data->nfs_server.protocol,
			data->timeo, data->retrans);
	if (error < 0)
	if (error < 0)
		goto error;
		goto error;


	/* set up the general RPC client */
	/* set up the general RPC client */
	error = nfs4_init_server(server, data, authflavour);
	error = nfs4_init_server(server, data);
	if (error < 0)
	if (error < 0)
		goto error;
		goto error;


@@ -973,7 +973,7 @@ struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data,
	BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
	BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);


	/* Probe the root fh to retrieve its FSID */
	/* Probe the root fh to retrieve its FSID */
	error = nfs4_path_walk(server, mntfh, mntpath);
	error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path);
	if (error < 0)
	if (error < 0)
		goto error;
		goto error;


+3 −8
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 nfs4_mount_data;


/* Maximum number of readahead requests
/* Maximum number of readahead requests
 * FIXME: this should really be a sysctl so that users may tune it to suit
 * FIXME: this should really be a sysctl so that users may tune it to suit
@@ -67,12 +66,8 @@ extern struct nfs_client *nfs_find_client(const struct sockaddr_in *, int);
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 *);
extern struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *,
extern struct nfs_server *nfs4_create_server(
					     const char *,
					const struct nfs_parsed_mount_data *,
					     const struct sockaddr_in *,
					     const char *,
					     const char *,
					     rpc_authflavor_t,
					struct nfs_fh *);
					struct nfs_fh *);
extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *,
extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *,
						      struct nfs_fh *);
						      struct nfs_fh *);
+66 −80
Original line number Original line Diff line number Diff line
@@ -1514,38 +1514,49 @@ static void nfs4_fill_super(struct super_block *sb)
/*
/*
 * Validate NFSv4 mount options
 * Validate NFSv4 mount options
 */
 */
static int nfs4_validate_mount_data(struct nfs4_mount_data **options,
static int nfs4_validate_mount_data(void *options,
				    const char *dev_name,
				    struct nfs_parsed_mount_data *args,
				    struct sockaddr_in *addr,
				    const char *dev_name)
				    rpc_authflavor_t *authflavour,
				    char **hostname,
				    char **mntpath,
				    char **ip_addr)
{
{
	struct nfs4_mount_data *data = *options;
	struct nfs4_mount_data *data = (struct nfs4_mount_data *)options;
	char *c;
	char *c;


	if (data == NULL)
	if (data == NULL)
		goto out_no_data;
		goto out_no_data;


	memset(args, 0, sizeof(*args));
	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->nfs_server.protocol = IPPROTO_TCP;

	switch (data->version) {
	switch (data->version) {
	case 1:
	case 1:
		if (data->host_addrlen != sizeof(*addr))
		if (data->host_addrlen != sizeof(args->nfs_server.address))
			goto out_no_address;
			goto out_no_address;
		if (copy_from_user(addr, data->host_addr, sizeof(*addr)))
		if (copy_from_user(&args->nfs_server.address,
				   data->host_addr,
				   sizeof(&args->nfs_server.address)))
			return -EFAULT;
			return -EFAULT;
		if (addr->sin_port == 0)
		if (args->nfs_server.address.sin_port == 0)
			addr->sin_port = htons(NFS_PORT);
			args->nfs_server.address.sin_port = htons(NFS_PORT);
		if (!nfs_verify_server_address((struct sockaddr *) addr))
		if (!nfs_verify_server_address((struct sockaddr *)
						&args->nfs_server.address))
			goto out_no_address;
			goto out_no_address;


		switch (data->auth_flavourlen) {
		switch (data->auth_flavourlen) {
		case 0:
		case 0:
			*authflavour = RPC_AUTH_UNIX;
			args->auth_flavors[0] = RPC_AUTH_UNIX;
			break;
			break;
		case 1:
		case 1:
			if (copy_from_user(authflavour, data->auth_flavours,
			if (copy_from_user(args->auth_flavors,
					   sizeof(*authflavour)))
					   data->auth_flavours,
					   sizeof(args->auth_flavors)))
				return -EFAULT;
				return -EFAULT;
			break;
			break;
		default:
		default:
@@ -1555,74 +1566,56 @@ static int nfs4_validate_mount_data(struct nfs4_mount_data **options,
		c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN);
		c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN);
		if (IS_ERR(c))
		if (IS_ERR(c))
			return PTR_ERR(c);
			return PTR_ERR(c);
		*hostname = c;
		args->nfs_server.hostname = c;


		c = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN);
		c = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN);
		if (IS_ERR(c))
		if (IS_ERR(c))
			return PTR_ERR(c);
			return PTR_ERR(c);
		*mntpath = c;
		args->nfs_server.export_path = c;
		dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", *mntpath);
		dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", c);


		c = strndup_user(data->client_addr.data, 16);
		c = strndup_user(data->client_addr.data, 16);
		if (IS_ERR(c))
		if (IS_ERR(c))
			return PTR_ERR(c);
			return PTR_ERR(c);
		*ip_addr = c;
		args->client_address = c;

		/*
		 * Translate to nfs_parsed_mount_data, which nfs4_fill_super
		 * can deal with.
		 */

		args->flags	= data->flags & NFS4_MOUNT_FLAGMASK;
		args->rsize	= data->rsize;
		args->wsize	= data->wsize;
		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.protocol = data->proto;


		break;
		break;
	default: {
	default: {
		unsigned int len;
		unsigned int len;
		struct nfs_parsed_mount_data args = {
			.rsize		= NFS_MAX_FILE_IO_SIZE,
			.wsize		= NFS_MAX_FILE_IO_SIZE,
			.timeo		= 600,
			.retrans	= 2,
			.acregmin	= 3,
			.acregmax	= 60,
			.acdirmin	= 30,
			.acdirmax	= 60,
			.nfs_server.protocol = IPPROTO_TCP,
		};


		if (nfs_parse_mount_options((char *) *options, &args) == 0)
		if (nfs_parse_mount_options((char *)options, args) == 0)
			return -EINVAL;
			return -EINVAL;


		if (!nfs_verify_server_address((struct sockaddr *)
		if (!nfs_verify_server_address((struct sockaddr *)
						&args.nfs_server.address))
						&args->nfs_server.address))
			return -EINVAL;
			return -EINVAL;
		*addr = args.nfs_server.address;


		switch (args.auth_flavor_len) {
		switch (args->auth_flavor_len) {
		case 0:
		case 0:
			*authflavour = RPC_AUTH_UNIX;
			args->auth_flavors[0] = RPC_AUTH_UNIX;
			break;
			break;
		case 1:
		case 1:
			*authflavour = (rpc_authflavor_t) args.auth_flavors[0];
			break;
			break;
		default:
		default:
			goto out_inval_auth;
			goto out_inval_auth;
		}
		}


		/*
		 * Translate to nfs4_mount_data, which nfs4_fill_super
		 * can deal with.
		 */
		data = kzalloc(sizeof(*data), GFP_KERNEL);
		if (data == NULL)
			return -ENOMEM;
		*options = data;

		data->version	= 1;
		data->flags	= args.flags & NFS4_MOUNT_FLAGMASK;
		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->proto	= args.nfs_server.protocol;

		/*
		/*
		 * Split "dev_name" into "hostname:mntpath".
		 * Split "dev_name" into "hostname:mntpath".
		 */
		 */
@@ -1633,27 +1626,25 @@ static int nfs4_validate_mount_data(struct nfs4_mount_data **options,
		len = c - dev_name;
		len = c - dev_name;
		if (len > NFS4_MAXNAMLEN)
		if (len > NFS4_MAXNAMLEN)
			return -ENAMETOOLONG;
			return -ENAMETOOLONG;
		*hostname = kzalloc(len, GFP_KERNEL);
		args->nfs_server.hostname = kzalloc(len, GFP_KERNEL);
		if (*hostname == NULL)
		if (args->nfs_server.hostname == NULL)
			return -ENOMEM;
			return -ENOMEM;
		strncpy(*hostname, dev_name, len - 1);
		strncpy(args->nfs_server.hostname, dev_name, len - 1);


		c++;			/* step over the ':' */
		c++;			/* step over the ':' */
		len = strlen(c);
		len = strlen(c);
		if (len > NFS4_MAXPATHLEN)
		if (len > NFS4_MAXPATHLEN)
			return -ENAMETOOLONG;
			return -ENAMETOOLONG;
		*mntpath = kzalloc(len + 1, GFP_KERNEL);
		args->nfs_server.export_path = kzalloc(len + 1, GFP_KERNEL);
		if (*mntpath == NULL)
		if (args->nfs_server.export_path == NULL)
			return -ENOMEM;
			return -ENOMEM;
		strncpy(*mntpath, c, len);
		strncpy(args->nfs_server.export_path, c, len);


		dprintk("MNTPATH: %s\n", *mntpath);
		dprintk("MNTPATH: %s\n", args->nfs_server.export_path);


		if (args.client_address == NULL)
		if (args->client_address == NULL)
			goto out_no_client_address;
			goto out_no_client_address;


		*ip_addr = args.client_address;

		break;
		break;
		}
		}
	}
	}
@@ -1684,14 +1675,11 @@ static int nfs4_validate_mount_data(struct nfs4_mount_data **options,
static int nfs4_get_sb(struct file_system_type *fs_type,
static int nfs4_get_sb(struct file_system_type *fs_type,
	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
{
{
	struct nfs4_mount_data *data = raw_data;
	struct nfs_parsed_mount_data data;
	struct super_block *s;
	struct super_block *s;
	struct nfs_server *server;
	struct nfs_server *server;
	struct sockaddr_in addr;
	rpc_authflavor_t authflavour;
	struct nfs_fh mntfh;
	struct nfs_fh mntfh;
	struct dentry *mntroot;
	struct dentry *mntroot;
	char *mntpath = NULL, *hostname = NULL, *ip_addr = NULL;
	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 = {
		.mntflags = flags,
		.mntflags = flags,
@@ -1699,14 +1687,12 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
	int error;
	int error;


	/* Validate the mount data */
	/* Validate the mount data */
	error = nfs4_validate_mount_data(&data, dev_name, &addr, &authflavour,
	error = nfs4_validate_mount_data(raw_data, &data, dev_name);
					 &hostname, &mntpath, &ip_addr);
	if (error < 0)
	if (error < 0)
		goto out;
		goto out;


	/* Get a volume representation */
	/* Get a volume representation */
	server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr,
	server = nfs4_create_server(&data, &mntfh);
				    authflavour, &mntfh);
	if (IS_ERR(server)) {
	if (IS_ERR(server)) {
		error = PTR_ERR(server);
		error = PTR_ERR(server);
		goto out;
		goto out;
@@ -1745,9 +1731,9 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
	error = 0;
	error = 0;


out:
out:
	kfree(ip_addr);
	kfree(data.client_address);
	kfree(mntpath);
	kfree(data.nfs_server.export_path);
	kfree(hostname);
	kfree(data.nfs_server.hostname);
	return error;
	return error;


out_free:
out_free: