svn commit: r220937 - head/sys/kern

Jaakko Heinonen jh at FreeBSD.org
Fri Apr 22 07:26:10 UTC 2011


Author: jh
Date: Fri Apr 22 07:26:09 2011
New Revision: 220937
URL: http://svn.freebsd.org/changeset/base/220937

Log:
  Utilize vfs_sanitizeopts() in vfs_mergeopts() to merge options. Because
  vfs_sanitizeopts() can handle "ro" and "rw" options properly, there is
  no more need to add "noro" in vfs_donmount() to cancel "ro".
  
  This also fixes a problem of canceling options beginning with "no".
  For example, "noatime" didn't cancel "nonoatime". Thus it was possible
  that both "noatime" and "nonoatime" were active at the same time.
  
  Reviewed by:	bde

Modified:
  head/sys/kern/vfs_mount.c

Modified: head/sys/kern/vfs_mount.c
==============================================================================
--- head/sys/kern/vfs_mount.c	Fri Apr 22 02:22:36 2011	(r220936)
+++ head/sys/kern/vfs_mount.c	Fri Apr 22 07:26:09 2011	(r220937)
@@ -336,50 +336,28 @@ bad:
  * Merge the old mount options with the new ones passed
  * in the MNT_UPDATE case.
  *
- * XXX This function will keep a "nofoo" option in the
- *     new options if there is no matching "foo" option
- *     to be cancelled in the old options.  This is a bug
- *     if the option's canonical name is "foo".  E.g., "noro"
- *     shouldn't end up in the mount point's active options,
- *     but it can.
+ * XXX: This function will keep a "nofoo" option in the new
+ * options.  E.g, if the option's canonical name is "foo",
+ * "nofoo" ends up in the mount point's active options.
  */
 static void
-vfs_mergeopts(struct vfsoptlist *toopts, struct vfsoptlist *opts)
+vfs_mergeopts(struct vfsoptlist *toopts, struct vfsoptlist *oldopts)
 {
-	struct vfsopt *opt, *opt2, *new;
+	struct vfsopt *opt, *new;
 
-	TAILQ_FOREACH(opt, opts, link) {
-		/*
-		 * Check that this option hasn't been redefined
-		 * nor cancelled with a "no" mount option.
-		 */
-		opt2 = TAILQ_FIRST(toopts);
-		while (opt2 != NULL) {
-			if (strcmp(opt2->name, opt->name) == 0)
-				goto next;
-			if (strncmp(opt2->name, "no", 2) == 0 &&
-			    strcmp(opt2->name + 2, opt->name) == 0) {
-				vfs_freeopt(toopts, opt2);
-				goto next;
-			}
-			opt2 = TAILQ_NEXT(opt2, link);
-		}
-		/* We want this option, duplicate it. */
+	TAILQ_FOREACH(opt, oldopts, link) {
 		new = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK);
-		new->name = malloc(strlen(opt->name) + 1, M_MOUNT, M_WAITOK);
-		strcpy(new->name, opt->name);
+		new->name = strdup(opt->name, M_MOUNT);
 		if (opt->len != 0) {
 			new->value = malloc(opt->len, M_MOUNT, M_WAITOK);
 			bcopy(opt->value, new->value, opt->len);
-		} else {
+		} else
 			new->value = NULL;
-		}
 		new->len = opt->len;
 		new->seen = opt->seen;
-		TAILQ_INSERT_TAIL(toopts, new, link);
-next:
-		continue;
+		TAILQ_INSERT_HEAD(toopts, new, link);
 	}
+	vfs_sanitizeopts(toopts);
 }
 
 /*
@@ -542,13 +520,12 @@ int
 vfs_donmount(struct thread *td, int fsflags, struct uio *fsoptions)
 {
 	struct vfsoptlist *optlist;
-	struct vfsopt *opt, *noro_opt, *tmp_opt;
+	struct vfsopt *opt, *tmp_opt;
 	char *fstype, *fspath, *errmsg;
 	int error, fstypelen, fspathlen, errmsg_len, errmsg_pos;
-	int has_rw, has_noro;
 
 	errmsg = fspath = NULL;
-	errmsg_len = has_noro = has_rw = fspathlen = 0;
+	errmsg_len = fspathlen = 0;
 	errmsg_pos = -1;
 
 	error = vfs_buildopts(fsoptions, &optlist);
@@ -641,14 +618,10 @@ vfs_donmount(struct thread *td, int fsfl
 			free(opt->name, M_MOUNT);
 			opt->name = strdup("nonosymfollow", M_MOUNT);
 		}
-		else if (strcmp(opt->name, "noro") == 0) {
+		else if (strcmp(opt->name, "noro") == 0)
 			fsflags &= ~MNT_RDONLY;
-			has_noro = 1;
-		}
-		else if (strcmp(opt->name, "rw") == 0) {
+		else if (strcmp(opt->name, "rw") == 0)
 			fsflags &= ~MNT_RDONLY;
-			has_rw = 1;
-		}
 		else if (strcmp(opt->name, "ro") == 0)
 			fsflags |= MNT_RDONLY;
 		else if (strcmp(opt->name, "rdonly") == 0) {
@@ -665,22 +638,6 @@ vfs_donmount(struct thread *td, int fsfl
 	}
 
 	/*
-	 * If "rw" was specified as a mount option, and we
-	 * are trying to update a mount-point from "ro" to "rw",
-	 * we need a mount option "noro", since in vfs_mergeopts(),
-	 * "noro" will cancel "ro", but "rw" will not do anything.
-	 */
-	if (has_rw && !has_noro) {
-		noro_opt = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK);
-		noro_opt->name = strdup("noro", M_MOUNT);
-		noro_opt->value = NULL;
-		noro_opt->len = 0;
-		noro_opt->pos = -1;
-		noro_opt->seen = 1;
-		TAILQ_INSERT_TAIL(optlist, noro_opt, link);
-	}
-
-	/*
 	 * Be ultra-paranoid about making sure the type and fspath
 	 * variables will fit in our mp buffers, including the
 	 * terminating NUL.


More information about the svn-src-head mailing list