[PATCH 10/13] NFS: Add functions to parse nfs4 mount options to fs/nfs/super.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add helpers required for parsing nfs4 mount options in the NFS
client.

Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx>
---

 fs/nfs/super.c |  290 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 290 insertions(+), 0 deletions(-)

diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 7b7cacb..927c1c2 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1332,6 +1332,296 @@ error_splat_super:
 
 #ifdef CONFIG_NFS_V4
 
+static match_table_t nfs4_tokens = {
+	{Opt_userspace, "bg"},
+	{Opt_userspace, "fg"},
+	{Opt_soft, "soft"},
+	{Opt_hard, "hard"},
+	{Opt_intr, "intr"},
+	{Opt_nointr, "nointr"},
+	{Opt_cto, "cto"},
+	{Opt_nocto, "nocto"},
+	{Opt_ac, "ac"},
+	{Opt_noac, "noac"},
+
+	{Opt_port, "port=%u"},
+	{Opt_rsize, "rsize=%u"},
+	{Opt_wsize, "wsize=%u"},
+	{Opt_timeo, "timeo=%u"},
+	{Opt_retrans, "retrans=%u"},
+	{Opt_acregmin, "acregmin=%u"},
+	{Opt_acregmax, "acregmax=%u"},
+	{Opt_acdirmin, "acdirmin=%u"},
+	{Opt_acdirmax, "acdirmax=%u"},
+	{Opt_actimeo, "actimeo=%u"},
+	{Opt_userspace, "retry=%u"},
+
+	{Opt_sec, "sec=%s"},
+	{Opt_proto, "proto=%s"},
+	{Opt_addr, "addr=%s"},
+	{Opt_clientaddr, "clientaddr=%s"},
+
+	{Opt_err, NULL},
+};
+
+static int nfs4_parse_options(char *raw, struct nfs4_mount_args *mnt)
+{
+	char *p, *string;
+
+	if (!raw)
+		return 1;
+
+	while ((p = strsep (&raw, ",")) != NULL) {
+		substring_t args[MAX_OPT_ARGS];
+		int option, token;
+
+		if (!*p)
+			continue;
+		token = match_token(p, nfs4_tokens, args);
+
+		dprintk("NFS:   nfs4 mount option '%s': parsing token %d\n",
+			p, token);
+
+		switch (token) {
+		case Opt_soft:
+			mnt->nmd.flags |= NFS4_MOUNT_SOFT;
+			break;
+		case Opt_hard:
+			mnt->nmd.flags &= ~NFS4_MOUNT_SOFT;
+			break;
+		case Opt_intr:
+			mnt->nmd.flags |= NFS4_MOUNT_INTR;
+			break;
+		case Opt_nointr:
+			mnt->nmd.flags &= ~NFS4_MOUNT_INTR;
+			break;
+		case Opt_cto:
+			mnt->nmd.flags &= ~NFS4_MOUNT_NOCTO;
+			break;
+		case Opt_nocto:
+			mnt->nmd.flags |= NFS4_MOUNT_NOCTO;
+			break;
+		case Opt_ac:
+			mnt->nmd.flags &= ~NFS4_MOUNT_NOAC;
+			break;
+		case Opt_noac:
+			mnt->nmd.flags |= NFS4_MOUNT_NOAC;
+			break;
+
+		case Opt_port:
+			if (match_int(args, &option))
+				return 0;
+			if (option < 0 || option > 65535)
+				return 0;
+			mnt->addr.sin_port = htonl(option);
+			break;
+		case Opt_rsize:
+			if (match_int(args, &mnt->nmd.rsize))
+				return 0;
+			break;
+		case Opt_wsize:
+			if (match_int(args, &mnt->nmd.wsize))
+				return 0;
+			break;
+		case Opt_timeo:
+			if (match_int(args, &mnt->nmd.timeo))
+				return 0;
+			break;
+		case Opt_retrans:
+			if (match_int(args, &mnt->nmd.retrans))
+				return 0;
+			break;
+		case Opt_acregmin:
+			if (match_int(args, &mnt->nmd.acregmin))
+				return 0;
+			break;
+		case Opt_acregmax:
+			if (match_int(args, &mnt->nmd.acregmax))
+				return 0;
+			break;
+		case Opt_acdirmin:
+			if (match_int(args, &mnt->nmd.acdirmin))
+				return 0;
+			break;
+		case Opt_acdirmax:
+			if (match_int(args, &mnt->nmd.acdirmax))
+				return 0;
+			break;
+		case Opt_actimeo:
+			if (match_int(args, &option))
+				return 0;
+			if (option < 0)
+				return 0;
+			mnt->nmd.acregmin =
+			mnt->nmd.acregmax =
+			mnt->nmd.acdirmin =
+			mnt->nmd.acdirmax = option;
+			break;
+
+		case Opt_proto: {
+			string = match_strdup(args);
+			if (string == NULL)
+				goto out_nomem;
+			if (strcmp(string, "udp") == 0) {
+				mnt->nmd.proto = IPPROTO_UDP;
+				kfree(string);
+				break;
+			}
+			if (strcmp(string, "tcp") == 0) {
+				mnt->nmd.proto = IPPROTO_TCP;
+				kfree(string);
+				break;
+			}
+			goto out_unrec_xprt;
+		}
+		case Opt_sec: {
+			string = match_strdup(args);
+			if (string == NULL)
+				goto out_nomem;
+			token = match_token(string, nfs_sec_tokens, args);
+			kfree(string);
+
+			mnt->nmd.auth_flavourlen = 1;
+
+			switch (token) {
+			case Opt_sec_sys:
+				mnt->nmd.auth_flavourlen = 0;
+				break;
+			case Opt_sec_krb5:
+				mnt->authflavor = RPC_AUTH_GSS_KRB5;
+				break;
+			case Opt_sec_krb5i:
+				mnt->authflavor = RPC_AUTH_GSS_KRB5I;
+				break;
+			case Opt_sec_krb5p:
+				mnt->authflavor = RPC_AUTH_GSS_KRB5P;
+				break;
+			case Opt_sec_lkey:
+				mnt->authflavor = RPC_AUTH_GSS_LKEY;
+				break;
+			case Opt_sec_lkeyi:
+				mnt->authflavor = RPC_AUTH_GSS_LKEYI;
+				break;
+			case Opt_sec_lkeyp:
+				mnt->authflavor = RPC_AUTH_GSS_LKEYP;
+				break;
+			case Opt_sec_spkm:
+				mnt->authflavor = RPC_AUTH_GSS_SPKM;
+				break;
+			case Opt_sec_spkmi:
+				mnt->authflavor = RPC_AUTH_GSS_SPKMI;
+				break;
+			case Opt_sec_spkmp:
+				mnt->authflavor = RPC_AUTH_GSS_SPKMP;
+				break;
+			default:
+				goto out_unrec_sec;
+			}
+			break;
+		}
+		case Opt_addr:
+			string = match_strdup(args);
+			if (string == NULL)
+				goto out_nomem;
+			mnt->addr.sin_family = AF_INET;
+			mnt->addr.sin_addr.s_addr = in_aton(string);
+			kfree(string);
+			break;
+		case Opt_clientaddr: {
+			unsigned int len = args[0].to - args[0].from;
+			if (len > 80)
+				goto out_clntaddr_long;
+			match_strcpy(mnt->clientaddr, args);
+			mnt->nmd.client_addr.data = mnt->clientaddr;
+			mnt->nmd.client_addr.len = len;
+			break;
+		}
+
+		case Opt_userspace:
+		case Opt_deprecated:
+			break;
+
+		default:
+			goto out_unknown;
+		}
+	}
+
+	return 1;
+
+out_unrec_xprt:
+	printk(KERN_INFO "NFS4: unrecognized transport protocol\n");
+	return 0;
+
+out_unrec_sec:
+	printk(KERN_INFO "NFS4: unrecognized security flavor\n");
+	return 0;
+
+out_nomem:
+	printk(KERN_INFO "NFS4: not enough memory to parse option\n");
+	return 0;
+
+out_clntaddr_long:
+	printk(KERN_INFO "NFS4: clientaddr too long\n");
+	return 0;
+
+out_unknown:
+	printk(KERN_INFO "NFS4: unrecognized mount option: %s\n", p);
+	return 0;
+}
+
+/*
+ * Convert a string of nfs4 mount options into an nfs4_mount_data struct.
+ *
+ * User space handles the following behaviors:
+ *
+ * + DNS: mapping server host name to IP address ("addr=" option)
+ *
+ * + DNS: providing IP address of callback interface ("clientaddr=" option)
+ *
+ * + failure mode: how to behave if a mount request can't be handled
+ *   immediately ("fg/bg" option)
+ *
+ * + retry: how often to retry a mount request ("retry=" option)
+ *
+ */
+static struct nfs4_mount_data *nfs4_convert_mount_opts(const char *options)
+{
+	struct nfs4_mount_args *args;
+
+	dprintk("NFS: nfs4 mount opts='%s'\n", options);
+
+	args = kzalloc(sizeof(*args), GFP_KERNEL);
+	if (args == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	args->nmd.rsize = NFS_MAX_FILE_IO_SIZE;
+	args->nmd.wsize = NFS_MAX_FILE_IO_SIZE;
+	args->nmd.proto = IPPROTO_TCP;
+	args->nmd.timeo = 600;		/* in tenths of a second */
+	args->nmd.retrans = 2;
+	args->nmd.acregmin = 3;
+	args->nmd.acregmax = 60;
+	args->nmd.acdirmin = 30;
+	args->nmd.acdirmax = 60;
+
+	args->nmd.auth_flavourlen = 0;
+	args->nmd.auth_flavours = &args->authflavor;
+
+	args->nmd.host_addrlen = sizeof(args->addr);
+	args->nmd.host_addr = (struct sockaddr *) &args->addr;
+
+	args->addr.sin_port = htons(NFS_PORT);
+
+	if (nfs4_parse_options((char *) options, args) == 0)
+		goto out_err;
+
+	return &args->nmd;
+
+out_err:
+	kfree(args);
+	return ERR_PTR(-EINVAL);
+}
+
 /*
  * Finish setting up a cloned NFS4 superblock
  */

-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux