[ 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  -  FREEBSD7  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  OPENSOLARIS  -  minix-3-1-1  -  TRUSTEDBSD-SEBSD  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

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

Cache object: e7814fc474028e18cda091d7a7258251


[ 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.