svn commit: r190315 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb nfsclient

Craig Rodrigues rodrigc at FreeBSD.org
Mon Mar 23 01:33:20 PDT 2009


Author: rodrigc
Date: Mon Mar 23 08:33:19 2009
New Revision: 190315
URL: http://svn.freebsd.org/changeset/base/190315

Log:
  MFC 183005, 187812:
  
  Add code to parse mount options passed as individual
  items of the nmount() iovec.

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/ath/ath_hal/   (props changed)
  stable/7/sys/dev/cxgb/   (props changed)
  stable/7/sys/nfsclient/nfs_vfsops.c

Modified: stable/7/sys/nfsclient/nfs_vfsops.c
==============================================================================
--- stable/7/sys/nfsclient/nfs_vfsops.c	Mon Mar 23 05:46:28 2009	(r190314)
+++ stable/7/sys/nfsclient/nfs_vfsops.c	Mon Mar 23 08:33:19 2009	(r190315)
@@ -717,7 +717,15 @@ nfs_decode_args(struct mount *mp, struct
 	}
 }
 
-static const char *nfs_opts[] = { "from", "nfs_args", NULL };
+static const char *nfs_opts[] = { "from", "nfs_args",
+    "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
+    "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
+    "async", "dumbtimer", "noconn", "nolockd", "intr", "rdirplus", "resvport",
+    "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
+    "retrans", "acregmin", "acregmax", "acdirmin", "acdirmax", 
+    "deadthresh", "hostname", "timeout", "addr", "fh", "nfsv3",
+    "maxgroups",
+    NULL };
 
 /*
  * VFS Operations.
@@ -732,13 +740,20 @@ static const char *nfs_opts[] = { "from"
 static int
 nfs_mount(struct mount *mp, struct thread *td)
 {
-	int error;
+	int error, ret, has_nfs_args_opt;
+	int has_addr_opt, has_fh_opt, has_hostname_opt;
 	struct nfs_args args;
 	struct sockaddr *nam;
 	struct vnode *vp;
 	char hst[MNAMELEN];
 	size_t len;
 	u_char nfh[NFSX_V3FHMAX];
+	char *opt;
+
+	has_nfs_args_opt = 0;
+	has_addr_opt = 0;
+	has_fh_opt = 0;
+	has_hostname_opt = 0;
 
 	if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
 		error = EINVAL;
@@ -750,12 +765,223 @@ nfs_mount(struct mount *mp, struct threa
 		goto out;
 	}
 
-	error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args, sizeof args);
-	if (error)
-		goto out;
+	/*
+	 * The old mount_nfs program passed the struct nfs_args
+	 * from userspace to kernel.  The new mount_nfs program
+	 * passes string options via nmount() from userspace to kernel
+	 * and we populate the struct nfs_args in the kernel.
+	 */
+	if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
+		error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
+		    sizeof args);
+		if (error)
+			goto out;
+
+		if (args.version != NFS_ARGSVERSION) {
+			error = EPROGMISMATCH;
+			goto out;
+		}
+		has_nfs_args_opt = 1;
+	}
 
-	if (args.version != NFS_ARGSVERSION) {
-		error = EPROGMISMATCH;
+	if (vfs_getopt(mp->mnt_optnew, "dumbtimer", NULL, NULL) == 0)
+		args.flags |= NFSMNT_DUMBTIMR;
+	if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
+		args.flags |= NFSMNT_NOCONN;
+	if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
+		args.flags |= NFSMNT_NOCONN;
+	if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
+		args.flags |= NFSMNT_NOLOCKD;
+	if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
+		args.flags &= ~NFSMNT_NOLOCKD;
+	if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
+		args.flags |= NFSMNT_INT;
+	if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
+		args.flags |= NFSMNT_RDIRPLUS;
+	if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
+		args.flags |= NFSMNT_RESVPORT;
+	if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
+		args.flags &= ~NFSMNT_RESVPORT;
+	if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
+		args.flags |= NFSMNT_SOFT;
+	if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
+		args.flags &= ~NFSMNT_SOFT;
+	if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
+		args.sotype = SOCK_DGRAM;
+	if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
+		args.sotype = SOCK_DGRAM;
+	if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
+		args.sotype = SOCK_STREAM;
+	if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
+		args.flags |= NFSMNT_NFSV3;
+	if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
+		if (opt == NULL) { 
+			vfs_mount_error(mp, "illegal readdirsize");
+			error = EINVAL;
+			goto out;
+		}
+		ret = sscanf(opt, "%d", &args.readdirsize);
+		if (ret != 1 || args.readdirsize <= 0) {
+			vfs_mount_error(mp, "illegal readdirsize: %s",
+			    opt);
+			error = EINVAL;
+			goto out;
+		}
+		args.flags |= NFSMNT_READDIRSIZE;
+	}
+	if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
+		if (opt == NULL) { 
+			vfs_mount_error(mp, "illegal readahead");
+			error = EINVAL;
+			goto out;
+		}
+		ret = sscanf(opt, "%d", &args.readahead);
+		if (ret != 1 || args.readahead <= 0) {
+			vfs_mount_error(mp, "illegal readahead: %s",
+			    opt);
+			error = EINVAL;
+			goto out;
+		}
+		args.flags |= NFSMNT_READAHEAD;
+	}
+	if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
+		if (opt == NULL) { 
+			vfs_mount_error(mp, "illegal wsize");
+			error = EINVAL;
+			goto out;
+		}
+		ret = sscanf(opt, "%d", &args.wsize);
+		if (ret != 1 || args.wsize <= 0) {
+			vfs_mount_error(mp, "illegal wsize: %s",
+			    opt);
+			error = EINVAL;
+			goto out;
+		}
+		args.flags |= NFSMNT_WSIZE;
+	}
+	if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
+		if (opt == NULL) { 
+			vfs_mount_error(mp, "illegal rsize");
+			error = EINVAL;
+			goto out;
+		}
+		ret = sscanf(opt, "%d", &args.rsize);
+		if (ret != 1 || args.rsize <= 0) {
+			vfs_mount_error(mp, "illegal wsize: %s",
+			    opt);
+			error = EINVAL;
+			goto out;
+		}
+		args.flags |= NFSMNT_RSIZE;
+	}
+	if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
+		if (opt == NULL) { 
+			vfs_mount_error(mp, "illegal retrans");
+			error = EINVAL;
+			goto out;
+		}
+		ret = sscanf(opt, "%d", &args.retrans);
+		if (ret != 1 || args.retrans <= 0) {
+			vfs_mount_error(mp, "illegal retrans: %s",
+			    opt);
+			error = EINVAL;
+			goto out;
+		}
+		args.flags |= NFSMNT_RETRANS;
+	}
+	if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
+		ret = sscanf(opt, "%d", &args.acregmin);
+		if (ret != 1 || args.acregmin < 0) {
+			vfs_mount_error(mp, "illegal acregmin: %s",
+			    opt);
+			error = EINVAL;
+			goto out;
+		}
+		args.flags |= NFSMNT_ACREGMIN;
+	}
+	if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
+		ret = sscanf(opt, "%d", &args.acregmax);
+		if (ret != 1 || args.acregmax < 0) {
+			vfs_mount_error(mp, "illegal acregmax: %s",
+			    opt);
+			error = EINVAL;
+			goto out;
+		}
+		args.flags |= NFSMNT_ACREGMAX;
+	}
+	if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
+		ret = sscanf(opt, "%d", &args.acdirmin);
+		if (ret != 1 || args.acdirmin < 0) {
+			vfs_mount_error(mp, "illegal acdirmin: %s",
+			    opt);
+			error = EINVAL;
+			goto out;
+		}
+		args.flags |= NFSMNT_ACDIRMIN;
+	}
+	if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
+		ret = sscanf(opt, "%d", &args.acdirmax);
+		if (ret != 1 || args.acdirmax < 0) {
+			vfs_mount_error(mp, "illegal acdirmax: %s",
+			    opt);
+			error = EINVAL;
+			goto out;
+		}
+		args.flags |= NFSMNT_ACDIRMAX;
+	}
+	if (vfs_getopt(mp->mnt_optnew, "deadthresh", (void **)&opt, NULL) == 0) {
+		ret = sscanf(opt, "%d", &args.deadthresh);
+		if (ret != 1 || args.deadthresh <= 0) {
+			vfs_mount_error(mp, "illegal deadthresh: %s",
+			    opt);
+			error = EINVAL;
+			goto out;
+		}
+		args.flags |= NFSMNT_DEADTHRESH;
+	}
+	if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
+		ret = sscanf(opt, "%d", &args.timeo);
+		if (ret != 1 || args.timeo <= 0) {
+			vfs_mount_error(mp, "illegal timeout: %s",
+			    opt);
+			error = EINVAL;
+			goto out;
+		}
+		args.flags |= NFSMNT_TIMEO;
+	}
+	if (vfs_getopt(mp->mnt_optnew, "maxgroups", (void **)&opt, NULL) == 0) {
+		ret = sscanf(opt, "%d", &args.maxgrouplist);
+		if (ret != 1 || args.timeo <= 0) {
+			vfs_mount_error(mp, "illegal maxgroups: %s",
+			    opt);
+			error = EINVAL;
+			goto out;
+		}
+		args.flags |= NFSMNT_MAXGRPS;
+	}
+	if (vfs_getopt(mp->mnt_optnew, "addr", (void **)&args.addr,
+		&args.addrlen) == 0) {
+		has_addr_opt = 1;
+		if (args.addrlen > SOCK_MAXADDRLEN) {
+			error = ENAMETOOLONG;
+			goto out;
+		}
+		MALLOC(nam, struct sockaddr *, args.addrlen, M_SONAME,
+		    M_WAITOK);
+		bcopy(args.addr, nam, args.addrlen);
+		nam->sa_len = args.addrlen;
+	}
+	if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
+		&args.fhsize) == 0) {
+		has_fh_opt = 1;
+	}
+	if (vfs_getopt(mp->mnt_optnew, "hostname", (void **)&args.hostname,
+		NULL) == 0) {
+		has_hostname_opt = 1;
+	}
+	if (args.hostname == NULL) {
+		vfs_mount_error(mp, "Invalid hostname");
+		error = EINVAL;
 		goto out;
 	}
 	if (mp->mnt_flag & MNT_UPDATE) {
@@ -788,23 +1014,38 @@ nfs_mount(struct mount *mp, struct threa
 	 */
 	if (nfs_ip_paranoia == 0)
 		args.flags |= NFSMNT_NOCONN;
-	if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
-		error = EINVAL;
-		goto out;
+
+	if (has_nfs_args_opt) {
+		/*
+		 * In the 'nfs_args' case, the pointers in the args
+		 * structure are in userland - we copy them in here.
+		 */
+		if (!has_fh_opt) {
+			error = copyin((caddr_t)args.fh, (caddr_t)nfh,
+			    args.fhsize);
+			if (error) {
+				goto out;
+			}
+			args.fh = nfh;
+		}
+		if (!has_hostname_opt) {
+			error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
+			if (error) {
+				goto out;
+			}
+			bzero(&hst[len], MNAMELEN - len);
+			args.hostname = hst;
+		}
+		if (!has_addr_opt) {
+			/* sockargs() call must be after above copyin() calls */
+			error = getsockaddr(&nam, (caddr_t)args.addr,
+			    args.addrlen);
+			if (error) {
+				goto out;
+			}
+		}
 	}
-	error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
-	if (error)
-		goto out;
-	error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
-	if (error)
-		goto out;
-	bzero(&hst[len], MNAMELEN - len);
-	/* sockargs() call must be after above copyin() calls */
-	error = getsockaddr(&nam, (caddr_t)args.addr, args.addrlen);
-	if (error)
-		goto out;
-	args.fh = nfh;
-	error = mountnfs(&args, mp, nam, hst, &vp, td->td_ucred);
+	error = mountnfs(&args, mp, nam, args.hostname, &vp, td->td_ucred);
 out:
 	if (!error) {
 		MNT_ILOCK(mp);


More information about the svn-src-all mailing list