Index: kern/vfs_subr.c
===================================================================
RCS file: /space2/ncvs/src/sys/kern/vfs_subr.c,v
retrieving revision 1.360
diff -u -p -r1.360 vfs_subr.c
--- kern/vfs_subr.c	6 Jun 2002 15:50:22 -0000	1.360
+++ kern/vfs_subr.c	19 Jun 2002 15:38:30 -0000
@@ -489,6 +489,49 @@ vfs_timestamp(tsp)
 }
 
 /*
+ * Build a linked list of mount options from a struct uio.
+ */
+int
+vfs_buildopts(struct uio *auio, struct vfsoptlist **options)
+{
+	struct vfsoptlist *opts;
+	struct vfsopt *opt;
+	unsigned int i, iovcnt;
+	int error, namelen, optlen;
+
+	iovcnt = auio->uio_iovcnt;
+	opts = malloc(sizeof(struct vfsoptlist), M_MOUNT, M_WAITOK);
+	TAILQ_INIT(opts);
+	for (i = 0; i < iovcnt; i += 2) {
+		opt = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK);
+		namelen = auio->uio_iov[i].iov_len;
+		optlen = auio->uio_iov[i + 1].iov_len;
+		opt->name = malloc(namelen, M_MOUNT, M_WAITOK);
+		opt->value = malloc(optlen, M_MOUNT, M_WAITOK);
+		opt->len = optlen;
+		if (auio->uio_segflg == UIO_SYSSPACE) {
+			bcopy(auio->uio_iov[i].iov_base, opt->name, namelen);
+			bcopy(auio->uio_iov[i + 1].iov_base, opt->value,
+			    optlen);
+		} else {
+			error = copyin(auio->uio_iov[i].iov_base, opt->name,
+			    namelen);
+			if (!error)
+				error = copyin(auio->uio_iov[i + 1].iov_base,
+				    opt->value, optlen);
+			if (error)
+				goto bad;
+		}
+		TAILQ_INSERT_TAIL(opts, opt, link);
+	}
+	*options = opts;
+	return (0);
+bad:
+	vfs_freeopts(opts);
+	return (error);
+}
+
+/*
  * Get a mount option by its name.
  *
  * Return 0 if the option was found, ENOENT otherwise.
@@ -504,11 +547,8 @@ vfs_getopt(opts, name, buf, len)
 	int *len;
 {
 	struct vfsopt *opt;
-	int i;
 
-	i = 0;
-	opt = opts->opt;
-	while (i++ < opts->optcnt) {
+	TAILQ_FOREACH(opt, opts, link) {
 		if (strcmp(name, opt->name) == 0) {
 			if (len != NULL)
 				*len = opt->len;
@@ -516,7 +556,6 @@ vfs_getopt(opts, name, buf, len)
 				*buf = opt->value;
 			return (0);
 		}
-		opt++;
 	}
 	return (ENOENT);
 }
@@ -538,11 +577,8 @@ vfs_copyopt(opts, name, dest, len, done)
 	int len, *done;
 {
 	struct vfsopt *opt;
-	int i;
 
-	i = 0;
-	opt = opts->opt;
-	while (i++ < opts->optcnt) {
+	TAILQ_FOREACH(opt, opts, link) {
 		if (strcmp(name, opt->name) == 0) {
 			if (len < opt->len)
 				return (EINVAL);
@@ -551,7 +587,6 @@ vfs_copyopt(opts, name, dest, len, done)
 				*done = opt->len;
 			return (0);
 		}
-		opt++;
 	}
 	return (ENOENT);
 }
Index: kern/vfs_syscalls.c
===================================================================
RCS file: /space2/ncvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.258
diff -u -p -r1.258 vfs_syscalls.c
--- kern/vfs_syscalls.c	28 May 2002 13:27:55 -0000	1.258
+++ kern/vfs_syscalls.c	19 Jun 2002 16:06:41 -0000
@@ -87,7 +87,6 @@ static int setutimes(struct thread *td, 
     const struct timespec *, int);
 static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred,
     struct thread *td);
-static void vfs_freeopts(struct vfsoptlist *opt);
 static int vfs_nmount(struct thread *td, int, struct uio *);
 
 static int	usermount = 0;	/* if 1, non-root can mount fs. */
@@ -167,13 +166,19 @@ finish:
  * Release all resources related to the
  * mount options.
  */
-static void
-vfs_freeopts(struct vfsoptlist *opt)
+void
+vfs_freeopts(struct vfsoptlist *opts)
 {
+	struct vfsopt *opt;
 
-	free(opt->opt, M_MOUNT);
-	free(opt->optbuf, M_MOUNT);
-	free(opt, M_MOUNT);
+	while (!TAILQ_EMPTY(opts)) {
+		opt = TAILQ_FIRST(opts);
+		TAILQ_REMOVE(opts, opt, link);
+		free(opt->name, M_MOUNT);
+		free(opt->value, M_MOUNT);
+		free(opt, M_MOUNT);
+	}
+	free(opts, M_MOUNT);
 }
 
 int
@@ -275,63 +280,16 @@ vfs_nmount(td, fsflags, fsoptions)
 	struct vnode *vp;
 	struct mount *mp;
 	struct vfsconf *vfsp;
-	struct iovec *cur;
 	struct vfsoptlist *optlist;
-	struct vfsopt *opt;
-	char *buf, *fstype, *fspath;
-	int error, flag = 0, kern_flag = 0, i, len, optcnt;
-	int offset, iovcnt, fstypelen, fspathlen;
+	char *fstype, *fspath;
+	int error, flag = 0, kern_flag = 0;
+	int fstypelen, fspathlen;
 	struct vattr va;
 	struct nameidata nd;
 
-	/*
-	 * Allocate memory to hold the vfsopt structures.
-	 */
-	iovcnt = fsoptions->uio_iovcnt;
-	optcnt = iovcnt >> 1;
-	opt = malloc(sizeof (struct vfsopt) * optcnt,
-	    M_MOUNT, M_WAITOK | M_ZERO);
-
-	/*
-	 * Count the size of the buffer for options,
-	 * allocate it, and fill in the vfsopt structures.
-	 */
-	cur = fsoptions->uio_iov;
-	len = fsoptions->uio_resid;
-	buf = malloc(len, M_TEMP, M_WAITOK | M_ZERO);
-
-	optlist = malloc(sizeof (struct vfsoptlist), M_MOUNT, M_WAITOK);
-	optlist->opt = opt;
-	optlist->optbuf = buf;
-	optlist->optcnt = optcnt;
-
-	offset = i = 0;
-	cur = fsoptions->uio_iov;
-	while (i < optcnt) {
-		opt[i].name = buf + offset;
-		/* Ensure the name of an option is a string. */
-		if (opt[i].name[cur->iov_len - 1] != '\0') {
-			error = EINVAL;
-			goto bad;
-		}
-		offset += cur->iov_len;
-		cur++;
-		opt[i].len = cur->iov_len;
-		/*
-		 * Prevent consumers from trying to
-		 * read the value of a 0 length option
-		 * by setting it to NULL.
-		 */
-		if (opt[i].len == 0)
-			opt[i].value = NULL;
-		else
-			opt[i].value = buf + offset;
-		offset += cur->iov_len;
-		cur++; i++;
-	}
-
-	if ((error = uiomove(buf, len, fsoptions)) != 0)
-		goto bad;
+	error = vfs_buildopts(fsoptions, &optlist);
+	if (error)
+		return (error);
 
 	/*
 	 * We need these two options before the others,
Index: sys/mount.h
===================================================================
RCS file: /space2/ncvs/src/sys/sys/mount.h,v
retrieving revision 1.126
diff -u -p -r1.126 mount.h
--- sys/mount.h	23 May 2002 23:18:25 -0000	1.126
+++ sys/mount.h	19 Jun 2002 15:37:53 -0000
@@ -120,13 +120,9 @@ struct statfs {
  */
 TAILQ_HEAD(vnodelst, vnode);
 
-struct vfsoptlist {
-	struct vfsopt	*opt;
-	unsigned int	optcnt;
-	char		*optbuf;
-};
-
+TAILQ_HEAD(vfsoptlist, vfsopt);
 struct vfsopt {
+	TAILQ_ENTRY(vfsopt) link;
 	char	*name;
 	void	*value;
 	int	len;
@@ -439,6 +435,8 @@ extern	char *mountrootfsname;
 int	dounmount(struct mount *, int, struct thread *td);
 int	kernel_mount(struct iovec *iovp, unsigned int iovcnt, int flags);
 int	kernel_vmount(int flags, ...);
+int	vfs_buildopts(struct uio *, struct vfsoptlist **);
+void	vfs_freeopts(struct vfsoptlist *);
 int	vfs_getopt(struct vfsoptlist *, const char *, void **, int *);
 int	vfs_copyopt(struct vfsoptlist *, const char *, void *, int, int *);
 int	vfs_mount(struct thread *td, const char *type, char *path,
