1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-15 10:17:20 +00:00

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
This commit is contained in:
Jaakko Heinonen 2011-04-22 07:26:09 +00:00
parent 88e428c6bc
commit 1b0fe69dc9
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=220937

View File

@ -336,50 +336,28 @@ vfs_buildopts(struct uio *auio, struct vfsoptlist **options)
* 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 fsflags, struct uio *fsoptions)
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) {
@ -664,22 +637,6 @@ vfs_donmount(struct thread *td, int fsflags, struct uio *fsoptions)
fsflags |= MNT_UNION;
}
/*
* 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