Index: sys/sys/mount.h =================================================================== --- sys/sys/mount.h (revision 220936) +++ sys/sys/mount.h (working copy) @@ -138,8 +138,12 @@ struct vfsopt { int len; int pos; int seen; + int flags; }; +/* vfsopt flags */ +#define VFSOPT_CANCELONLY 0x01 + /* * Structure per mounted filesystem. Each mounted filesystem has an * array of operations and an instance record. The filesystems are Index: sys/kern/vfs_mount.c =================================================================== --- sys/kern/vfs_mount.c (revision 220937) +++ sys/kern/vfs_mount.c (working copy) @@ -284,12 +284,9 @@ vfs_buildopts(struct uio *auio, struct v goto bad; } - opt = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK); + opt = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK | M_ZERO); opt->name = malloc(namelen, M_MOUNT, M_WAITOK); - opt->value = NULL; - opt->len = 0; opt->pos = i / 2; - opt->seen = 0; /* * Do this early, so jumps to "bad" will free the current @@ -335,15 +332,11 @@ 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. 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 *oldopts) { - struct vfsopt *opt, *new; + struct vfsopt *new, *opt, *opt_tmp; TAILQ_FOREACH(opt, oldopts, link) { new = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK); @@ -355,9 +348,18 @@ vfs_mergeopts(struct vfsoptlist *toopts, new->value = NULL; new->len = opt->len; new->seen = opt->seen; + new->flags = opt->flags; TAILQ_INSERT_HEAD(toopts, new, link); } vfs_sanitizeopts(toopts); + /* + * Remove options which shouldn't end up in the mount point's + * active options. + */ + TAILQ_FOREACH_SAFE(opt, toopts, link, opt_tmp) { + if ((opt->flags & VFSOPT_CANCELONLY) != 0) + vfs_freeopt(toopts, opt); + } } /* @@ -584,40 +586,16 @@ vfs_donmount(struct thread *td, int fsfl fsflags &= ~MNT_ASYNC; else if (strcmp(opt->name, "noatime") == 0) fsflags |= MNT_NOATIME; - else if (strcmp(opt->name, "atime") == 0) { - free(opt->name, M_MOUNT); - opt->name = strdup("nonoatime", M_MOUNT); - } else if (strcmp(opt->name, "noclusterr") == 0) fsflags |= MNT_NOCLUSTERR; - else if (strcmp(opt->name, "clusterr") == 0) { - free(opt->name, M_MOUNT); - opt->name = strdup("nonoclusterr", M_MOUNT); - } else if (strcmp(opt->name, "noclusterw") == 0) fsflags |= MNT_NOCLUSTERW; - else if (strcmp(opt->name, "clusterw") == 0) { - free(opt->name, M_MOUNT); - opt->name = strdup("nonoclusterw", M_MOUNT); - } else if (strcmp(opt->name, "noexec") == 0) fsflags |= MNT_NOEXEC; - else if (strcmp(opt->name, "exec") == 0) { - free(opt->name, M_MOUNT); - opt->name = strdup("nonoexec", M_MOUNT); - } else if (strcmp(opt->name, "nosuid") == 0) fsflags |= MNT_NOSUID; - else if (strcmp(opt->name, "suid") == 0) { - free(opt->name, M_MOUNT); - opt->name = strdup("nonosuid", M_MOUNT); - } else if (strcmp(opt->name, "nosymfollow") == 0) fsflags |= MNT_NOSYMFOLLOW; - else if (strcmp(opt->name, "symfollow") == 0) { - free(opt->name, M_MOUNT); - opt->name = strdup("nonosymfollow", M_MOUNT); - } else if (strcmp(opt->name, "noro") == 0) fsflags &= ~MNT_RDONLY; else if (strcmp(opt->name, "rw") == 0) @@ -1372,27 +1350,27 @@ vfs_opterror(struct vfsoptlist *opts, co */ /* - * Check that no unknown options are given + * Check that no unknown options are given and mark options which + * should not become active with the VFSOPT_CANCELONLY flag. */ int vfs_filteropt(struct vfsoptlist *opts, const char **legal) { struct vfsopt *opt; char errmsg[255]; - const char **t, *p, *q; - int ret = 0; + const char **t, *p; + int ret; + + ret = 0; TAILQ_FOREACH(opt, opts, link) { p = opt->name; - q = NULL; - if (p[0] == 'n' && p[1] == 'o') - q = p + 2; for(t = global_opts; *t != NULL; t++) { if (strcmp(*t, p) == 0) break; - if (q != NULL) { - if (strcmp(*t, q) == 0) - break; + if (vfs_equalopts(*t, p)) { + opt->flags |= VFSOPT_CANCELONLY; + break; } } if (*t != NULL) @@ -1400,9 +1378,9 @@ vfs_filteropt(struct vfsoptlist *opts, c for(t = legal; *t != NULL; t++) { if (strcmp(*t, p) == 0) break; - if (q != NULL) { - if (strcmp(*t, q) == 0) - break; + if (vfs_equalopts(*t, p)) { + opt->flags |= VFSOPT_CANCELONLY; + break; } } if (*t != NULL)