The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/vfs_mount.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1999-2004 Poul-Henning Kamp
    3  * Copyright (c) 1999 Michael Smith
    4  * Copyright (c) 1989, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  * (c) UNIX System Laboratories, Inc.
    7  * All or some portions of this file are derived from material licensed
    8  * to the University of California by American Telephone and Telegraph
    9  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   10  * the permission of UNIX System Laboratories, Inc.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 4. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __FBSDID("$FreeBSD: releng/8.2/sys/kern/vfs_mount.c 214420 2010-10-27 15:44:49Z kib $");
   39 
   40 #include <sys/param.h>
   41 #include <sys/conf.h>
   42 #include <sys/fcntl.h>
   43 #include <sys/jail.h>
   44 #include <sys/kernel.h>
   45 #include <sys/libkern.h>
   46 #include <sys/malloc.h>
   47 #include <sys/mount.h>
   48 #include <sys/mutex.h>
   49 #include <sys/namei.h>
   50 #include <sys/priv.h>
   51 #include <sys/proc.h>
   52 #include <sys/filedesc.h>
   53 #include <sys/reboot.h>
   54 #include <sys/syscallsubr.h>
   55 #include <sys/sysproto.h>
   56 #include <sys/sx.h>
   57 #include <sys/sysctl.h>
   58 #include <sys/sysent.h>
   59 #include <sys/systm.h>
   60 #include <sys/vnode.h>
   61 #include <vm/uma.h>
   62 
   63 #include <geom/geom.h>
   64 
   65 #include <machine/stdarg.h>
   66 
   67 #include <security/audit/audit.h>
   68 #include <security/mac/mac_framework.h>
   69 
   70 #include "opt_rootdevname.h"
   71 
   72 #define ROOTNAME                "root_device"
   73 #define VFS_MOUNTARG_SIZE_MAX   (1024 * 64)
   74 
   75 static void     set_rootvnode(void);
   76 static int      vfs_domount(struct thread *td, const char *fstype,
   77                     char *fspath, int fsflags, void *fsdata);
   78 static int      vfs_mountroot_ask(void);
   79 static int      vfs_mountroot_try(const char *mountfrom, const char *options);
   80 static void     free_mntarg(struct mntarg *ma);
   81 
   82 static int      usermount = 0;
   83 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0,
   84     "Unprivileged users may mount and unmount file systems");
   85 
   86 MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount structure");
   87 MALLOC_DEFINE(M_VNODE_MARKER, "vnodemarker", "vnode marker");
   88 static uma_zone_t mount_zone;
   89 
   90 /* List of mounted filesystems. */
   91 struct mntlist mountlist = TAILQ_HEAD_INITIALIZER(mountlist);
   92 
   93 /* For any iteration/modification of mountlist */
   94 struct mtx mountlist_mtx;
   95 MTX_SYSINIT(mountlist, &mountlist_mtx, "mountlist", MTX_DEF);
   96 
   97 /*
   98  * The vnode of the system's root (/ in the filesystem, without chroot
   99  * active.)
  100  */
  101 struct vnode    *rootvnode;
  102 
  103 /*
  104  * The root filesystem is detailed in the kernel environment variable
  105  * vfs.root.mountfrom, which is expected to be in the general format
  106  *
  107  * <vfsname>:[<path>][  <vfsname>:[<path>] ...]
  108  * vfsname   := the name of a VFS known to the kernel and capable
  109  *              of being mounted as root
  110  * path      := disk device name or other data used by the filesystem
  111  *              to locate its physical store
  112  *
  113  * If the environment variable vfs.root.mountfrom is a space separated list,
  114  * each list element is tried in turn and the root filesystem will be mounted
  115  * from the first one that suceeds.
  116  *
  117  * The environment variable vfs.root.mountfrom.options is a comma delimited
  118  * set of string mount options.  These mount options must be parseable
  119  * by nmount() in the kernel.
  120  */
  121 
  122 /*
  123  * Global opts, taken by all filesystems
  124  */
  125 static const char *global_opts[] = {
  126         "errmsg",
  127         "fstype",
  128         "fspath",
  129         "ro",
  130         "rw",
  131         "nosuid",
  132         "noexec",
  133         NULL
  134 };
  135 
  136 /*
  137  * The root specifiers we will try if RB_CDROM is specified.
  138  */
  139 static char *cdrom_rootdevnames[] = {
  140         "cd9660:cd0",
  141         "cd9660:acd0",
  142         NULL
  143 };
  144 
  145 /* legacy find-root code */
  146 char            *rootdevnames[2] = {NULL, NULL};
  147 #ifndef ROOTDEVNAME
  148 #  define ROOTDEVNAME NULL
  149 #endif
  150 static const char       *ctrootdevname = ROOTDEVNAME;
  151 
  152 /*
  153  * ---------------------------------------------------------------------
  154  * Functions for building and sanitizing the mount options
  155  */
  156 
  157 /* Remove one mount option. */
  158 static void
  159 vfs_freeopt(struct vfsoptlist *opts, struct vfsopt *opt)
  160 {
  161 
  162         TAILQ_REMOVE(opts, opt, link);
  163         free(opt->name, M_MOUNT);
  164         if (opt->value != NULL)
  165                 free(opt->value, M_MOUNT);
  166         free(opt, M_MOUNT);
  167 }
  168 
  169 /* Release all resources related to the mount options. */
  170 void
  171 vfs_freeopts(struct vfsoptlist *opts)
  172 {
  173         struct vfsopt *opt;
  174 
  175         while (!TAILQ_EMPTY(opts)) {
  176                 opt = TAILQ_FIRST(opts);
  177                 vfs_freeopt(opts, opt);
  178         }
  179         free(opts, M_MOUNT);
  180 }
  181 
  182 void
  183 vfs_deleteopt(struct vfsoptlist *opts, const char *name)
  184 {
  185         struct vfsopt *opt, *temp;
  186 
  187         if (opts == NULL)
  188                 return;
  189         TAILQ_FOREACH_SAFE(opt, opts, link, temp)  {
  190                 if (strcmp(opt->name, name) == 0)
  191                         vfs_freeopt(opts, opt);
  192         }
  193 }
  194 
  195 /*
  196  * Check if options are equal (with or without the "no" prefix).
  197  */
  198 static int
  199 vfs_equalopts(const char *opt1, const char *opt2)
  200 {
  201         char *p;
  202 
  203         /* "opt" vs. "opt" or "noopt" vs. "noopt" */
  204         if (strcmp(opt1, opt2) == 0)
  205                 return (1);
  206         /* "noopt" vs. "opt" */
  207         if (strncmp(opt1, "no", 2) == 0 && strcmp(opt1 + 2, opt2) == 0)
  208                 return (1);
  209         /* "opt" vs. "noopt" */
  210         if (strncmp(opt2, "no", 2) == 0 && strcmp(opt1, opt2 + 2) == 0)
  211                 return (1);
  212         while ((p = strchr(opt1, '.')) != NULL &&
  213             !strncmp(opt1, opt2, ++p - opt1)) {
  214                 opt2 += p - opt1;
  215                 opt1 = p;
  216                 /* "foo.noopt" vs. "foo.opt" */
  217                 if (strncmp(opt1, "no", 2) == 0 && strcmp(opt1 + 2, opt2) == 0)
  218                         return (1);
  219                 /* "foo.opt" vs. "foo.noopt" */
  220                 if (strncmp(opt2, "no", 2) == 0 && strcmp(opt1, opt2 + 2) == 0)
  221                         return (1);
  222         }
  223         return (0);
  224 }
  225 
  226 /*
  227  * If a mount option is specified several times,
  228  * (with or without the "no" prefix) only keep
  229  * the last occurence of it.
  230  */
  231 static void
  232 vfs_sanitizeopts(struct vfsoptlist *opts)
  233 {
  234         struct vfsopt *opt, *opt2, *tmp;
  235 
  236         TAILQ_FOREACH_REVERSE(opt, opts, vfsoptlist, link) {
  237                 opt2 = TAILQ_PREV(opt, vfsoptlist, link);
  238                 while (opt2 != NULL) {
  239                         if (vfs_equalopts(opt->name, opt2->name)) {
  240                                 tmp = TAILQ_PREV(opt2, vfsoptlist, link);
  241                                 vfs_freeopt(opts, opt2);
  242                                 opt2 = tmp;
  243                         } else {
  244                                 opt2 = TAILQ_PREV(opt2, vfsoptlist, link);
  245                         }
  246                 }
  247         }
  248 }
  249 
  250 /*
  251  * Build a linked list of mount options from a struct uio.
  252  */
  253 int
  254 vfs_buildopts(struct uio *auio, struct vfsoptlist **options)
  255 {
  256         struct vfsoptlist *opts;
  257         struct vfsopt *opt;
  258         size_t memused, namelen, optlen;
  259         unsigned int i, iovcnt;
  260         int error;
  261 
  262         opts = malloc(sizeof(struct vfsoptlist), M_MOUNT, M_WAITOK);
  263         TAILQ_INIT(opts);
  264         memused = 0;
  265         iovcnt = auio->uio_iovcnt;
  266         for (i = 0; i < iovcnt; i += 2) {
  267                 namelen = auio->uio_iov[i].iov_len;
  268                 optlen = auio->uio_iov[i + 1].iov_len;
  269                 memused += sizeof(struct vfsopt) + optlen + namelen;
  270                 /*
  271                  * Avoid consuming too much memory, and attempts to overflow
  272                  * memused.
  273                  */
  274                 if (memused > VFS_MOUNTARG_SIZE_MAX ||
  275                     optlen > VFS_MOUNTARG_SIZE_MAX ||
  276                     namelen > VFS_MOUNTARG_SIZE_MAX) {
  277                         error = EINVAL;
  278                         goto bad;
  279                 }
  280 
  281                 opt = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK);
  282                 opt->name = malloc(namelen, M_MOUNT, M_WAITOK);
  283                 opt->value = NULL;
  284                 opt->len = 0;
  285                 opt->pos = i / 2;
  286                 opt->seen = 0;
  287 
  288                 /*
  289                  * Do this early, so jumps to "bad" will free the current
  290                  * option.
  291                  */
  292                 TAILQ_INSERT_TAIL(opts, opt, link);
  293 
  294                 if (auio->uio_segflg == UIO_SYSSPACE) {
  295                         bcopy(auio->uio_iov[i].iov_base, opt->name, namelen);
  296                 } else {
  297                         error = copyin(auio->uio_iov[i].iov_base, opt->name,
  298                             namelen);
  299                         if (error)
  300                                 goto bad;
  301                 }
  302                 /* Ensure names are null-terminated strings. */
  303                 if (namelen == 0 || opt->name[namelen - 1] != '\0') {
  304                         error = EINVAL;
  305                         goto bad;
  306                 }
  307                 if (optlen != 0) {
  308                         opt->len = optlen;
  309                         opt->value = malloc(optlen, M_MOUNT, M_WAITOK);
  310                         if (auio->uio_segflg == UIO_SYSSPACE) {
  311                                 bcopy(auio->uio_iov[i + 1].iov_base, opt->value,
  312                                     optlen);
  313                         } else {
  314                                 error = copyin(auio->uio_iov[i + 1].iov_base,
  315                                     opt->value, optlen);
  316                                 if (error)
  317                                         goto bad;
  318                         }
  319                 }
  320         }
  321         vfs_sanitizeopts(opts);
  322         *options = opts;
  323         return (0);
  324 bad:
  325         vfs_freeopts(opts);
  326         return (error);
  327 }
  328 
  329 /*
  330  * Merge the old mount options with the new ones passed
  331  * in the MNT_UPDATE case.
  332  *
  333  * XXX This function will keep a "nofoo" option in the
  334  *     new options if there is no matching "foo" option
  335  *     to be cancelled in the old options.  This is a bug
  336  *     if the option's canonical name is "foo".  E.g., "noro"
  337  *     shouldn't end up in the mount point's active options,
  338  *     but it can.
  339  */
  340 static void
  341 vfs_mergeopts(struct vfsoptlist *toopts, struct vfsoptlist *opts)
  342 {
  343         struct vfsopt *opt, *opt2, *new;
  344 
  345         TAILQ_FOREACH(opt, opts, link) {
  346                 /*
  347                  * Check that this option hasn't been redefined
  348                  * nor cancelled with a "no" mount option.
  349                  */
  350                 opt2 = TAILQ_FIRST(toopts);
  351                 while (opt2 != NULL) {
  352                         if (strcmp(opt2->name, opt->name) == 0)
  353                                 goto next;
  354                         if (strncmp(opt2->name, "no", 2) == 0 &&
  355                             strcmp(opt2->name + 2, opt->name) == 0) {
  356                                 vfs_freeopt(toopts, opt2);
  357                                 goto next;
  358                         }
  359                         opt2 = TAILQ_NEXT(opt2, link);
  360                 }
  361                 /* We want this option, duplicate it. */
  362                 new = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK);
  363                 new->name = malloc(strlen(opt->name) + 1, M_MOUNT, M_WAITOK);
  364                 strcpy(new->name, opt->name);
  365                 if (opt->len != 0) {
  366                         new->value = malloc(opt->len, M_MOUNT, M_WAITOK);
  367                         bcopy(opt->value, new->value, opt->len);
  368                 } else {
  369                         new->value = NULL;
  370                 }
  371                 new->len = opt->len;
  372                 new->seen = opt->seen;
  373                 TAILQ_INSERT_TAIL(toopts, new, link);
  374 next:
  375                 continue;
  376         }
  377 }
  378 
  379 /*
  380  * Mount a filesystem.
  381  */
  382 int
  383 nmount(td, uap)
  384         struct thread *td;
  385         struct nmount_args /* {
  386                 struct iovec *iovp;
  387                 unsigned int iovcnt;
  388                 int flags;
  389         } */ *uap;
  390 {
  391         struct uio *auio;
  392         int error;
  393         u_int iovcnt;
  394 
  395         AUDIT_ARG_FFLAGS(uap->flags);
  396         CTR4(KTR_VFS, "%s: iovp %p with iovcnt %d and flags %d", __func__,
  397             uap->iovp, uap->iovcnt, uap->flags);
  398 
  399         /*
  400          * Filter out MNT_ROOTFS.  We do not want clients of nmount() in
  401          * userspace to set this flag, but we must filter it out if we want
  402          * MNT_UPDATE on the root file system to work.
  403          * MNT_ROOTFS should only be set in the kernel in vfs_mountroot_try().
  404          */
  405         uap->flags &= ~MNT_ROOTFS;
  406 
  407         iovcnt = uap->iovcnt;
  408         /*
  409          * Check that we have an even number of iovec's
  410          * and that we have at least two options.
  411          */
  412         if ((iovcnt & 1) || (iovcnt < 4)) {
  413                 CTR2(KTR_VFS, "%s: failed for invalid iovcnt %d", __func__,
  414                     uap->iovcnt);
  415                 return (EINVAL);
  416         }
  417 
  418         error = copyinuio(uap->iovp, iovcnt, &auio);
  419         if (error) {
  420                 CTR2(KTR_VFS, "%s: failed for invalid uio op with %d errno",
  421                     __func__, error);
  422                 return (error);
  423         }
  424         error = vfs_donmount(td, uap->flags, auio);
  425 
  426         free(auio, M_IOV);
  427         return (error);
  428 }
  429 
  430 /*
  431  * ---------------------------------------------------------------------
  432  * Various utility functions
  433  */
  434 
  435 void
  436 vfs_ref(struct mount *mp)
  437 {
  438 
  439         CTR2(KTR_VFS, "%s: mp %p", __func__, mp);
  440         MNT_ILOCK(mp);
  441         MNT_REF(mp);
  442         MNT_IUNLOCK(mp);
  443 }
  444 
  445 void
  446 vfs_rel(struct mount *mp)
  447 {
  448 
  449         CTR2(KTR_VFS, "%s: mp %p", __func__, mp);
  450         MNT_ILOCK(mp);
  451         MNT_REL(mp);
  452         MNT_IUNLOCK(mp);
  453 }
  454 
  455 static int
  456 mount_init(void *mem, int size, int flags)
  457 {
  458         struct mount *mp;
  459 
  460         mp = (struct mount *)mem;
  461         mtx_init(&mp->mnt_mtx, "struct mount mtx", NULL, MTX_DEF);
  462         lockinit(&mp->mnt_explock, PVFS, "explock", 0, 0);
  463         return (0);
  464 }
  465 
  466 static void
  467 mount_fini(void *mem, int size)
  468 {
  469         struct mount *mp;
  470 
  471         mp = (struct mount *)mem;
  472         lockdestroy(&mp->mnt_explock);
  473         mtx_destroy(&mp->mnt_mtx);
  474 }
  475 
  476 /*
  477  * Allocate and initialize the mount point struct.
  478  */
  479 struct mount *
  480 vfs_mount_alloc(struct vnode *vp, struct vfsconf *vfsp, const char *fspath,
  481     struct ucred *cred)
  482 {
  483         struct mount *mp;
  484 
  485         mp = uma_zalloc(mount_zone, M_WAITOK);
  486         bzero(&mp->mnt_startzero,
  487             __rangeof(struct mount, mnt_startzero, mnt_endzero));
  488         TAILQ_INIT(&mp->mnt_nvnodelist);
  489         mp->mnt_nvnodelistsize = 0;
  490         mp->mnt_ref = 0;
  491         (void) vfs_busy(mp, MBF_NOWAIT);
  492         mp->mnt_op = vfsp->vfc_vfsops;
  493         mp->mnt_vfc = vfsp;
  494         vfsp->vfc_refcount++;   /* XXX Unlocked */
  495         mp->mnt_stat.f_type = vfsp->vfc_typenum;
  496         mp->mnt_gen++;
  497         strlcpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
  498         mp->mnt_vnodecovered = vp;
  499         mp->mnt_cred = crdup(cred);
  500         mp->mnt_stat.f_owner = cred->cr_uid;
  501         strlcpy(mp->mnt_stat.f_mntonname, fspath, MNAMELEN);
  502         mp->mnt_iosize_max = DFLTPHYS;
  503 #ifdef MAC
  504         mac_mount_init(mp);
  505         mac_mount_create(cred, mp);
  506 #endif
  507         arc4rand(&mp->mnt_hashseed, sizeof mp->mnt_hashseed, 0);
  508         return (mp);
  509 }
  510 
  511 /*
  512  * Destroy the mount struct previously allocated by vfs_mount_alloc().
  513  */
  514 void
  515 vfs_mount_destroy(struct mount *mp)
  516 {
  517 
  518         MNT_ILOCK(mp);
  519         mp->mnt_kern_flag |= MNTK_REFEXPIRE;
  520         if (mp->mnt_kern_flag & MNTK_MWAIT) {
  521                 mp->mnt_kern_flag &= ~MNTK_MWAIT;
  522                 wakeup(mp);
  523         }
  524         while (mp->mnt_ref)
  525                 msleep(mp, MNT_MTX(mp), PVFS, "mntref", 0);
  526         KASSERT(mp->mnt_ref == 0,
  527             ("%s: invalid refcount in the drain path @ %s:%d", __func__,
  528             __FILE__, __LINE__));
  529         if (mp->mnt_writeopcount != 0)
  530                 panic("vfs_mount_destroy: nonzero writeopcount");
  531         if (mp->mnt_secondary_writes != 0)
  532                 panic("vfs_mount_destroy: nonzero secondary_writes");
  533         mp->mnt_vfc->vfc_refcount--;
  534         if (!TAILQ_EMPTY(&mp->mnt_nvnodelist)) {
  535                 struct vnode *vp;
  536 
  537                 TAILQ_FOREACH(vp, &mp->mnt_nvnodelist, v_nmntvnodes)
  538                         vprint("", vp);
  539                 panic("unmount: dangling vnode");
  540         }
  541         if (mp->mnt_nvnodelistsize != 0)
  542                 panic("vfs_mount_destroy: nonzero nvnodelistsize");
  543         if (mp->mnt_lockref != 0)
  544                 panic("vfs_mount_destroy: nonzero lock refcount");
  545         MNT_IUNLOCK(mp);
  546 #ifdef MAC
  547         mac_mount_destroy(mp);
  548 #endif
  549         if (mp->mnt_opt != NULL)
  550                 vfs_freeopts(mp->mnt_opt);
  551         crfree(mp->mnt_cred);
  552         uma_zfree(mount_zone, mp);
  553 }
  554 
  555 int
  556 vfs_donmount(struct thread *td, int fsflags, struct uio *fsoptions)
  557 {
  558         struct vfsoptlist *optlist;
  559         struct vfsopt *opt, *noro_opt, *tmp_opt;
  560         char *fstype, *fspath, *errmsg;
  561         int error, fstypelen, fspathlen, errmsg_len, errmsg_pos;
  562         int has_rw, has_noro;
  563 
  564         errmsg = fspath = NULL;
  565         errmsg_len = has_noro = has_rw = fspathlen = 0;
  566         errmsg_pos = -1;
  567 
  568         error = vfs_buildopts(fsoptions, &optlist);
  569         if (error)
  570                 return (error);
  571 
  572         if (vfs_getopt(optlist, "errmsg", (void **)&errmsg, &errmsg_len) == 0)
  573                 errmsg_pos = vfs_getopt_pos(optlist, "errmsg");
  574 
  575         /*
  576          * We need these two options before the others,
  577          * and they are mandatory for any filesystem.
  578          * Ensure they are NUL terminated as well.
  579          */
  580         fstypelen = 0;
  581         error = vfs_getopt(optlist, "fstype", (void **)&fstype, &fstypelen);
  582         if (error || fstype[fstypelen - 1] != '\0') {
  583                 error = EINVAL;
  584                 if (errmsg != NULL)
  585                         strncpy(errmsg, "Invalid fstype", errmsg_len);
  586                 goto bail;
  587         }
  588         fspathlen = 0;
  589         error = vfs_getopt(optlist, "fspath", (void **)&fspath, &fspathlen);
  590         if (error || fspath[fspathlen - 1] != '\0') {
  591                 error = EINVAL;
  592                 if (errmsg != NULL)
  593                         strncpy(errmsg, "Invalid fspath", errmsg_len);
  594                 goto bail;
  595         }
  596 
  597         /*
  598          * We need to see if we have the "update" option
  599          * before we call vfs_domount(), since vfs_domount() has special
  600          * logic based on MNT_UPDATE.  This is very important
  601          * when we want to update the root filesystem.
  602          */
  603         TAILQ_FOREACH_SAFE(opt, optlist, link, tmp_opt) {
  604                 if (strcmp(opt->name, "update") == 0) {
  605                         fsflags |= MNT_UPDATE;
  606                         vfs_freeopt(optlist, opt);
  607                 }
  608                 else if (strcmp(opt->name, "async") == 0)
  609                         fsflags |= MNT_ASYNC;
  610                 else if (strcmp(opt->name, "force") == 0) {
  611                         fsflags |= MNT_FORCE;
  612                         vfs_freeopt(optlist, opt);
  613                 }
  614                 else if (strcmp(opt->name, "reload") == 0) {
  615                         fsflags |= MNT_RELOAD;
  616                         vfs_freeopt(optlist, opt);
  617                 }
  618                 else if (strcmp(opt->name, "multilabel") == 0)
  619                         fsflags |= MNT_MULTILABEL;
  620                 else if (strcmp(opt->name, "noasync") == 0)
  621                         fsflags &= ~MNT_ASYNC;
  622                 else if (strcmp(opt->name, "noatime") == 0)
  623                         fsflags |= MNT_NOATIME;
  624                 else if (strcmp(opt->name, "atime") == 0) {
  625                         free(opt->name, M_MOUNT);
  626                         opt->name = strdup("nonoatime", M_MOUNT);
  627                 }
  628                 else if (strcmp(opt->name, "noclusterr") == 0)
  629                         fsflags |= MNT_NOCLUSTERR;
  630                 else if (strcmp(opt->name, "clusterr") == 0) {
  631                         free(opt->name, M_MOUNT);
  632                         opt->name = strdup("nonoclusterr", M_MOUNT);
  633                 }
  634                 else if (strcmp(opt->name, "noclusterw") == 0)
  635                         fsflags |= MNT_NOCLUSTERW;
  636                 else if (strcmp(opt->name, "clusterw") == 0) {
  637                         free(opt->name, M_MOUNT);
  638                         opt->name = strdup("nonoclusterw", M_MOUNT);
  639                 }
  640                 else if (strcmp(opt->name, "noexec") == 0)
  641                         fsflags |= MNT_NOEXEC;
  642                 else if (strcmp(opt->name, "exec") == 0) {
  643                         free(opt->name, M_MOUNT);
  644                         opt->name = strdup("nonoexec", M_MOUNT);
  645                 }
  646                 else if (strcmp(opt->name, "nosuid") == 0)
  647                         fsflags |= MNT_NOSUID;
  648                 else if (strcmp(opt->name, "suid") == 0) {
  649                         free(opt->name, M_MOUNT);
  650                         opt->name = strdup("nonosuid", M_MOUNT);
  651                 }
  652                 else if (strcmp(opt->name, "nosymfollow") == 0)
  653                         fsflags |= MNT_NOSYMFOLLOW;
  654                 else if (strcmp(opt->name, "symfollow") == 0) {
  655                         free(opt->name, M_MOUNT);
  656                         opt->name = strdup("nonosymfollow", M_MOUNT);
  657                 }
  658                 else if (strcmp(opt->name, "noro") == 0) {
  659                         fsflags &= ~MNT_RDONLY;
  660                         has_noro = 1;
  661                 }
  662                 else if (strcmp(opt->name, "rw") == 0) {
  663                         fsflags &= ~MNT_RDONLY;
  664                         has_rw = 1;
  665                 }
  666                 else if (strcmp(opt->name, "ro") == 0)
  667                         fsflags |= MNT_RDONLY;
  668                 else if (strcmp(opt->name, "rdonly") == 0) {
  669                         free(opt->name, M_MOUNT);
  670                         opt->name = strdup("ro", M_MOUNT);
  671                         fsflags |= MNT_RDONLY;
  672                 }
  673                 else if (strcmp(opt->name, "suiddir") == 0)
  674                         fsflags |= MNT_SUIDDIR;
  675                 else if (strcmp(opt->name, "sync") == 0)
  676                         fsflags |= MNT_SYNCHRONOUS;
  677                 else if (strcmp(opt->name, "union") == 0)
  678                         fsflags |= MNT_UNION;
  679         }
  680 
  681         /*
  682          * If "rw" was specified as a mount option, and we
  683          * are trying to update a mount-point from "ro" to "rw",
  684          * we need a mount option "noro", since in vfs_mergeopts(),
  685          * "noro" will cancel "ro", but "rw" will not do anything.
  686          */
  687         if (has_rw && !has_noro) {
  688                 noro_opt = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK);
  689                 noro_opt->name = strdup("noro", M_MOUNT);
  690                 noro_opt->value = NULL;
  691                 noro_opt->len = 0;
  692                 noro_opt->pos = -1;
  693                 noro_opt->seen = 1;
  694                 TAILQ_INSERT_TAIL(optlist, noro_opt, link);
  695         }
  696 
  697         /*
  698          * Be ultra-paranoid about making sure the type and fspath
  699          * variables will fit in our mp buffers, including the
  700          * terminating NUL.
  701          */
  702         if (fstypelen >= MFSNAMELEN - 1 || fspathlen >= MNAMELEN - 1) {
  703                 error = ENAMETOOLONG;
  704                 goto bail;
  705         }
  706 
  707         mtx_lock(&Giant);
  708         error = vfs_domount(td, fstype, fspath, fsflags, optlist);
  709         mtx_unlock(&Giant);
  710 bail:
  711         /* copyout the errmsg */
  712         if (errmsg_pos != -1 && ((2 * errmsg_pos + 1) < fsoptions->uio_iovcnt)
  713             && errmsg_len > 0 && errmsg != NULL) {
  714                 if (fsoptions->uio_segflg == UIO_SYSSPACE) {
  715                         bcopy(errmsg,
  716                             fsoptions->uio_iov[2 * errmsg_pos + 1].iov_base,
  717                             fsoptions->uio_iov[2 * errmsg_pos + 1].iov_len);
  718                 } else {
  719                         copyout(errmsg,
  720                             fsoptions->uio_iov[2 * errmsg_pos + 1].iov_base,
  721                             fsoptions->uio_iov[2 * errmsg_pos + 1].iov_len);
  722                 }
  723         }
  724 
  725         if (error != 0)
  726                 vfs_freeopts(optlist);
  727         return (error);
  728 }
  729 
  730 /*
  731  * Old mount API.
  732  */
  733 #ifndef _SYS_SYSPROTO_H_
  734 struct mount_args {
  735         char    *type;
  736         char    *path;
  737         int     flags;
  738         caddr_t data;
  739 };
  740 #endif
  741 /* ARGSUSED */
  742 int
  743 mount(td, uap)
  744         struct thread *td;
  745         struct mount_args /* {
  746                 char *type;
  747                 char *path;
  748                 int flags;
  749                 caddr_t data;
  750         } */ *uap;
  751 {
  752         char *fstype;
  753         struct vfsconf *vfsp = NULL;
  754         struct mntarg *ma = NULL;
  755         int error;
  756 
  757         AUDIT_ARG_FFLAGS(uap->flags);
  758 
  759         /*
  760          * Filter out MNT_ROOTFS.  We do not want clients of mount() in
  761          * userspace to set this flag, but we must filter it out if we want
  762          * MNT_UPDATE on the root file system to work.
  763          * MNT_ROOTFS should only be set in the kernel in vfs_mountroot_try().
  764          */
  765         uap->flags &= ~MNT_ROOTFS;
  766 
  767         fstype = malloc(MFSNAMELEN, M_TEMP, M_WAITOK);
  768         error = copyinstr(uap->type, fstype, MFSNAMELEN, NULL);
  769         if (error) {
  770                 free(fstype, M_TEMP);
  771                 return (error);
  772         }
  773 
  774         AUDIT_ARG_TEXT(fstype);
  775         mtx_lock(&Giant);
  776         vfsp = vfs_byname_kld(fstype, td, &error);
  777         free(fstype, M_TEMP);
  778         if (vfsp == NULL) {
  779                 mtx_unlock(&Giant);
  780                 return (ENOENT);
  781         }
  782         if (vfsp->vfc_vfsops->vfs_cmount == NULL) {
  783                 mtx_unlock(&Giant);
  784                 return (EOPNOTSUPP);
  785         }
  786 
  787         ma = mount_argsu(ma, "fstype", uap->type, MNAMELEN);
  788         ma = mount_argsu(ma, "fspath", uap->path, MNAMELEN);
  789         ma = mount_argb(ma, uap->flags & MNT_RDONLY, "noro");
  790         ma = mount_argb(ma, !(uap->flags & MNT_NOSUID), "nosuid");
  791         ma = mount_argb(ma, !(uap->flags & MNT_NOEXEC), "noexec");
  792 
  793         error = vfsp->vfc_vfsops->vfs_cmount(ma, uap->data, uap->flags);
  794         mtx_unlock(&Giant);
  795         return (error);
  796 }
  797 
  798 
  799 /*
  800  * vfs_domount(): actually attempt a filesystem mount.
  801  */
  802 static int
  803 vfs_domount(
  804         struct thread *td,      /* Calling thread. */
  805         const char *fstype,     /* Filesystem type. */
  806         char *fspath,           /* Mount path. */
  807         int fsflags,            /* Flags common to all filesystems. */
  808         void *fsdata            /* Options local to the filesystem. */
  809         )
  810 {
  811         struct vnode *vp;
  812         struct mount *mp;
  813         struct vfsconf *vfsp;
  814         struct oexport_args oexport;
  815         struct export_args export;
  816         int error, flag = 0;
  817         struct vattr va;
  818         struct nameidata nd;
  819 
  820         mtx_assert(&Giant, MA_OWNED);
  821         /*
  822          * Be ultra-paranoid about making sure the type and fspath
  823          * variables will fit in our mp buffers, including the
  824          * terminating NUL.
  825          */
  826         if (strlen(fstype) >= MFSNAMELEN || strlen(fspath) >= MNAMELEN)
  827                 return (ENAMETOOLONG);
  828 
  829         if (jailed(td->td_ucred) || usermount == 0) {
  830                 if ((error = priv_check(td, PRIV_VFS_MOUNT)) != 0)
  831                         return (error);
  832         }
  833 
  834         /*
  835          * Do not allow NFS export or MNT_SUIDDIR by unprivileged users.
  836          */
  837         if (fsflags & MNT_EXPORTED) {
  838                 error = priv_check(td, PRIV_VFS_MOUNT_EXPORTED);
  839                 if (error)
  840                         return (error);
  841         }
  842         if (fsflags & MNT_SUIDDIR) {
  843                 error = priv_check(td, PRIV_VFS_MOUNT_SUIDDIR);
  844                 if (error)
  845                         return (error);
  846         }
  847         /*
  848          * Silently enforce MNT_NOSUID and MNT_USER for unprivileged users.
  849          */
  850         if ((fsflags & (MNT_NOSUID | MNT_USER)) != (MNT_NOSUID | MNT_USER)) {
  851                 if (priv_check(td, PRIV_VFS_MOUNT_NONUSER) != 0)
  852                         fsflags |= MNT_NOSUID | MNT_USER;
  853         }
  854 
  855         /* Load KLDs before we lock the covered vnode to avoid reversals. */
  856         vfsp = NULL;
  857         if ((fsflags & MNT_UPDATE) == 0) {
  858                 /* Don't try to load KLDs if we're mounting the root. */
  859                 if (fsflags & MNT_ROOTFS)
  860                         vfsp = vfs_byname(fstype);
  861                 else
  862                         vfsp = vfs_byname_kld(fstype, td, &error);
  863                 if (vfsp == NULL)
  864                         return (ENODEV);
  865                 if (jailed(td->td_ucred) && !(vfsp->vfc_flags & VFCF_JAIL))
  866                         return (EPERM);
  867         }
  868         /*
  869          * Get vnode to be covered
  870          */
  871         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_SYSSPACE,
  872             fspath, td);
  873         if ((error = namei(&nd)) != 0)
  874                 return (error);
  875         NDFREE(&nd, NDF_ONLY_PNBUF);
  876         vp = nd.ni_vp;
  877         if (fsflags & MNT_UPDATE) {
  878                 if ((vp->v_vflag & VV_ROOT) == 0) {
  879                         vput(vp);
  880                         return (EINVAL);
  881                 }
  882                 mp = vp->v_mount;
  883                 MNT_ILOCK(mp);
  884                 flag = mp->mnt_flag;
  885                 /*
  886                  * We only allow the filesystem to be reloaded if it
  887                  * is currently mounted read-only.
  888                  */
  889                 if ((fsflags & MNT_RELOAD) &&
  890                     ((mp->mnt_flag & MNT_RDONLY) == 0)) {
  891                         MNT_IUNLOCK(mp);
  892                         vput(vp);
  893                         return (EOPNOTSUPP);    /* Needs translation */
  894                 }
  895                 MNT_IUNLOCK(mp);
  896                 /*
  897                  * Only privileged root, or (if MNT_USER is set) the user that
  898                  * did the original mount is permitted to update it.
  899                  */
  900                 error = vfs_suser(mp, td);
  901                 if (error) {
  902                         vput(vp);
  903                         return (error);
  904                 }
  905                 if (vfs_busy(mp, MBF_NOWAIT)) {
  906                         vput(vp);
  907                         return (EBUSY);
  908                 }
  909                 VI_LOCK(vp);
  910                 if ((vp->v_iflag & VI_MOUNT) != 0 ||
  911                     vp->v_mountedhere != NULL) {
  912                         VI_UNLOCK(vp);
  913                         vfs_unbusy(mp);
  914                         vput(vp);
  915                         return (EBUSY);
  916                 }
  917                 vp->v_iflag |= VI_MOUNT;
  918                 VI_UNLOCK(vp);
  919                 MNT_ILOCK(mp);
  920                 mp->mnt_flag |= fsflags &
  921                     (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_SNAPSHOT | MNT_ROOTFS);
  922                 MNT_IUNLOCK(mp);
  923                 VOP_UNLOCK(vp, 0);
  924                 mp->mnt_optnew = fsdata;
  925                 vfs_mergeopts(mp->mnt_optnew, mp->mnt_opt);
  926         } else {
  927                 /*
  928                  * If the user is not root, ensure that they own the directory
  929                  * onto which we are attempting to mount.
  930                  */
  931                 error = VOP_GETATTR(vp, &va, td->td_ucred);
  932                 if (error) {
  933                         vput(vp);
  934                         return (error);
  935                 }
  936                 if (va.va_uid != td->td_ucred->cr_uid) {
  937                         error = priv_check_cred(td->td_ucred, PRIV_VFS_ADMIN,
  938                             0);
  939                         if (error) {
  940                                 vput(vp);
  941                                 return (error);
  942                         }
  943                 }
  944                 error = vinvalbuf(vp, V_SAVE, 0, 0);
  945                 if (error != 0) {
  946                         vput(vp);
  947                         return (error);
  948                 }
  949                 if (vp->v_type != VDIR) {
  950                         vput(vp);
  951                         return (ENOTDIR);
  952                 }
  953                 VI_LOCK(vp);
  954                 if ((vp->v_iflag & VI_MOUNT) != 0 ||
  955                     vp->v_mountedhere != NULL) {
  956                         VI_UNLOCK(vp);
  957                         vput(vp);
  958                         return (EBUSY);
  959                 }
  960                 vp->v_iflag |= VI_MOUNT;
  961                 VI_UNLOCK(vp);
  962 
  963                 /*
  964                  * Allocate and initialize the filesystem.
  965                  */
  966                 mp = vfs_mount_alloc(vp, vfsp, fspath, td->td_ucred);
  967                 VOP_UNLOCK(vp, 0);
  968 
  969                 /* XXXMAC: pass to vfs_mount_alloc? */
  970                 mp->mnt_optnew = fsdata;
  971         }
  972 
  973         /*
  974          * Set the mount level flags.
  975          */
  976         MNT_ILOCK(mp);
  977         mp->mnt_flag = (mp->mnt_flag & ~MNT_UPDATEMASK) |
  978                 (fsflags & (MNT_UPDATEMASK | MNT_FORCE | MNT_ROOTFS |
  979                             MNT_RDONLY));
  980         if ((mp->mnt_flag & MNT_ASYNC) == 0)
  981                 mp->mnt_kern_flag &= ~MNTK_ASYNC;
  982         MNT_IUNLOCK(mp);
  983         /*
  984          * Mount the filesystem.
  985          * XXX The final recipients of VFS_MOUNT just overwrite the ndp they
  986          * get.  No freeing of cn_pnbuf.
  987          */
  988         error = VFS_MOUNT(mp);
  989 
  990         /*
  991          * Process the export option only if we are
  992          * updating mount options.
  993          */
  994         if (!error && (fsflags & MNT_UPDATE)) {
  995                 if (vfs_copyopt(mp->mnt_optnew, "export", &export,
  996                     sizeof(export)) == 0)
  997                         error = vfs_export(mp, &export);
  998                 else if (vfs_copyopt(mp->mnt_optnew, "export", &oexport,
  999                         sizeof(oexport)) == 0) {
 1000                         export.ex_flags = oexport.ex_flags;
 1001                         export.ex_root = oexport.ex_root;
 1002                         export.ex_anon = oexport.ex_anon;
 1003                         export.ex_addr = oexport.ex_addr;
 1004                         export.ex_addrlen = oexport.ex_addrlen;
 1005                         export.ex_mask = oexport.ex_mask;
 1006                         export.ex_masklen = oexport.ex_masklen;
 1007                         export.ex_indexfile = oexport.ex_indexfile;
 1008                         export.ex_numsecflavors = 0;
 1009                         error = vfs_export(mp, &export);
 1010                 }
 1011         }
 1012 
 1013         if (!error) {
 1014                 if (mp->mnt_opt != NULL)
 1015                         vfs_freeopts(mp->mnt_opt);
 1016                 mp->mnt_opt = mp->mnt_optnew;
 1017                 (void)VFS_STATFS(mp, &mp->mnt_stat);
 1018         }
 1019         /*
 1020          * Prevent external consumers of mount options from reading
 1021          * mnt_optnew.
 1022         */
 1023         mp->mnt_optnew = NULL;
 1024         if (mp->mnt_flag & MNT_UPDATE) {
 1025                 MNT_ILOCK(mp);
 1026                 if (error)
 1027                         mp->mnt_flag = (mp->mnt_flag & MNT_QUOTA) |
 1028                                 (flag & ~MNT_QUOTA);
 1029                 else
 1030                         mp->mnt_flag &= ~(MNT_UPDATE | MNT_RELOAD |
 1031                                           MNT_FORCE | MNT_SNAPSHOT);
 1032                 if ((mp->mnt_flag & MNT_ASYNC) != 0 && mp->mnt_noasync == 0)
 1033                         mp->mnt_kern_flag |= MNTK_ASYNC;
 1034                 else
 1035                         mp->mnt_kern_flag &= ~MNTK_ASYNC;
 1036                 MNT_IUNLOCK(mp);
 1037                 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
 1038                         if (mp->mnt_syncer == NULL)
 1039                                 error = vfs_allocate_syncvnode(mp);
 1040                 } else {
 1041                         if (mp->mnt_syncer != NULL)
 1042                                 vrele(mp->mnt_syncer);
 1043                         mp->mnt_syncer = NULL;
 1044                 }
 1045                 vfs_unbusy(mp);
 1046                 VI_LOCK(vp);
 1047                 vp->v_iflag &= ~VI_MOUNT;
 1048                 VI_UNLOCK(vp);
 1049                 vrele(vp);
 1050                 return (error);
 1051         }
 1052         MNT_ILOCK(mp);
 1053         if ((mp->mnt_flag & MNT_ASYNC) != 0 && mp->mnt_noasync == 0)
 1054                 mp->mnt_kern_flag |= MNTK_ASYNC;
 1055         else
 1056                 mp->mnt_kern_flag &= ~MNTK_ASYNC;
 1057         MNT_IUNLOCK(mp);
 1058         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 1059         /*
 1060          * Put the new filesystem on the mount list after root.
 1061          */
 1062         cache_purge(vp);
 1063         if (!error) {
 1064                 struct vnode *newdp;
 1065 
 1066                 VI_LOCK(vp);
 1067                 vp->v_iflag &= ~VI_MOUNT;
 1068                 VI_UNLOCK(vp);
 1069                 vp->v_mountedhere = mp;
 1070                 mtx_lock(&mountlist_mtx);
 1071                 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
 1072                 mtx_unlock(&mountlist_mtx);
 1073                 vfs_event_signal(NULL, VQ_MOUNT, 0);
 1074                 if (VFS_ROOT(mp, LK_EXCLUSIVE, &newdp))
 1075                         panic("mount: lost mount");
 1076                 VOP_UNLOCK(newdp, 0);
 1077                 VOP_UNLOCK(vp, 0);
 1078                 mountcheckdirs(vp, newdp);
 1079                 vrele(newdp);
 1080                 if ((mp->mnt_flag & MNT_RDONLY) == 0)
 1081                         error = vfs_allocate_syncvnode(mp);
 1082                 vfs_unbusy(mp);
 1083                 if (error)
 1084                         vrele(vp);
 1085         } else {
 1086                 VI_LOCK(vp);
 1087                 vp->v_iflag &= ~VI_MOUNT;
 1088                 VI_UNLOCK(vp);
 1089                 vfs_unbusy(mp);
 1090                 vfs_mount_destroy(mp);
 1091                 vput(vp);
 1092         }
 1093         return (error);
 1094 }
 1095 
 1096 /*
 1097  * Unmount a filesystem.
 1098  *
 1099  * Note: unmount takes a path to the vnode mounted on as argument, not
 1100  * special file (as before).
 1101  */
 1102 #ifndef _SYS_SYSPROTO_H_
 1103 struct unmount_args {
 1104         char    *path;
 1105         int     flags;
 1106 };
 1107 #endif
 1108 /* ARGSUSED */
 1109 int
 1110 unmount(td, uap)
 1111         struct thread *td;
 1112         register struct unmount_args /* {
 1113                 char *path;
 1114                 int flags;
 1115         } */ *uap;
 1116 {
 1117         struct mount *mp;
 1118         char *pathbuf;
 1119         int error, id0, id1;
 1120 
 1121         AUDIT_ARG_VALUE(uap->flags);
 1122         if (jailed(td->td_ucred) || usermount == 0) {
 1123                 error = priv_check(td, PRIV_VFS_UNMOUNT);
 1124                 if (error)
 1125                         return (error);
 1126         }
 1127 
 1128         pathbuf = malloc(MNAMELEN, M_TEMP, M_WAITOK);
 1129         error = copyinstr(uap->path, pathbuf, MNAMELEN, NULL);
 1130         if (error) {
 1131                 free(pathbuf, M_TEMP);
 1132                 return (error);
 1133         }
 1134         mtx_lock(&Giant);
 1135         if (uap->flags & MNT_BYFSID) {
 1136                 AUDIT_ARG_TEXT(pathbuf);
 1137                 /* Decode the filesystem ID. */
 1138                 if (sscanf(pathbuf, "FSID:%d:%d", &id0, &id1) != 2) {
 1139                         mtx_unlock(&Giant);
 1140                         free(pathbuf, M_TEMP);
 1141                         return (EINVAL);
 1142                 }
 1143 
 1144                 mtx_lock(&mountlist_mtx);
 1145                 TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) {
 1146                         if (mp->mnt_stat.f_fsid.val[0] == id0 &&
 1147                             mp->mnt_stat.f_fsid.val[1] == id1)
 1148                                 break;
 1149                 }
 1150                 mtx_unlock(&mountlist_mtx);
 1151         } else {
 1152                 AUDIT_ARG_UPATH1(td, pathbuf);
 1153                 mtx_lock(&mountlist_mtx);
 1154                 TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) {
 1155                         if (strcmp(mp->mnt_stat.f_mntonname, pathbuf) == 0)
 1156                                 break;
 1157                 }
 1158                 mtx_unlock(&mountlist_mtx);
 1159         }
 1160         free(pathbuf, M_TEMP);
 1161         if (mp == NULL) {
 1162                 /*
 1163                  * Previously we returned ENOENT for a nonexistent path and
 1164                  * EINVAL for a non-mountpoint.  We cannot tell these apart
 1165                  * now, so in the !MNT_BYFSID case return the more likely
 1166                  * EINVAL for compatibility.
 1167                  */
 1168                 mtx_unlock(&Giant);
 1169                 return ((uap->flags & MNT_BYFSID) ? ENOENT : EINVAL);
 1170         }
 1171 
 1172         /*
 1173          * Don't allow unmounting the root filesystem.
 1174          */
 1175         if (mp->mnt_flag & MNT_ROOTFS) {
 1176                 mtx_unlock(&Giant);
 1177                 return (EINVAL);
 1178         }
 1179         error = dounmount(mp, uap->flags, td);
 1180         mtx_unlock(&Giant);
 1181         return (error);
 1182 }
 1183 
 1184 /*
 1185  * Do the actual filesystem unmount.
 1186  */
 1187 int
 1188 dounmount(mp, flags, td)
 1189         struct mount *mp;
 1190         int flags;
 1191         struct thread *td;
 1192 {
 1193         struct vnode *coveredvp, *fsrootvp;
 1194         int error;
 1195         int async_flag;
 1196         int mnt_gen_r;
 1197 
 1198         mtx_assert(&Giant, MA_OWNED);
 1199 
 1200         if ((coveredvp = mp->mnt_vnodecovered) != NULL) {
 1201                 mnt_gen_r = mp->mnt_gen;
 1202                 VI_LOCK(coveredvp);
 1203                 vholdl(coveredvp);
 1204                 vn_lock(coveredvp, LK_EXCLUSIVE | LK_INTERLOCK | LK_RETRY);
 1205                 vdrop(coveredvp);
 1206                 /*
 1207                  * Check for mp being unmounted while waiting for the
 1208                  * covered vnode lock.
 1209                  */
 1210                 if (coveredvp->v_mountedhere != mp ||
 1211                     coveredvp->v_mountedhere->mnt_gen != mnt_gen_r) {
 1212                         VOP_UNLOCK(coveredvp, 0);
 1213                         return (EBUSY);
 1214                 }
 1215         }
 1216         /*
 1217          * Only privileged root, or (if MNT_USER is set) the user that did the
 1218          * original mount is permitted to unmount this filesystem.
 1219          */
 1220         error = vfs_suser(mp, td);
 1221         if (error) {
 1222                 if (coveredvp)
 1223                         VOP_UNLOCK(coveredvp, 0);
 1224                 return (error);
 1225         }
 1226 
 1227         MNT_ILOCK(mp);
 1228         if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
 1229                 MNT_IUNLOCK(mp);
 1230                 if (coveredvp)
 1231                         VOP_UNLOCK(coveredvp, 0);
 1232                 return (EBUSY);
 1233         }
 1234         mp->mnt_kern_flag |= MNTK_UNMOUNT | MNTK_NOINSMNTQ;
 1235         /* Allow filesystems to detect that a forced unmount is in progress. */
 1236         if (flags & MNT_FORCE)
 1237                 mp->mnt_kern_flag |= MNTK_UNMOUNTF;
 1238         error = 0;
 1239         if (mp->mnt_lockref) {
 1240                 if ((flags & MNT_FORCE) == 0) {
 1241                         mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_NOINSMNTQ |
 1242                             MNTK_UNMOUNTF);
 1243                         if (mp->mnt_kern_flag & MNTK_MWAIT) {
 1244                                 mp->mnt_kern_flag &= ~MNTK_MWAIT;
 1245                                 wakeup(mp);
 1246                         }
 1247                         MNT_IUNLOCK(mp);
 1248                         if (coveredvp)
 1249                                 VOP_UNLOCK(coveredvp, 0);
 1250                         return (EBUSY);
 1251                 }
 1252                 mp->mnt_kern_flag |= MNTK_DRAINING;
 1253                 error = msleep(&mp->mnt_lockref, MNT_MTX(mp), PVFS,
 1254                     "mount drain", 0);
 1255         }
 1256         MNT_IUNLOCK(mp);
 1257         KASSERT(mp->mnt_lockref == 0,
 1258             ("%s: invalid lock refcount in the drain path @ %s:%d",
 1259             __func__, __FILE__, __LINE__));
 1260         KASSERT(error == 0,
 1261             ("%s: invalid return value for msleep in the drain path @ %s:%d",
 1262             __func__, __FILE__, __LINE__));
 1263         vn_start_write(NULL, &mp, V_WAIT);
 1264 
 1265         if (mp->mnt_flag & MNT_EXPUBLIC)
 1266                 vfs_setpublicfs(NULL, NULL, NULL);
 1267 
 1268         vfs_msync(mp, MNT_WAIT);
 1269         MNT_ILOCK(mp);
 1270         async_flag = mp->mnt_flag & MNT_ASYNC;
 1271         mp->mnt_flag &= ~MNT_ASYNC;
 1272         mp->mnt_kern_flag &= ~MNTK_ASYNC;
 1273         MNT_IUNLOCK(mp);
 1274         cache_purgevfs(mp);     /* remove cache entries for this file sys */
 1275         if (mp->mnt_syncer != NULL)
 1276                 vrele(mp->mnt_syncer);
 1277         /*
 1278          * For forced unmounts, move process cdir/rdir refs on the fs root
 1279          * vnode to the covered vnode.  For non-forced unmounts we want
 1280          * such references to cause an EBUSY error.
 1281          */
 1282         if ((flags & MNT_FORCE) &&
 1283             VFS_ROOT(mp, LK_EXCLUSIVE, &fsrootvp) == 0) {
 1284                 if (mp->mnt_vnodecovered != NULL)
 1285                         mountcheckdirs(fsrootvp, mp->mnt_vnodecovered);
 1286                 if (fsrootvp == rootvnode) {
 1287                         vrele(rootvnode);
 1288                         rootvnode = NULL;
 1289                 }
 1290                 vput(fsrootvp);
 1291         }
 1292         if (((mp->mnt_flag & MNT_RDONLY) ||
 1293              (error = VFS_SYNC(mp, MNT_WAIT)) == 0) || (flags & MNT_FORCE) != 0)
 1294                 error = VFS_UNMOUNT(mp, flags);
 1295         vn_finished_write(mp);
 1296         /*
 1297          * If we failed to flush the dirty blocks for this mount point,
 1298          * undo all the cdir/rdir and rootvnode changes we made above.
 1299          * Unless we failed to do so because the device is reporting that
 1300          * it doesn't exist anymore.
 1301          */
 1302         if (error && error != ENXIO) {
 1303                 if ((flags & MNT_FORCE) &&
 1304                     VFS_ROOT(mp, LK_EXCLUSIVE, &fsrootvp) == 0) {
 1305                         if (mp->mnt_vnodecovered != NULL)
 1306                                 mountcheckdirs(mp->mnt_vnodecovered, fsrootvp);
 1307                         if (rootvnode == NULL) {
 1308                                 rootvnode = fsrootvp;
 1309                                 vref(rootvnode);
 1310                         }
 1311                         vput(fsrootvp);
 1312                 }
 1313                 MNT_ILOCK(mp);
 1314                 mp->mnt_kern_flag &= ~MNTK_NOINSMNTQ;
 1315                 if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL) {
 1316                         MNT_IUNLOCK(mp);
 1317                         (void) vfs_allocate_syncvnode(mp);
 1318                         MNT_ILOCK(mp);
 1319                 }
 1320                 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
 1321                 mp->mnt_flag |= async_flag;
 1322                 if ((mp->mnt_flag & MNT_ASYNC) != 0 && mp->mnt_noasync == 0)
 1323                         mp->mnt_kern_flag |= MNTK_ASYNC;
 1324                 if (mp->mnt_kern_flag & MNTK_MWAIT) {
 1325                         mp->mnt_kern_flag &= ~MNTK_MWAIT;
 1326                         wakeup(mp);
 1327                 }
 1328                 MNT_IUNLOCK(mp);
 1329                 if (coveredvp)
 1330                         VOP_UNLOCK(coveredvp, 0);
 1331                 return (error);
 1332         }
 1333         mtx_lock(&mountlist_mtx);
 1334         TAILQ_REMOVE(&mountlist, mp, mnt_list);
 1335         mtx_unlock(&mountlist_mtx);
 1336         if (coveredvp != NULL) {
 1337                 coveredvp->v_mountedhere = NULL;
 1338                 vput(coveredvp);
 1339         }
 1340         vfs_event_signal(NULL, VQ_UNMOUNT, 0);
 1341         vfs_mount_destroy(mp);
 1342         return (0);
 1343 }
 1344 
 1345 /*
 1346  * ---------------------------------------------------------------------
 1347  * Mounting of root filesystem
 1348  *
 1349  */
 1350 
 1351 struct root_hold_token {
 1352         const char                      *who;
 1353         LIST_ENTRY(root_hold_token)     list;
 1354 };
 1355 
 1356 static LIST_HEAD(, root_hold_token)     root_holds =
 1357     LIST_HEAD_INITIALIZER(root_holds);
 1358 
 1359 static int root_mount_complete;
 1360 
 1361 /*
 1362  * Hold root mount.
 1363  */
 1364 struct root_hold_token *
 1365 root_mount_hold(const char *identifier)
 1366 {
 1367         struct root_hold_token *h;
 1368 
 1369         if (root_mounted())
 1370                 return (NULL);
 1371 
 1372         h = malloc(sizeof *h, M_DEVBUF, M_ZERO | M_WAITOK);
 1373         h->who = identifier;
 1374         mtx_lock(&mountlist_mtx);
 1375         LIST_INSERT_HEAD(&root_holds, h, list);
 1376         mtx_unlock(&mountlist_mtx);
 1377         return (h);
 1378 }
 1379 
 1380 /*
 1381  * Release root mount.
 1382  */
 1383 void
 1384 root_mount_rel(struct root_hold_token *h)
 1385 {
 1386 
 1387         if (h == NULL)
 1388                 return;
 1389         mtx_lock(&mountlist_mtx);
 1390         LIST_REMOVE(h, list);
 1391         wakeup(&root_holds);
 1392         mtx_unlock(&mountlist_mtx);
 1393         free(h, M_DEVBUF);
 1394 }
 1395 
 1396 /*
 1397  * Wait for all subsystems to release root mount.
 1398  */
 1399 static void
 1400 root_mount_prepare(void)
 1401 {
 1402         struct root_hold_token *h;
 1403         struct timeval lastfail;
 1404         int curfail = 0;
 1405 
 1406         for (;;) {
 1407                 DROP_GIANT();
 1408                 g_waitidle();
 1409                 PICKUP_GIANT();
 1410                 mtx_lock(&mountlist_mtx);
 1411                 if (LIST_EMPTY(&root_holds)) {
 1412                         mtx_unlock(&mountlist_mtx);
 1413                         break;
 1414                 }
 1415                 if (ppsratecheck(&lastfail, &curfail, 1)) {
 1416                         printf("Root mount waiting for:");
 1417                         LIST_FOREACH(h, &root_holds, list)
 1418                                 printf(" %s", h->who);
 1419                         printf("\n");
 1420                 }
 1421                 msleep(&root_holds, &mountlist_mtx, PZERO | PDROP, "roothold",
 1422                     hz);
 1423         }
 1424 }
 1425 
 1426 /*
 1427  * Root was mounted, share the good news.
 1428  */
 1429 static void
 1430 root_mount_done(void)
 1431 {
 1432 
 1433         /* Keep prison0's root in sync with the global rootvnode. */
 1434         mtx_lock(&prison0.pr_mtx);
 1435         prison0.pr_root = rootvnode;
 1436         vref(prison0.pr_root);
 1437         mtx_unlock(&prison0.pr_mtx);
 1438         /*
 1439          * Use a mutex to prevent the wakeup being missed and waiting for
 1440          * an extra 1 second sleep.
 1441          */
 1442         mtx_lock(&mountlist_mtx);
 1443         root_mount_complete = 1;
 1444         wakeup(&root_mount_complete);
 1445         mtx_unlock(&mountlist_mtx);
 1446 }
 1447 
 1448 /*
 1449  * Return true if root is already mounted.
 1450  */
 1451 int
 1452 root_mounted(void)
 1453 {
 1454 
 1455         /* No mutex is acquired here because int stores are atomic. */
 1456         return (root_mount_complete);
 1457 }
 1458 
 1459 /*
 1460  * Wait until root is mounted.
 1461  */
 1462 void
 1463 root_mount_wait(void)
 1464 {
 1465 
 1466         /*
 1467          * Panic on an obvious deadlock - the function can't be called from
 1468          * a thread which is doing the whole SYSINIT stuff.
 1469          */
 1470         KASSERT(curthread->td_proc->p_pid != 0,
 1471             ("root_mount_wait: cannot be called from the swapper thread"));
 1472         mtx_lock(&mountlist_mtx);
 1473         while (!root_mount_complete) {
 1474                 msleep(&root_mount_complete, &mountlist_mtx, PZERO, "rootwait",
 1475                     hz);
 1476         }
 1477         mtx_unlock(&mountlist_mtx);
 1478 }
 1479 
 1480 static void
 1481 set_rootvnode()
 1482 {
 1483         struct proc *p;
 1484 
 1485         if (VFS_ROOT(TAILQ_FIRST(&mountlist), LK_EXCLUSIVE, &rootvnode))
 1486                 panic("Cannot find root vnode");
 1487 
 1488         VOP_UNLOCK(rootvnode, 0);
 1489 
 1490         p = curthread->td_proc;
 1491         FILEDESC_XLOCK(p->p_fd);
 1492 
 1493         if (p->p_fd->fd_cdir != NULL)
 1494                 vrele(p->p_fd->fd_cdir);
 1495         p->p_fd->fd_cdir = rootvnode;
 1496         VREF(rootvnode);
 1497 
 1498         if (p->p_fd->fd_rdir != NULL)
 1499                 vrele(p->p_fd->fd_rdir);
 1500         p->p_fd->fd_rdir = rootvnode;
 1501         VREF(rootvnode);
 1502 
 1503         FILEDESC_XUNLOCK(p->p_fd);
 1504 
 1505         EVENTHANDLER_INVOKE(mountroot);
 1506 }
 1507 
 1508 /*
 1509  * Mount /devfs as our root filesystem, but do not put it on the mountlist
 1510  * yet.  Create a /dev -> / symlink so that absolute pathnames will lookup.
 1511  */
 1512 
 1513 static void
 1514 devfs_first(void)
 1515 {
 1516         struct thread *td = curthread;
 1517         struct vfsoptlist *opts;
 1518         struct vfsconf *vfsp;
 1519         struct mount *mp = NULL;
 1520         int error;
 1521 
 1522         vfsp = vfs_byname("devfs");
 1523         KASSERT(vfsp != NULL, ("Could not find devfs by name"));
 1524         if (vfsp == NULL)
 1525                 return;
 1526 
 1527         mp = vfs_mount_alloc(NULLVP, vfsp, "/dev", td->td_ucred);
 1528 
 1529         error = VFS_MOUNT(mp);
 1530         KASSERT(error == 0, ("VFS_MOUNT(devfs) failed %d", error));
 1531         if (error)
 1532                 return;
 1533 
 1534         opts = malloc(sizeof(struct vfsoptlist), M_MOUNT, M_WAITOK);
 1535         TAILQ_INIT(opts);
 1536         mp->mnt_opt = opts;
 1537 
 1538         mtx_lock(&mountlist_mtx);
 1539         TAILQ_INSERT_HEAD(&mountlist, mp, mnt_list);
 1540         mtx_unlock(&mountlist_mtx);
 1541 
 1542         set_rootvnode();
 1543 
 1544         error = kern_symlink(td, "/", "dev", UIO_SYSSPACE);
 1545         if (error)
 1546                 printf("kern_symlink /dev -> / returns %d\n", error);
 1547 }
 1548 
 1549 /*
 1550  * Surgically move our devfs to be mounted on /dev.
 1551  */
 1552 
 1553 static void
 1554 devfs_fixup(struct thread *td)
 1555 {
 1556         struct nameidata nd;
 1557         int error;
 1558         struct vnode *vp, *dvp;
 1559         struct mount *mp;
 1560 
 1561         /* Remove our devfs mount from the mountlist and purge the cache */
 1562         mtx_lock(&mountlist_mtx);
 1563         mp = TAILQ_FIRST(&mountlist);
 1564         TAILQ_REMOVE(&mountlist, mp, mnt_list);
 1565         mtx_unlock(&mountlist_mtx);
 1566         cache_purgevfs(mp);
 1567 
 1568         VFS_ROOT(mp, LK_EXCLUSIVE, &dvp);
 1569         VI_LOCK(dvp);
 1570         dvp->v_iflag &= ~VI_MOUNT;
 1571         VI_UNLOCK(dvp);
 1572         dvp->v_mountedhere = NULL;
 1573 
 1574         /* Set up the real rootvnode, and purge the cache */
 1575         TAILQ_FIRST(&mountlist)->mnt_vnodecovered = NULL;
 1576         set_rootvnode();
 1577         cache_purgevfs(rootvnode->v_mount);
 1578 
 1579         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, "/dev", td);
 1580         error = namei(&nd);
 1581         if (error) {
 1582                 printf("Lookup of /dev for devfs, error: %d\n", error);
 1583                 return;
 1584         }
 1585         NDFREE(&nd, NDF_ONLY_PNBUF);
 1586         vp = nd.ni_vp;
 1587         if (vp->v_type != VDIR) {
 1588                 vput(vp);
 1589         }
 1590         error = vinvalbuf(vp, V_SAVE, 0, 0);
 1591         if (error) {
 1592                 vput(vp);
 1593         }
 1594         cache_purge(vp);
 1595         mp->mnt_vnodecovered = vp;
 1596         vp->v_mountedhere = mp;
 1597         mtx_lock(&mountlist_mtx);
 1598         TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
 1599         mtx_unlock(&mountlist_mtx);
 1600         VOP_UNLOCK(vp, 0);
 1601         vput(dvp);
 1602         vfs_unbusy(mp);
 1603 
 1604         /* Unlink the no longer needed /dev/dev -> / symlink */
 1605         kern_unlink(td, "/dev/dev", UIO_SYSSPACE);
 1606 }
 1607 
 1608 /*
 1609  * Report errors during filesystem mounting.
 1610  */
 1611 void
 1612 vfs_mount_error(struct mount *mp, const char *fmt, ...)
 1613 {
 1614         struct vfsoptlist *moptlist = mp->mnt_optnew;
 1615         va_list ap;
 1616         int error, len;
 1617         char *errmsg;
 1618 
 1619         error = vfs_getopt(moptlist, "errmsg", (void **)&errmsg, &len);
 1620         if (error || errmsg == NULL || len <= 0)
 1621                 return;
 1622 
 1623         va_start(ap, fmt);
 1624         vsnprintf(errmsg, (size_t)len, fmt, ap);
 1625         va_end(ap);
 1626 }
 1627 
 1628 void
 1629 vfs_opterror(struct vfsoptlist *opts, const char *fmt, ...)
 1630 {
 1631         va_list ap;
 1632         int error, len;
 1633         char *errmsg;
 1634 
 1635         error = vfs_getopt(opts, "errmsg", (void **)&errmsg, &len);
 1636         if (error || errmsg == NULL || len <= 0)
 1637                 return;
 1638 
 1639         va_start(ap, fmt);
 1640         vsnprintf(errmsg, (size_t)len, fmt, ap);
 1641         va_end(ap);
 1642 }
 1643 
 1644 /*
 1645  * Find and mount the root filesystem
 1646  */
 1647 void
 1648 vfs_mountroot(void)
 1649 {
 1650         char *cp, *cpt, *options, *tmpdev;
 1651         int error, i, asked = 0;
 1652 
 1653         options = NULL;
 1654 
 1655         root_mount_prepare();
 1656 
 1657         mount_zone = uma_zcreate("Mountpoints", sizeof(struct mount),
 1658             NULL, NULL, mount_init, mount_fini,
 1659             UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
 1660         devfs_first();
 1661 
 1662         /*
 1663          * We are booted with instructions to prompt for the root filesystem.
 1664          */
 1665         if (boothowto & RB_ASKNAME) {
 1666                 if (!vfs_mountroot_ask())
 1667                         goto mounted;
 1668                 asked = 1;
 1669         }
 1670 
 1671         options = getenv("vfs.root.mountfrom.options");
 1672 
 1673         /*
 1674          * The root filesystem information is compiled in, and we are
 1675          * booted with instructions to use it.
 1676          */
 1677         if (ctrootdevname != NULL && (boothowto & RB_DFLTROOT)) {
 1678                 if (!vfs_mountroot_try(ctrootdevname, options))
 1679                         goto mounted;
 1680                 ctrootdevname = NULL;
 1681         }
 1682 
 1683         /*
 1684          * We've been given the generic "use CDROM as root" flag.  This is
 1685          * necessary because one media may be used in many different
 1686          * devices, so we need to search for them.
 1687          */
 1688         if (boothowto & RB_CDROM) {
 1689                 for (i = 0; cdrom_rootdevnames[i] != NULL; i++) {
 1690                         if (!vfs_mountroot_try(cdrom_rootdevnames[i], options))
 1691                                 goto mounted;
 1692                 }
 1693         }
 1694 
 1695         /*
 1696          * Try to use the value read by the loader from /etc/fstab, or
 1697          * supplied via some other means.  This is the preferred
 1698          * mechanism.
 1699          */
 1700         cp = getenv("vfs.root.mountfrom");
 1701         if (cp != NULL) {
 1702                 cpt = cp;
 1703                 while ((tmpdev = strsep(&cpt, " \t")) != NULL) {
 1704                         error = vfs_mountroot_try(tmpdev, options);
 1705                         if (error == 0) {
 1706                                 freeenv(cp);
 1707                                 goto mounted;
 1708                         }
 1709                 }
 1710                 freeenv(cp);
 1711         }
 1712 
 1713         /*
 1714          * Try values that may have been computed by code during boot
 1715          */
 1716         if (!vfs_mountroot_try(rootdevnames[0], options))
 1717                 goto mounted;
 1718         if (!vfs_mountroot_try(rootdevnames[1], options))
 1719                 goto mounted;
 1720 
 1721         /*
 1722          * If we (still) have a compiled-in default, try it.
 1723          */
 1724         if (ctrootdevname != NULL)
 1725                 if (!vfs_mountroot_try(ctrootdevname, options))
 1726                         goto mounted;
 1727         /*
 1728          * Everything so far has failed, prompt on the console if we haven't
 1729          * already tried that.
 1730          */
 1731         if (!asked)
 1732                 if (!vfs_mountroot_ask())
 1733                         goto mounted;
 1734 
 1735         panic("Root mount failed, startup aborted.");
 1736 
 1737 mounted:
 1738         root_mount_done();
 1739         freeenv(options);
 1740 }
 1741 
 1742 static struct mntarg *
 1743 parse_mountroot_options(struct mntarg *ma, const char *options)
 1744 {
 1745         char *p;
 1746         char *name, *name_arg;
 1747         char *val, *val_arg;
 1748         char *opts;
 1749 
 1750         if (options == NULL || options[0] == '\0')
 1751                 return (ma);
 1752 
 1753         p = opts = strdup(options, M_MOUNT);
 1754         if (opts == NULL) {
 1755                 return (ma);
 1756         } 
 1757 
 1758         while((name = strsep(&p, ",")) != NULL) {
 1759                 if (name[0] == '\0')
 1760                         break;
 1761 
 1762                 val = strchr(name, '=');
 1763                 if (val != NULL) {
 1764                         *val = '\0';
 1765                         ++val;
 1766                 }
 1767                 if( strcmp(name, "rw") == 0 ||
 1768                     strcmp(name, "noro") == 0) {
 1769                         /*
 1770                          * The first time we mount the root file system,
 1771                          * we need to mount 'ro', so We need to ignore
 1772                          * 'rw' and 'noro' mount options.
 1773                          */
 1774                         continue;
 1775                 }
 1776                 name_arg = strdup(name, M_MOUNT);
 1777                 val_arg = NULL;
 1778                 if (val != NULL) 
 1779                         val_arg = strdup(val, M_MOUNT);
 1780 
 1781                 ma = mount_arg(ma, name_arg, val_arg,
 1782                     (val_arg != NULL ? -1 : 0));
 1783         }
 1784         free(opts, M_MOUNT);
 1785         return (ma);
 1786 }
 1787 
 1788 /*
 1789  * Mount (mountfrom) as the root filesystem.
 1790  */
 1791 static int
 1792 vfs_mountroot_try(const char *mountfrom, const char *options)
 1793 {
 1794         struct mount    *mp;
 1795         struct mntarg   *ma;
 1796         char            *vfsname, *path;
 1797         time_t          timebase;
 1798         int             error;
 1799         char            patt[32];
 1800         char            errmsg[255];
 1801 
 1802         vfsname = NULL;
 1803         path    = NULL;
 1804         mp      = NULL;
 1805         ma      = NULL;
 1806         error   = EINVAL;
 1807         bzero(errmsg, sizeof(errmsg));
 1808 
 1809         if (mountfrom == NULL)
 1810                 return (error);         /* don't complain */
 1811         printf("Trying to mount root from %s\n", mountfrom);
 1812 
 1813         /* parse vfs name and path */
 1814         vfsname = malloc(MFSNAMELEN, M_MOUNT, M_WAITOK);
 1815         path = malloc(MNAMELEN, M_MOUNT, M_WAITOK);
 1816         vfsname[0] = path[0] = 0;
 1817         sprintf(patt, "%%%d[a-z0-9]:%%%ds", MFSNAMELEN, MNAMELEN);
 1818         if (sscanf(mountfrom, patt, vfsname, path) < 1)
 1819                 goto out;
 1820 
 1821         if (path[0] == '\0')
 1822                 strcpy(path, ROOTNAME);
 1823 
 1824         ma = mount_arg(ma, "fstype", vfsname, -1);
 1825         ma = mount_arg(ma, "fspath", "/", -1);
 1826         ma = mount_arg(ma, "from", path, -1);
 1827         ma = mount_arg(ma, "errmsg", errmsg, sizeof(errmsg));
 1828         ma = mount_arg(ma, "ro", NULL, 0);
 1829         ma = parse_mountroot_options(ma, options);
 1830         error = kernel_mount(ma, MNT_ROOTFS);
 1831 
 1832         if (error == 0) {
 1833                 /*
 1834                  * We mount devfs prior to mounting the / FS, so the first
 1835                  * entry will typically be devfs.
 1836                  */
 1837                 mp = TAILQ_FIRST(&mountlist);
 1838                 KASSERT(mp != NULL, ("%s: mountlist is empty", __func__));
 1839 
 1840                 /*
 1841                  * Iterate over all currently mounted file systems and use
 1842                  * the time stamp found to check and/or initialize the RTC.
 1843                  * Typically devfs has no time stamp and the only other FS
 1844                  * is the actual / FS.
 1845                  * Call inittodr() only once and pass it the largest of the
 1846                  * timestamps we encounter.
 1847                  */
 1848                 timebase = 0;
 1849                 do {
 1850                         if (mp->mnt_time > timebase)
 1851                                 timebase = mp->mnt_time;
 1852                         mp = TAILQ_NEXT(mp, mnt_list);
 1853                 } while (mp != NULL);
 1854                 inittodr(timebase);
 1855 
 1856                 devfs_fixup(curthread);
 1857         }
 1858 
 1859         if (error != 0 ) {
 1860                 printf("ROOT MOUNT ERROR: %s\n", errmsg);
 1861                 printf("If you have invalid mount options, reboot, and ");
 1862                 printf("first try the following from\n");
 1863                 printf("the loader prompt:\n\n");
 1864                 printf("     set vfs.root.mountfrom.options=rw\n\n");
 1865                 printf("and then remove invalid mount options from ");
 1866                 printf("/etc/fstab.\n\n");
 1867         }
 1868 out:
 1869         free(path, M_MOUNT);
 1870         free(vfsname, M_MOUNT);
 1871         return (error);
 1872 }
 1873 
 1874 /*
 1875  * ---------------------------------------------------------------------
 1876  * Interactive root filesystem selection code.
 1877  */
 1878 
 1879 static int
 1880 vfs_mountroot_ask(void)
 1881 {
 1882         char name[128];
 1883         char *mountfrom;
 1884         char *options;
 1885 
 1886         for(;;) {
 1887                 printf("Loader variables:\n");
 1888                 printf("vfs.root.mountfrom=");
 1889                 mountfrom = getenv("vfs.root.mountfrom");
 1890                 if (mountfrom != NULL) {
 1891                         printf("%s", mountfrom);
 1892                 }
 1893                 printf("\n");
 1894                 printf("vfs.root.mountfrom.options=");
 1895                 options = getenv("vfs.root.mountfrom.options");
 1896                 if (options != NULL) {
 1897                         printf("%s", options);
 1898                 }
 1899                 printf("\n");
 1900                 freeenv(mountfrom);
 1901                 freeenv(options);
 1902                 printf("\nManual root filesystem specification:\n");
 1903                 printf("  <fstype>:<device>  Mount <device> using filesystem <fstype>\n");
 1904                 printf("                       eg. ufs:/dev/da0s1a\n");
 1905                 printf("                       eg. cd9660:/dev/acd0\n");
 1906                 printf("                       This is equivalent to: ");
 1907                 printf("mount -t cd9660 /dev/acd0 /\n"); 
 1908                 printf("\n");
 1909                 printf("  ?                  List valid disk boot devices\n");
 1910                 printf("  <empty line>       Abort manual input\n");
 1911                 printf("\nmountroot> ");
 1912                 gets(name, sizeof(name), 1);
 1913                 if (name[0] == '\0')
 1914                         return (1);
 1915                 if (name[0] == '?') {
 1916                         printf("\nList of GEOM managed disk devices:\n  ");
 1917                         g_dev_print();
 1918                         continue;
 1919                 }
 1920                 if (!vfs_mountroot_try(name, NULL))
 1921                         return (0);
 1922         }
 1923 }
 1924 
 1925 /*
 1926  * ---------------------------------------------------------------------
 1927  * Functions for querying mount options/arguments from filesystems.
 1928  */
 1929 
 1930 /*
 1931  * Check that no unknown options are given
 1932  */
 1933 int
 1934 vfs_filteropt(struct vfsoptlist *opts, const char **legal)
 1935 {
 1936         struct vfsopt *opt;
 1937         char errmsg[255];
 1938         const char **t, *p, *q;
 1939         int ret = 0;
 1940 
 1941         TAILQ_FOREACH(opt, opts, link) {
 1942                 p = opt->name;
 1943                 q = NULL;
 1944                 if (p[0] == 'n' && p[1] == 'o')
 1945                         q = p + 2;
 1946                 for(t = global_opts; *t != NULL; t++) {
 1947                         if (strcmp(*t, p) == 0)
 1948                                 break;
 1949                         if (q != NULL) {
 1950                                 if (strcmp(*t, q) == 0)
 1951                                         break;
 1952                         }
 1953                 }
 1954                 if (*t != NULL)
 1955                         continue;
 1956                 for(t = legal; *t != NULL; t++) {
 1957                         if (strcmp(*t, p) == 0)
 1958                                 break;
 1959                         if (q != NULL) {
 1960                                 if (strcmp(*t, q) == 0)
 1961                                         break;
 1962                         }
 1963                 }
 1964                 if (*t != NULL)
 1965                         continue;
 1966                 snprintf(errmsg, sizeof(errmsg),
 1967                     "mount option <%s> is unknown", p);
 1968                 printf("%s\n", errmsg);
 1969                 ret = EINVAL;
 1970         }
 1971         if (ret != 0) {
 1972                 TAILQ_FOREACH(opt, opts, link) {
 1973                         if (strcmp(opt->name, "errmsg") == 0) {
 1974                                 strncpy((char *)opt->value, errmsg, opt->len);
 1975                         }
 1976                 }
 1977         }
 1978         return (ret);
 1979 }
 1980 
 1981 /*
 1982  * Get a mount option by its name.
 1983  *
 1984  * Return 0 if the option was found, ENOENT otherwise.
 1985  * If len is non-NULL it will be filled with the length
 1986  * of the option. If buf is non-NULL, it will be filled
 1987  * with the address of the option.
 1988  */
 1989 int
 1990 vfs_getopt(opts, name, buf, len)
 1991         struct vfsoptlist *opts;
 1992         const char *name;
 1993         void **buf;
 1994         int *len;
 1995 {
 1996         struct vfsopt *opt;
 1997 
 1998         KASSERT(opts != NULL, ("vfs_getopt: caller passed 'opts' as NULL"));
 1999 
 2000         TAILQ_FOREACH(opt, opts, link) {
 2001                 if (strcmp(name, opt->name) == 0) {
 2002                         opt->seen = 1;
 2003                         if (len != NULL)
 2004                                 *len = opt->len;
 2005                         if (buf != NULL)
 2006                                 *buf = opt->value;
 2007                         return (0);
 2008                 }
 2009         }
 2010         return (ENOENT);
 2011 }
 2012 
 2013 int
 2014 vfs_getopt_pos(struct vfsoptlist *opts, const char *name)
 2015 {
 2016         struct vfsopt *opt;
 2017 
 2018         if (opts == NULL)
 2019                 return (-1);
 2020 
 2021         TAILQ_FOREACH(opt, opts, link) {
 2022                 if (strcmp(name, opt->name) == 0) {
 2023                         opt->seen = 1;
 2024                         return (opt->pos);
 2025                 }
 2026         }
 2027         return (-1);
 2028 }
 2029 
 2030 char *
 2031 vfs_getopts(struct vfsoptlist *opts, const char *name, int *error)
 2032 {
 2033         struct vfsopt *opt;
 2034 
 2035         *error = 0;
 2036         TAILQ_FOREACH(opt, opts, link) {
 2037                 if (strcmp(name, opt->name) != 0)
 2038                         continue;
 2039                 opt->seen = 1;
 2040                 if (opt->len == 0 ||
 2041                     ((char *)opt->value)[opt->len - 1] != '\0') {
 2042                         *error = EINVAL;
 2043                         return (NULL);
 2044                 }
 2045                 return (opt->value);
 2046         }
 2047         *error = ENOENT;
 2048         return (NULL);
 2049 }
 2050 
 2051 int
 2052 vfs_flagopt(struct vfsoptlist *opts, const char *name, u_int *w, u_int val)
 2053 {
 2054         struct vfsopt *opt;
 2055 
 2056         TAILQ_FOREACH(opt, opts, link) {
 2057                 if (strcmp(name, opt->name) == 0) {
 2058                         opt->seen = 1;
 2059                         if (w != NULL)
 2060                                 *w |= val;
 2061                         return (1);
 2062                 }
 2063         }
 2064         if (w != NULL)
 2065                 *w &= ~val;
 2066         return (0);
 2067 }
 2068 
 2069 int
 2070 vfs_scanopt(struct vfsoptlist *opts, const char *name, const char *fmt, ...)
 2071 {
 2072         va_list ap;
 2073         struct vfsopt *opt;
 2074         int ret;
 2075 
 2076         KASSERT(opts != NULL, ("vfs_getopt: caller passed 'opts' as NULL"));
 2077 
 2078         TAILQ_FOREACH(opt, opts, link) {
 2079                 if (strcmp(name, opt->name) != 0)
 2080                         continue;
 2081                 opt->seen = 1;
 2082                 if (opt->len == 0 || opt->value == NULL)
 2083                         return (0);
 2084                 if (((char *)opt->value)[opt->len - 1] != '\0')
 2085                         return (0);
 2086                 va_start(ap, fmt);
 2087                 ret = vsscanf(opt->value, fmt, ap);
 2088                 va_end(ap);
 2089                 return (ret);
 2090         }
 2091         return (0);
 2092 }
 2093 
 2094 int
 2095 vfs_setopt(struct vfsoptlist *opts, const char *name, void *value, int len)
 2096 {
 2097         struct vfsopt *opt;
 2098 
 2099         TAILQ_FOREACH(opt, opts, link) {
 2100                 if (strcmp(name, opt->name) != 0)
 2101                         continue;
 2102                 opt->seen = 1;
 2103                 if (opt->value == NULL)
 2104                         opt->len = len;
 2105                 else {
 2106                         if (opt->len != len)
 2107                                 return (EINVAL);
 2108                         bcopy(value, opt->value, len);
 2109                 }
 2110                 return (0);
 2111         }
 2112         return (ENOENT);
 2113 }
 2114 
 2115 int
 2116 vfs_setopt_part(struct vfsoptlist *opts, const char *name, void *value, int len)
 2117 {
 2118         struct vfsopt *opt;
 2119 
 2120         TAILQ_FOREACH(opt, opts, link) {
 2121                 if (strcmp(name, opt->name) != 0)
 2122                         continue;
 2123                 opt->seen = 1;
 2124                 if (opt->value == NULL)
 2125                         opt->len = len;
 2126                 else {
 2127                         if (opt->len < len)
 2128                                 return (EINVAL);
 2129                         opt->len = len;
 2130                         bcopy(value, opt->value, len);
 2131                 }
 2132                 return (0);
 2133         }
 2134         return (ENOENT);
 2135 }
 2136 
 2137 int
 2138 vfs_setopts(struct vfsoptlist *opts, const char *name, const char *value)
 2139 {
 2140         struct vfsopt *opt;
 2141 
 2142         TAILQ_FOREACH(opt, opts, link) {
 2143                 if (strcmp(name, opt->name) != 0)
 2144                         continue;
 2145                 opt->seen = 1;
 2146                 if (opt->value == NULL)
 2147                         opt->len = strlen(value) + 1;
 2148                 else if (strlcpy(opt->value, value, opt->len) >= opt->len)
 2149                         return (EINVAL);
 2150                 return (0);
 2151         }
 2152         return (ENOENT);
 2153 }
 2154 
 2155 /*
 2156  * Find and copy a mount option.
 2157  *
 2158  * The size of the buffer has to be specified
 2159  * in len, if it is not the same length as the
 2160  * mount option, EINVAL is returned.
 2161  * Returns ENOENT if the option is not found.
 2162  */
 2163 int
 2164 vfs_copyopt(opts, name, dest, len)
 2165         struct vfsoptlist *opts;
 2166         const char *name;
 2167         void *dest;
 2168         int len;
 2169 {
 2170         struct vfsopt *opt;
 2171 
 2172         KASSERT(opts != NULL, ("vfs_copyopt: caller passed 'opts' as NULL"));
 2173 
 2174         TAILQ_FOREACH(opt, opts, link) {
 2175                 if (strcmp(name, opt->name) == 0) {
 2176                         opt->seen = 1;
 2177                         if (len != opt->len)
 2178                                 return (EINVAL);
 2179                         bcopy(opt->value, dest, opt->len);
 2180                         return (0);
 2181                 }
 2182         }
 2183         return (ENOENT);
 2184 }
 2185 
 2186 /*
 2187  * This is a helper function for filesystems to traverse their
 2188  * vnodes.  See MNT_VNODE_FOREACH() in sys/mount.h
 2189  */
 2190 
 2191 struct vnode *
 2192 __mnt_vnode_next(struct vnode **mvp, struct mount *mp)
 2193 {
 2194         struct vnode *vp;
 2195 
 2196         mtx_assert(MNT_MTX(mp), MA_OWNED);
 2197 
 2198         KASSERT((*mvp)->v_mount == mp, ("marker vnode mount list mismatch"));
 2199         if ((*mvp)->v_yield++ == 500) {
 2200                 MNT_IUNLOCK(mp);
 2201                 (*mvp)->v_yield = 0;
 2202                 uio_yield();
 2203                 MNT_ILOCK(mp);
 2204         }
 2205         vp = TAILQ_NEXT(*mvp, v_nmntvnodes);
 2206         while (vp != NULL && vp->v_type == VMARKER)
 2207                 vp = TAILQ_NEXT(vp, v_nmntvnodes);
 2208 
 2209         /* Check if we are done */
 2210         if (vp == NULL) {
 2211                 __mnt_vnode_markerfree(mvp, mp);
 2212                 return (NULL);
 2213         }
 2214         TAILQ_REMOVE(&mp->mnt_nvnodelist, *mvp, v_nmntvnodes);
 2215         TAILQ_INSERT_AFTER(&mp->mnt_nvnodelist, vp, *mvp, v_nmntvnodes);
 2216         return (vp);
 2217 }
 2218 
 2219 struct vnode *
 2220 __mnt_vnode_first(struct vnode **mvp, struct mount *mp)
 2221 {
 2222         struct vnode *vp;
 2223 
 2224         mtx_assert(MNT_MTX(mp), MA_OWNED);
 2225 
 2226         vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
 2227         while (vp != NULL && vp->v_type == VMARKER)
 2228                 vp = TAILQ_NEXT(vp, v_nmntvnodes);
 2229 
 2230         /* Check if we are done */
 2231         if (vp == NULL) {
 2232                 *mvp = NULL;
 2233                 return (NULL);
 2234         }
 2235         MNT_REF(mp);
 2236         MNT_IUNLOCK(mp);
 2237         *mvp = (struct vnode *) malloc(sizeof(struct vnode),
 2238                                        M_VNODE_MARKER,
 2239                                        M_WAITOK | M_ZERO);
 2240         MNT_ILOCK(mp);
 2241         (*mvp)->v_type = VMARKER;
 2242 
 2243         vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
 2244         while (vp != NULL && vp->v_type == VMARKER)
 2245                 vp = TAILQ_NEXT(vp, v_nmntvnodes);
 2246 
 2247         /* Check if we are done */
 2248         if (vp == NULL) {
 2249                 MNT_IUNLOCK(mp);
 2250                 free(*mvp, M_VNODE_MARKER);
 2251                 MNT_ILOCK(mp);
 2252                 *mvp = NULL;
 2253                 MNT_REL(mp);
 2254                 return (NULL);
 2255         }
 2256         (*mvp)->v_mount = mp;
 2257         TAILQ_INSERT_AFTER(&mp->mnt_nvnodelist, vp, *mvp, v_nmntvnodes);
 2258         return (vp);
 2259 }
 2260 
 2261 
 2262 void
 2263 __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp)
 2264 {
 2265 
 2266         if (*mvp == NULL)
 2267                 return;
 2268 
 2269         mtx_assert(MNT_MTX(mp), MA_OWNED);
 2270 
 2271         KASSERT((*mvp)->v_mount == mp, ("marker vnode mount list mismatch"));
 2272         TAILQ_REMOVE(&mp->mnt_nvnodelist, *mvp, v_nmntvnodes);
 2273         MNT_IUNLOCK(mp);
 2274         free(*mvp, M_VNODE_MARKER);
 2275         MNT_ILOCK(mp);
 2276         *mvp = NULL;
 2277         MNT_REL(mp);
 2278 }
 2279 
 2280 
 2281 int
 2282 __vfs_statfs(struct mount *mp, struct statfs *sbp)
 2283 {
 2284         int error;
 2285 
 2286         error = mp->mnt_op->vfs_statfs(mp, &mp->mnt_stat);
 2287         if (sbp != &mp->mnt_stat)
 2288                 *sbp = mp->mnt_stat;
 2289         return (error);
 2290 }
 2291 
 2292 void
 2293 vfs_mountedfrom(struct mount *mp, const char *from)
 2294 {
 2295 
 2296         bzero(mp->mnt_stat.f_mntfromname, sizeof mp->mnt_stat.f_mntfromname);
 2297         strlcpy(mp->mnt_stat.f_mntfromname, from,
 2298             sizeof mp->mnt_stat.f_mntfromname);
 2299 }
 2300 
 2301 /*
 2302  * ---------------------------------------------------------------------
 2303  * This is the api for building mount args and mounting filesystems from
 2304  * inside the kernel.
 2305  *
 2306  * The API works by accumulation of individual args.  First error is
 2307  * latched.
 2308  *
 2309  * XXX: should be documented in new manpage kernel_mount(9)
 2310  */
 2311 
 2312 /* A memory allocation which must be freed when we are done */
 2313 struct mntaarg {
 2314         SLIST_ENTRY(mntaarg)    next;
 2315 };
 2316 
 2317 /* The header for the mount arguments */
 2318 struct mntarg {
 2319         struct iovec *v;
 2320         int len;
 2321         int error;
 2322         SLIST_HEAD(, mntaarg)   list;
 2323 };
 2324 
 2325 /*
 2326  * Add a boolean argument.
 2327  *
 2328  * flag is the boolean value.
 2329  * name must start with "no".
 2330  */
 2331 struct mntarg *
 2332 mount_argb(struct mntarg *ma, int flag, const char *name)
 2333 {
 2334 
 2335         KASSERT(name[0] == 'n' && name[1] == 'o',
 2336             ("mount_argb(...,%s): name must start with 'no'", name));
 2337 
 2338         return (mount_arg(ma, name + (flag ? 2 : 0), NULL, 0));
 2339 }
 2340 
 2341 /*
 2342  * Add an argument printf style
 2343  */
 2344 struct mntarg *
 2345 mount_argf(struct mntarg *ma, const char *name, const char *fmt, ...)
 2346 {
 2347         va_list ap;
 2348         struct mntaarg *maa;
 2349         struct sbuf *sb;
 2350         int len;
 2351 
 2352         if (ma == NULL) {
 2353                 ma = malloc(sizeof *ma, M_MOUNT, M_WAITOK | M_ZERO);
 2354                 SLIST_INIT(&ma->list);
 2355         }
 2356         if (ma->error)
 2357                 return (ma);
 2358 
 2359         ma->v = realloc(ma->v, sizeof *ma->v * (ma->len + 2),
 2360             M_MOUNT, M_WAITOK);
 2361         ma->v[ma->len].iov_base = (void *)(uintptr_t)name;
 2362         ma->v[ma->len].iov_len = strlen(name) + 1;
 2363         ma->len++;
 2364 
 2365         sb = sbuf_new_auto();
 2366         va_start(ap, fmt);
 2367         sbuf_vprintf(sb, fmt, ap);
 2368         va_end(ap);
 2369         sbuf_finish(sb);
 2370         len = sbuf_len(sb) + 1;
 2371         maa = malloc(sizeof *maa + len, M_MOUNT, M_WAITOK | M_ZERO);
 2372         SLIST_INSERT_HEAD(&ma->list, maa, next);
 2373         bcopy(sbuf_data(sb), maa + 1, len);
 2374         sbuf_delete(sb);
 2375 
 2376         ma->v[ma->len].iov_base = maa + 1;
 2377         ma->v[ma->len].iov_len = len;
 2378         ma->len++;
 2379 
 2380         return (ma);
 2381 }
 2382 
 2383 /*
 2384  * Add an argument which is a userland string.
 2385  */
 2386 struct mntarg *
 2387 mount_argsu(struct mntarg *ma, const char *name, const void *val, int len)
 2388 {
 2389         struct mntaarg *maa;
 2390         char *tbuf;
 2391 
 2392         if (val == NULL)
 2393                 return (ma);
 2394         if (ma == NULL) {
 2395                 ma = malloc(sizeof *ma, M_MOUNT, M_WAITOK | M_ZERO);
 2396                 SLIST_INIT(&ma->list);
 2397         }
 2398         if (ma->error)
 2399                 return (ma);
 2400         maa = malloc(sizeof *maa + len, M_MOUNT, M_WAITOK | M_ZERO);
 2401         SLIST_INSERT_HEAD(&ma->list, maa, next);
 2402         tbuf = (void *)(maa + 1);
 2403         ma->error = copyinstr(val, tbuf, len, NULL);
 2404         return (mount_arg(ma, name, tbuf, -1));
 2405 }
 2406 
 2407 /*
 2408  * Plain argument.
 2409  *
 2410  * If length is -1, treat value as a C string.
 2411  */
 2412 struct mntarg *
 2413 mount_arg(struct mntarg *ma, const char *name, const void *val, int len)
 2414 {
 2415 
 2416         if (ma == NULL) {
 2417                 ma = malloc(sizeof *ma, M_MOUNT, M_WAITOK | M_ZERO);
 2418                 SLIST_INIT(&ma->list);
 2419         }
 2420         if (ma->error)
 2421                 return (ma);
 2422 
 2423         ma->v = realloc(ma->v, sizeof *ma->v * (ma->len + 2),
 2424             M_MOUNT, M_WAITOK);
 2425         ma->v[ma->len].iov_base = (void *)(uintptr_t)name;
 2426         ma->v[ma->len].iov_len = strlen(name) + 1;
 2427         ma->len++;
 2428 
 2429         ma->v[ma->len].iov_base = (void *)(uintptr_t)val;
 2430         if (len < 0)
 2431                 ma->v[ma->len].iov_len = strlen(val) + 1;
 2432         else
 2433                 ma->v[ma->len].iov_len = len;
 2434         ma->len++;
 2435         return (ma);
 2436 }
 2437 
 2438 /*
 2439  * Free a mntarg structure
 2440  */
 2441 static void
 2442 free_mntarg(struct mntarg *ma)
 2443 {
 2444         struct mntaarg *maa;
 2445 
 2446         while (!SLIST_EMPTY(&ma->list)) {
 2447                 maa = SLIST_FIRST(&ma->list);
 2448                 SLIST_REMOVE_HEAD(&ma->list, next);
 2449                 free(maa, M_MOUNT);
 2450         }
 2451         free(ma->v, M_MOUNT);
 2452         free(ma, M_MOUNT);
 2453 }
 2454 
 2455 /*
 2456  * Mount a filesystem
 2457  */
 2458 int
 2459 kernel_mount(struct mntarg *ma, int flags)
 2460 {
 2461         struct uio auio;
 2462         int error;
 2463 
 2464         KASSERT(ma != NULL, ("kernel_mount NULL ma"));
 2465         KASSERT(ma->v != NULL, ("kernel_mount NULL ma->v"));
 2466         KASSERT(!(ma->len & 1), ("kernel_mount odd ma->len (%d)", ma->len));
 2467 
 2468         auio.uio_iov = ma->v;
 2469         auio.uio_iovcnt = ma->len;
 2470         auio.uio_segflg = UIO_SYSSPACE;
 2471 
 2472         error = ma->error;
 2473         if (!error)
 2474                 error = vfs_donmount(curthread, flags, &auio);
 2475         free_mntarg(ma);
 2476         return (error);
 2477 }
 2478 
 2479 /*
 2480  * A printflike function to mount a filesystem.
 2481  */
 2482 int
 2483 kernel_vmount(int flags, ...)
 2484 {
 2485         struct mntarg *ma = NULL;
 2486         va_list ap;
 2487         const char *cp;
 2488         const void *vp;
 2489         int error;
 2490 
 2491         va_start(ap, flags);
 2492         for (;;) {
 2493                 cp = va_arg(ap, const char *);
 2494                 if (cp == NULL)
 2495                         break;
 2496                 vp = va_arg(ap, const void *);
 2497                 ma = mount_arg(ma, cp, vp, (vp != NULL ? -1 : 0));
 2498         }
 2499         va_end(ap);
 2500 
 2501         error = kernel_mount(ma, flags);
 2502         return (error);
 2503 }
 2504 
 2505 void
 2506 vfs_oexport_conv(const struct oexport_args *oexp, struct export_args *exp)
 2507 {
 2508 
 2509         bcopy(oexp, exp, sizeof(*oexp));
 2510         exp->ex_numsecflavors = 0;
 2511 }

Cache object: 5bfaa3d490e435e71896797b6ce0673c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.