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


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

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

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

    1 /*-
    2  * Copyright (c) 1999-2004 Poul-Henning Kamp
    3  * Copyright (c) 1999 Michael Smith
    4  * Copyright (c) 1989, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  * (c) UNIX System Laboratories, Inc.
    7  * All or some portions of this file are derived from material licensed
    8  * to the University of California by American Telephone and Telegraph
    9  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   10  * the permission of UNIX System Laboratories, Inc.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 4. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __FBSDID("$FreeBSD: releng/8.0/sys/kern/vfs_mount.c 195995 2009-07-31 13:40:06Z jhb $");
   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                 VOP_UNLOCK(newdp, 0);
 1073                 VOP_UNLOCK(vp, 0);
 1074                 mountcheckdirs(vp, newdp);
 1075                 vrele(newdp);
 1076                 if ((mp->mnt_flag & MNT_RDONLY) == 0)
 1077                         error = vfs_allocate_syncvnode(mp);
 1078                 vfs_unbusy(mp);
 1079                 if (error)
 1080                         vrele(vp);
 1081         } else {
 1082                 VI_LOCK(vp);
 1083                 vp->v_iflag &= ~VI_MOUNT;
 1084                 VI_UNLOCK(vp);
 1085                 vfs_unbusy(mp);
 1086                 vfs_mount_destroy(mp);
 1087                 vput(vp);
 1088         }
 1089         return (error);
 1090 }
 1091 
 1092 /*
 1093  * Unmount a filesystem.
 1094  *
 1095  * Note: unmount takes a path to the vnode mounted on as argument, not
 1096  * special file (as before).
 1097  */
 1098 #ifndef _SYS_SYSPROTO_H_
 1099 struct unmount_args {
 1100         char    *path;
 1101         int     flags;
 1102 };
 1103 #endif
 1104 /* ARGSUSED */
 1105 int
 1106 unmount(td, uap)
 1107         struct thread *td;
 1108         register struct unmount_args /* {
 1109                 char *path;
 1110                 int flags;
 1111         } */ *uap;
 1112 {
 1113         struct mount *mp;
 1114         char *pathbuf;
 1115         int error, id0, id1;
 1116 
 1117         AUDIT_ARG_VALUE(uap->flags);
 1118         if (jailed(td->td_ucred) || usermount == 0) {
 1119                 error = priv_check(td, PRIV_VFS_UNMOUNT);
 1120                 if (error)
 1121                         return (error);
 1122         }
 1123 
 1124         pathbuf = malloc(MNAMELEN, M_TEMP, M_WAITOK);
 1125         error = copyinstr(uap->path, pathbuf, MNAMELEN, NULL);
 1126         if (error) {
 1127                 free(pathbuf, M_TEMP);
 1128                 return (error);
 1129         }
 1130         mtx_lock(&Giant);
 1131         if (uap->flags & MNT_BYFSID) {
 1132                 AUDIT_ARG_TEXT(pathbuf);
 1133                 /* Decode the filesystem ID. */
 1134                 if (sscanf(pathbuf, "FSID:%d:%d", &id0, &id1) != 2) {
 1135                         mtx_unlock(&Giant);
 1136                         free(pathbuf, M_TEMP);
 1137                         return (EINVAL);
 1138                 }
 1139 
 1140                 mtx_lock(&mountlist_mtx);
 1141                 TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) {
 1142                         if (mp->mnt_stat.f_fsid.val[0] == id0 &&
 1143                             mp->mnt_stat.f_fsid.val[1] == id1)
 1144                                 break;
 1145                 }
 1146                 mtx_unlock(&mountlist_mtx);
 1147         } else {
 1148                 AUDIT_ARG_UPATH1(td, pathbuf);
 1149                 mtx_lock(&mountlist_mtx);
 1150                 TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) {
 1151                         if (strcmp(mp->mnt_stat.f_mntonname, pathbuf) == 0)
 1152                                 break;
 1153                 }
 1154                 mtx_unlock(&mountlist_mtx);
 1155         }
 1156         free(pathbuf, M_TEMP);
 1157         if (mp == NULL) {
 1158                 /*
 1159                  * Previously we returned ENOENT for a nonexistent path and
 1160                  * EINVAL for a non-mountpoint.  We cannot tell these apart
 1161                  * now, so in the !MNT_BYFSID case return the more likely
 1162                  * EINVAL for compatibility.
 1163                  */
 1164                 mtx_unlock(&Giant);
 1165                 return ((uap->flags & MNT_BYFSID) ? ENOENT : EINVAL);
 1166         }
 1167 
 1168         /*
 1169          * Don't allow unmounting the root filesystem.
 1170          */
 1171         if (mp->mnt_flag & MNT_ROOTFS) {
 1172                 mtx_unlock(&Giant);
 1173                 return (EINVAL);
 1174         }
 1175         error = dounmount(mp, uap->flags, td);
 1176         mtx_unlock(&Giant);
 1177         return (error);
 1178 }
 1179 
 1180 /*
 1181  * Do the actual filesystem unmount.
 1182  */
 1183 int
 1184 dounmount(mp, flags, td)
 1185         struct mount *mp;
 1186         int flags;
 1187         struct thread *td;
 1188 {
 1189         struct vnode *coveredvp, *fsrootvp;
 1190         int error;
 1191         int async_flag;
 1192         int mnt_gen_r;
 1193 
 1194         mtx_assert(&Giant, MA_OWNED);
 1195 
 1196         if ((coveredvp = mp->mnt_vnodecovered) != NULL) {
 1197                 mnt_gen_r = mp->mnt_gen;
 1198                 VI_LOCK(coveredvp);
 1199                 vholdl(coveredvp);
 1200                 vn_lock(coveredvp, LK_EXCLUSIVE | LK_INTERLOCK | LK_RETRY);
 1201                 vdrop(coveredvp);
 1202                 /*
 1203                  * Check for mp being unmounted while waiting for the
 1204                  * covered vnode lock.
 1205                  */
 1206                 if (coveredvp->v_mountedhere != mp ||
 1207                     coveredvp->v_mountedhere->mnt_gen != mnt_gen_r) {
 1208                         VOP_UNLOCK(coveredvp, 0);
 1209                         return (EBUSY);
 1210                 }
 1211         }
 1212         /*
 1213          * Only privileged root, or (if MNT_USER is set) the user that did the
 1214          * original mount is permitted to unmount this filesystem.
 1215          */
 1216         error = vfs_suser(mp, td);
 1217         if (error) {
 1218                 if (coveredvp)
 1219                         VOP_UNLOCK(coveredvp, 0);
 1220                 return (error);
 1221         }
 1222 
 1223         MNT_ILOCK(mp);
 1224         if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
 1225                 MNT_IUNLOCK(mp);
 1226                 if (coveredvp)
 1227                         VOP_UNLOCK(coveredvp, 0);
 1228                 return (EBUSY);
 1229         }
 1230         mp->mnt_kern_flag |= MNTK_UNMOUNT | MNTK_NOINSMNTQ;
 1231         /* Allow filesystems to detect that a forced unmount is in progress. */
 1232         if (flags & MNT_FORCE)
 1233                 mp->mnt_kern_flag |= MNTK_UNMOUNTF;
 1234         error = 0;
 1235         if (mp->mnt_lockref) {
 1236                 if ((flags & MNT_FORCE) == 0) {
 1237                         mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_NOINSMNTQ |
 1238                             MNTK_UNMOUNTF);
 1239                         if (mp->mnt_kern_flag & MNTK_MWAIT) {
 1240                                 mp->mnt_kern_flag &= ~MNTK_MWAIT;
 1241                                 wakeup(mp);
 1242                         }
 1243                         MNT_IUNLOCK(mp);
 1244                         if (coveredvp)
 1245                                 VOP_UNLOCK(coveredvp, 0);
 1246                         return (EBUSY);
 1247                 }
 1248                 mp->mnt_kern_flag |= MNTK_DRAINING;
 1249                 error = msleep(&mp->mnt_lockref, MNT_MTX(mp), PVFS,
 1250                     "mount drain", 0);
 1251         }
 1252         MNT_IUNLOCK(mp);
 1253         KASSERT(mp->mnt_lockref == 0,
 1254             ("%s: invalid lock refcount in the drain path @ %s:%d",
 1255             __func__, __FILE__, __LINE__));
 1256         KASSERT(error == 0,
 1257             ("%s: invalid return value for msleep in the drain path @ %s:%d",
 1258             __func__, __FILE__, __LINE__));
 1259         vn_start_write(NULL, &mp, V_WAIT);
 1260 
 1261         if (mp->mnt_flag & MNT_EXPUBLIC)
 1262                 vfs_setpublicfs(NULL, NULL, NULL);
 1263 
 1264         vfs_msync(mp, MNT_WAIT);
 1265         MNT_ILOCK(mp);
 1266         async_flag = mp->mnt_flag & MNT_ASYNC;
 1267         mp->mnt_flag &= ~MNT_ASYNC;
 1268         mp->mnt_kern_flag &= ~MNTK_ASYNC;
 1269         MNT_IUNLOCK(mp);
 1270         cache_purgevfs(mp);     /* remove cache entries for this file sys */
 1271         if (mp->mnt_syncer != NULL)
 1272                 vrele(mp->mnt_syncer);
 1273         /*
 1274          * For forced unmounts, move process cdir/rdir refs on the fs root
 1275          * vnode to the covered vnode.  For non-forced unmounts we want
 1276          * such references to cause an EBUSY error.
 1277          */
 1278         if ((flags & MNT_FORCE) &&
 1279             VFS_ROOT(mp, LK_EXCLUSIVE, &fsrootvp) == 0) {
 1280                 if (mp->mnt_vnodecovered != NULL)
 1281                         mountcheckdirs(fsrootvp, mp->mnt_vnodecovered);
 1282                 if (fsrootvp == rootvnode) {
 1283                         vrele(rootvnode);
 1284                         rootvnode = NULL;
 1285                 }
 1286                 vput(fsrootvp);
 1287         }
 1288         if (((mp->mnt_flag & MNT_RDONLY) ||
 1289              (error = VFS_SYNC(mp, MNT_WAIT)) == 0) || (flags & MNT_FORCE) != 0)
 1290                 error = VFS_UNMOUNT(mp, flags);
 1291         vn_finished_write(mp);
 1292         /*
 1293          * If we failed to flush the dirty blocks for this mount point,
 1294          * undo all the cdir/rdir and rootvnode changes we made above.
 1295          * Unless we failed to do so because the device is reporting that
 1296          * it doesn't exist anymore.
 1297          */
 1298         if (error && error != ENXIO) {
 1299                 if ((flags & MNT_FORCE) &&
 1300                     VFS_ROOT(mp, LK_EXCLUSIVE, &fsrootvp) == 0) {
 1301                         if (mp->mnt_vnodecovered != NULL)
 1302                                 mountcheckdirs(mp->mnt_vnodecovered, fsrootvp);
 1303                         if (rootvnode == NULL) {
 1304                                 rootvnode = fsrootvp;
 1305                                 vref(rootvnode);
 1306                         }
 1307                         vput(fsrootvp);
 1308                 }
 1309                 MNT_ILOCK(mp);
 1310                 mp->mnt_kern_flag &= ~MNTK_NOINSMNTQ;
 1311                 if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL) {
 1312                         MNT_IUNLOCK(mp);
 1313                         (void) vfs_allocate_syncvnode(mp);
 1314                         MNT_ILOCK(mp);
 1315                 }
 1316                 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
 1317                 mp->mnt_flag |= async_flag;
 1318                 if ((mp->mnt_flag & MNT_ASYNC) != 0 && mp->mnt_noasync == 0)
 1319                         mp->mnt_kern_flag |= MNTK_ASYNC;
 1320                 if (mp->mnt_kern_flag & MNTK_MWAIT) {
 1321                         mp->mnt_kern_flag &= ~MNTK_MWAIT;
 1322                         wakeup(mp);
 1323                 }
 1324                 MNT_IUNLOCK(mp);
 1325                 if (coveredvp)
 1326                         VOP_UNLOCK(coveredvp, 0);
 1327                 return (error);
 1328         }
 1329         mtx_lock(&mountlist_mtx);
 1330         TAILQ_REMOVE(&mountlist, mp, mnt_list);
 1331         mtx_unlock(&mountlist_mtx);
 1332         if (coveredvp != NULL) {
 1333                 coveredvp->v_mountedhere = NULL;
 1334                 vput(coveredvp);
 1335         }
 1336         vfs_event_signal(NULL, VQ_UNMOUNT, 0);
 1337         vfs_mount_destroy(mp);
 1338         return (0);
 1339 }
 1340 
 1341 /*
 1342  * ---------------------------------------------------------------------
 1343  * Mounting of root filesystem
 1344  *
 1345  */
 1346 
 1347 struct root_hold_token {
 1348         const char                      *who;
 1349         LIST_ENTRY(root_hold_token)     list;
 1350 };
 1351 
 1352 static LIST_HEAD(, root_hold_token)     root_holds =
 1353     LIST_HEAD_INITIALIZER(&root_holds);
 1354 
 1355 static int root_mount_complete;
 1356 
 1357 /*
 1358  * Hold root mount.
 1359  */
 1360 struct root_hold_token *
 1361 root_mount_hold(const char *identifier)
 1362 {
 1363         struct root_hold_token *h;
 1364 
 1365         if (root_mounted())
 1366                 return (NULL);
 1367 
 1368         h = malloc(sizeof *h, M_DEVBUF, M_ZERO | M_WAITOK);
 1369         h->who = identifier;
 1370         mtx_lock(&mountlist_mtx);
 1371         LIST_INSERT_HEAD(&root_holds, h, list);
 1372         mtx_unlock(&mountlist_mtx);
 1373         return (h);
 1374 }
 1375 
 1376 /*
 1377  * Release root mount.
 1378  */
 1379 void
 1380 root_mount_rel(struct root_hold_token *h)
 1381 {
 1382 
 1383         if (h == NULL)
 1384                 return;
 1385         mtx_lock(&mountlist_mtx);
 1386         LIST_REMOVE(h, list);
 1387         wakeup(&root_holds);
 1388         mtx_unlock(&mountlist_mtx);
 1389         free(h, M_DEVBUF);
 1390 }
 1391 
 1392 /*
 1393  * Wait for all subsystems to release root mount.
 1394  */
 1395 static void
 1396 root_mount_prepare(void)
 1397 {
 1398         struct root_hold_token *h;
 1399         struct timeval lastfail;
 1400         int curfail = 0;
 1401 
 1402         for (;;) {
 1403                 DROP_GIANT();
 1404                 g_waitidle();
 1405                 PICKUP_GIANT();
 1406                 mtx_lock(&mountlist_mtx);
 1407                 if (LIST_EMPTY(&root_holds)) {
 1408                         mtx_unlock(&mountlist_mtx);
 1409                         break;
 1410                 }
 1411                 if (ppsratecheck(&lastfail, &curfail, 1)) {
 1412                         printf("Root mount waiting for:");
 1413                         LIST_FOREACH(h, &root_holds, list)
 1414                                 printf(" %s", h->who);
 1415                         printf("\n");
 1416                 }
 1417                 msleep(&root_holds, &mountlist_mtx, PZERO | PDROP, "roothold",
 1418                     hz);
 1419         }
 1420 }
 1421 
 1422 /*
 1423  * Root was mounted, share the good news.
 1424  */
 1425 static void
 1426 root_mount_done(void)
 1427 {
 1428 
 1429         /* Keep prison0's root in sync with the global rootvnode. */
 1430         mtx_lock(&prison0.pr_mtx);
 1431         prison0.pr_root = rootvnode;
 1432         vref(prison0.pr_root);
 1433         mtx_unlock(&prison0.pr_mtx);
 1434         /*
 1435          * Use a mutex to prevent the wakeup being missed and waiting for
 1436          * an extra 1 second sleep.
 1437          */
 1438         mtx_lock(&mountlist_mtx);
 1439         root_mount_complete = 1;
 1440         wakeup(&root_mount_complete);
 1441         mtx_unlock(&mountlist_mtx);
 1442 }
 1443 
 1444 /*
 1445  * Return true if root is already mounted.
 1446  */
 1447 int
 1448 root_mounted(void)
 1449 {
 1450 
 1451         /* No mutex is acquired here because int stores are atomic. */
 1452         return (root_mount_complete);
 1453 }
 1454 
 1455 /*
 1456  * Wait until root is mounted.
 1457  */
 1458 void
 1459 root_mount_wait(void)
 1460 {
 1461 
 1462         /*
 1463          * Panic on an obvious deadlock - the function can't be called from
 1464          * a thread which is doing the whole SYSINIT stuff.
 1465          */
 1466         KASSERT(curthread->td_proc->p_pid != 0,
 1467             ("root_mount_wait: cannot be called from the swapper thread"));
 1468         mtx_lock(&mountlist_mtx);
 1469         while (!root_mount_complete) {
 1470                 msleep(&root_mount_complete, &mountlist_mtx, PZERO, "rootwait",
 1471                     hz);
 1472         }
 1473         mtx_unlock(&mountlist_mtx);
 1474 }
 1475 
 1476 static void
 1477 set_rootvnode()
 1478 {
 1479         struct proc *p;
 1480 
 1481         if (VFS_ROOT(TAILQ_FIRST(&mountlist), LK_EXCLUSIVE, &rootvnode))
 1482                 panic("Cannot find root vnode");
 1483 
 1484         VOP_UNLOCK(rootvnode, 0);
 1485 
 1486         p = curthread->td_proc;
 1487         FILEDESC_XLOCK(p->p_fd);
 1488 
 1489         if (p->p_fd->fd_cdir != NULL)
 1490                 vrele(p->p_fd->fd_cdir);
 1491         p->p_fd->fd_cdir = rootvnode;
 1492         VREF(rootvnode);
 1493 
 1494         if (p->p_fd->fd_rdir != NULL)
 1495                 vrele(p->p_fd->fd_rdir);
 1496         p->p_fd->fd_rdir = rootvnode;
 1497         VREF(rootvnode);
 1498 
 1499         FILEDESC_XUNLOCK(p->p_fd);
 1500 
 1501         EVENTHANDLER_INVOKE(mountroot);
 1502 }
 1503 
 1504 /*
 1505  * Mount /devfs as our root filesystem, but do not put it on the mountlist
 1506  * yet.  Create a /dev -> / symlink so that absolute pathnames will lookup.
 1507  */
 1508 
 1509 static void
 1510 devfs_first(void)
 1511 {
 1512         struct thread *td = curthread;
 1513         struct vfsoptlist *opts;
 1514         struct vfsconf *vfsp;
 1515         struct mount *mp = NULL;
 1516         int error;
 1517 
 1518         vfsp = vfs_byname("devfs");
 1519         KASSERT(vfsp != NULL, ("Could not find devfs by name"));
 1520         if (vfsp == NULL)
 1521                 return;
 1522 
 1523         mp = vfs_mount_alloc(NULLVP, vfsp, "/dev", td->td_ucred);
 1524 
 1525         error = VFS_MOUNT(mp);
 1526         KASSERT(error == 0, ("VFS_MOUNT(devfs) failed %d", error));
 1527         if (error)
 1528                 return;
 1529 
 1530         opts = malloc(sizeof(struct vfsoptlist), M_MOUNT, M_WAITOK);
 1531         TAILQ_INIT(opts);
 1532         mp->mnt_opt = opts;
 1533 
 1534         mtx_lock(&mountlist_mtx);
 1535         TAILQ_INSERT_HEAD(&mountlist, mp, mnt_list);
 1536         mtx_unlock(&mountlist_mtx);
 1537 
 1538         set_rootvnode();
 1539 
 1540         error = kern_symlink(td, "/", "dev", UIO_SYSSPACE);
 1541         if (error)
 1542                 printf("kern_symlink /dev -> / returns %d\n", error);
 1543 }
 1544 
 1545 /*
 1546  * Surgically move our devfs to be mounted on /dev.
 1547  */
 1548 
 1549 static void
 1550 devfs_fixup(struct thread *td)
 1551 {
 1552         struct nameidata nd;
 1553         int error;
 1554         struct vnode *vp, *dvp;
 1555         struct mount *mp;
 1556 
 1557         /* Remove our devfs mount from the mountlist and purge the cache */
 1558         mtx_lock(&mountlist_mtx);
 1559         mp = TAILQ_FIRST(&mountlist);
 1560         TAILQ_REMOVE(&mountlist, mp, mnt_list);
 1561         mtx_unlock(&mountlist_mtx);
 1562         cache_purgevfs(mp);
 1563 
 1564         VFS_ROOT(mp, LK_EXCLUSIVE, &dvp);
 1565         VI_LOCK(dvp);
 1566         dvp->v_iflag &= ~VI_MOUNT;
 1567         VI_UNLOCK(dvp);
 1568         dvp->v_mountedhere = NULL;
 1569 
 1570         /* Set up the real rootvnode, and purge the cache */
 1571         TAILQ_FIRST(&mountlist)->mnt_vnodecovered = NULL;
 1572         set_rootvnode();
 1573         cache_purgevfs(rootvnode->v_mount);
 1574 
 1575         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, "/dev", td);
 1576         error = namei(&nd);
 1577         if (error) {
 1578                 printf("Lookup of /dev for devfs, error: %d\n", error);
 1579                 return;
 1580         }
 1581         NDFREE(&nd, NDF_ONLY_PNBUF);
 1582         vp = nd.ni_vp;
 1583         if (vp->v_type != VDIR) {
 1584                 vput(vp);
 1585         }
 1586         error = vinvalbuf(vp, V_SAVE, 0, 0);
 1587         if (error) {
 1588                 vput(vp);
 1589         }
 1590         cache_purge(vp);
 1591         mp->mnt_vnodecovered = vp;
 1592         vp->v_mountedhere = mp;
 1593         mtx_lock(&mountlist_mtx);
 1594         TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
 1595         mtx_unlock(&mountlist_mtx);
 1596         VOP_UNLOCK(vp, 0);
 1597         vput(dvp);
 1598         vfs_unbusy(mp);
 1599 
 1600         /* Unlink the no longer needed /dev/dev -> / symlink */
 1601         kern_unlink(td, "/dev/dev", UIO_SYSSPACE);
 1602 }
 1603 
 1604 /*
 1605  * Report errors during filesystem mounting.
 1606  */
 1607 void
 1608 vfs_mount_error(struct mount *mp, const char *fmt, ...)
 1609 {
 1610         struct vfsoptlist *moptlist = mp->mnt_optnew;
 1611         va_list ap;
 1612         int error, len;
 1613         char *errmsg;
 1614 
 1615         error = vfs_getopt(moptlist, "errmsg", (void **)&errmsg, &len);
 1616         if (error || errmsg == NULL || len <= 0)
 1617                 return;
 1618 
 1619         va_start(ap, fmt);
 1620         vsnprintf(errmsg, (size_t)len, fmt, ap);
 1621         va_end(ap);
 1622 }
 1623 
 1624 void
 1625 vfs_opterror(struct vfsoptlist *opts, const char *fmt, ...)
 1626 {
 1627         va_list ap;
 1628         int error, len;
 1629         char *errmsg;
 1630 
 1631         error = vfs_getopt(opts, "errmsg", (void **)&errmsg, &len);
 1632         if (error || errmsg == NULL || len <= 0)
 1633                 return;
 1634 
 1635         va_start(ap, fmt);
 1636         vsnprintf(errmsg, (size_t)len, fmt, ap);
 1637         va_end(ap);
 1638 }
 1639 
 1640 /*
 1641  * Find and mount the root filesystem
 1642  */
 1643 void
 1644 vfs_mountroot(void)
 1645 {
 1646         char *cp, *options;
 1647         int error, i, asked = 0;
 1648 
 1649         options = NULL;
 1650 
 1651         root_mount_prepare();
 1652 
 1653         mount_zone = uma_zcreate("Mountpoints", sizeof(struct mount),
 1654             NULL, NULL, mount_init, mount_fini,
 1655             UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
 1656         devfs_first();
 1657 
 1658         /*
 1659          * We are booted with instructions to prompt for the root filesystem.
 1660          */
 1661         if (boothowto & RB_ASKNAME) {
 1662                 if (!vfs_mountroot_ask())
 1663                         goto mounted;
 1664                 asked = 1;
 1665         }
 1666 
 1667         options = getenv("vfs.root.mountfrom.options");
 1668 
 1669         /*
 1670          * The root filesystem information is compiled in, and we are
 1671          * booted with instructions to use it.
 1672          */
 1673         if (ctrootdevname != NULL && (boothowto & RB_DFLTROOT)) {
 1674                 if (!vfs_mountroot_try(ctrootdevname, options))
 1675                         goto mounted;
 1676                 ctrootdevname = NULL;
 1677         }
 1678 
 1679         /*
 1680          * We've been given the generic "use CDROM as root" flag.  This is
 1681          * necessary because one media may be used in many different
 1682          * devices, so we need to search for them.
 1683          */
 1684         if (boothowto & RB_CDROM) {
 1685                 for (i = 0; cdrom_rootdevnames[i] != NULL; i++) {
 1686                         if (!vfs_mountroot_try(cdrom_rootdevnames[i], options))
 1687                                 goto mounted;
 1688                 }
 1689         }
 1690 
 1691         /*
 1692          * Try to use the value read by the loader from /etc/fstab, or
 1693          * supplied via some other means.  This is the preferred
 1694          * mechanism.
 1695          */
 1696         cp = getenv("vfs.root.mountfrom");
 1697         if (cp != NULL) {
 1698                 error = vfs_mountroot_try(cp, options);
 1699                 freeenv(cp);
 1700                 if (!error)
 1701                         goto mounted;
 1702         }
 1703 
 1704         /*
 1705          * Try values that may have been computed by code during boot
 1706          */
 1707         if (!vfs_mountroot_try(rootdevnames[0], options))
 1708                 goto mounted;
 1709         if (!vfs_mountroot_try(rootdevnames[1], options))
 1710                 goto mounted;
 1711 
 1712         /*
 1713          * If we (still) have a compiled-in default, try it.
 1714          */
 1715         if (ctrootdevname != NULL)
 1716                 if (!vfs_mountroot_try(ctrootdevname, options))
 1717                         goto mounted;
 1718         /*
 1719          * Everything so far has failed, prompt on the console if we haven't
 1720          * already tried that.
 1721          */
 1722         if (!asked)
 1723                 if (!vfs_mountroot_ask())
 1724                         goto mounted;
 1725 
 1726         panic("Root mount failed, startup aborted.");
 1727 
 1728 mounted:
 1729         root_mount_done();
 1730         freeenv(options);
 1731 }
 1732 
 1733 static struct mntarg *
 1734 parse_mountroot_options(struct mntarg *ma, const char *options)
 1735 {
 1736         char *p;
 1737         char *name, *name_arg;
 1738         char *val, *val_arg;
 1739         char *opts;
 1740 
 1741         if (options == NULL || options[0] == '\0')
 1742                 return (ma);
 1743 
 1744         p = opts = strdup(options, M_MOUNT);
 1745         if (opts == NULL) {
 1746                 return (ma);
 1747         } 
 1748 
 1749         while((name = strsep(&p, ",")) != NULL) {
 1750                 if (name[0] == '\0')
 1751                         break;
 1752 
 1753                 val = strchr(name, '=');
 1754                 if (val != NULL) {
 1755                         *val = '\0';
 1756                         ++val;
 1757                 }
 1758                 if( strcmp(name, "rw") == 0 ||
 1759                     strcmp(name, "noro") == 0) {
 1760                         /*
 1761                          * The first time we mount the root file system,
 1762                          * we need to mount 'ro', so We need to ignore
 1763                          * 'rw' and 'noro' mount options.
 1764                          */
 1765                         continue;
 1766                 }
 1767                 name_arg = strdup(name, M_MOUNT);
 1768                 val_arg = NULL;
 1769                 if (val != NULL) 
 1770                         val_arg = strdup(val, M_MOUNT);
 1771 
 1772                 ma = mount_arg(ma, name_arg, val_arg,
 1773                     (val_arg != NULL ? -1 : 0));
 1774         }
 1775         free(opts, M_MOUNT);
 1776         return (ma);
 1777 }
 1778 
 1779 /*
 1780  * Mount (mountfrom) as the root filesystem.
 1781  */
 1782 static int
 1783 vfs_mountroot_try(const char *mountfrom, const char *options)
 1784 {
 1785         struct mount    *mp;
 1786         struct mntarg   *ma;
 1787         char            *vfsname, *path;
 1788         time_t          timebase;
 1789         int             error;
 1790         char            patt[32];
 1791         char            errmsg[255];
 1792 
 1793         vfsname = NULL;
 1794         path    = NULL;
 1795         mp      = NULL;
 1796         ma      = NULL;
 1797         error   = EINVAL;
 1798         bzero(errmsg, sizeof(errmsg));
 1799 
 1800         if (mountfrom == NULL)
 1801                 return (error);         /* don't complain */
 1802         printf("Trying to mount root from %s\n", mountfrom);
 1803 
 1804         /* parse vfs name and path */
 1805         vfsname = malloc(MFSNAMELEN, M_MOUNT, M_WAITOK);
 1806         path = malloc(MNAMELEN, M_MOUNT, M_WAITOK);
 1807         vfsname[0] = path[0] = 0;
 1808         sprintf(patt, "%%%d[a-z0-9]:%%%ds", MFSNAMELEN, MNAMELEN);
 1809         if (sscanf(mountfrom, patt, vfsname, path) < 1)
 1810                 goto out;
 1811 
 1812         if (path[0] == '\0')
 1813                 strcpy(path, ROOTNAME);
 1814 
 1815         ma = mount_arg(ma, "fstype", vfsname, -1);
 1816         ma = mount_arg(ma, "fspath", "/", -1);
 1817         ma = mount_arg(ma, "from", path, -1);
 1818         ma = mount_arg(ma, "errmsg", errmsg, sizeof(errmsg));
 1819         ma = mount_arg(ma, "ro", NULL, 0);
 1820         ma = parse_mountroot_options(ma, options);
 1821         error = kernel_mount(ma, MNT_ROOTFS);
 1822 
 1823         if (error == 0) {
 1824                 /*
 1825                  * We mount devfs prior to mounting the / FS, so the first
 1826                  * entry will typically be devfs.
 1827                  */
 1828                 mp = TAILQ_FIRST(&mountlist);
 1829                 KASSERT(mp != NULL, ("%s: mountlist is empty", __func__));
 1830 
 1831                 /*
 1832                  * Iterate over all currently mounted file systems and use
 1833                  * the time stamp found to check and/or initialize the RTC.
 1834                  * Typically devfs has no time stamp and the only other FS
 1835                  * is the actual / FS.
 1836                  * Call inittodr() only once and pass it the largest of the
 1837                  * timestamps we encounter.
 1838                  */
 1839                 timebase = 0;
 1840                 do {
 1841                         if (mp->mnt_time > timebase)
 1842                                 timebase = mp->mnt_time;
 1843                         mp = TAILQ_NEXT(mp, mnt_list);
 1844                 } while (mp != NULL);
 1845                 inittodr(timebase);
 1846 
 1847                 devfs_fixup(curthread);
 1848         }
 1849 
 1850         if (error != 0 ) {
 1851                 printf("ROOT MOUNT ERROR: %s\n", errmsg);
 1852                 printf("If you have invalid mount options, reboot, and ");
 1853                 printf("first try the following from\n");
 1854                 printf("the loader prompt:\n\n");
 1855                 printf("     set vfs.root.mountfrom.options=rw\n\n");
 1856                 printf("and then remove invalid mount options from ");
 1857                 printf("/etc/fstab.\n\n");
 1858         }
 1859 out:
 1860         free(path, M_MOUNT);
 1861         free(vfsname, M_MOUNT);
 1862         return (error);
 1863 }
 1864 
 1865 /*
 1866  * ---------------------------------------------------------------------
 1867  * Interactive root filesystem selection code.
 1868  */
 1869 
 1870 static int
 1871 vfs_mountroot_ask(void)
 1872 {
 1873         char name[128];
 1874         char *mountfrom;
 1875         char *options;
 1876 
 1877         for(;;) {
 1878                 printf("Loader variables:\n");
 1879                 printf("vfs.root.mountfrom=");
 1880                 mountfrom = getenv("vfs.root.mountfrom");
 1881                 if (mountfrom != NULL) {
 1882                         printf("%s", mountfrom);
 1883                 }
 1884                 printf("\n");
 1885                 printf("vfs.root.mountfrom.options=");
 1886                 options = getenv("vfs.root.mountfrom.options");
 1887                 if (options != NULL) {
 1888                         printf("%s", options);
 1889                 }
 1890                 printf("\n");
 1891                 freeenv(mountfrom);
 1892                 freeenv(options);
 1893                 printf("\nManual root filesystem specification:\n");
 1894                 printf("  <fstype>:<device>  Mount <device> using filesystem <fstype>\n");
 1895                 printf("                       eg. ufs:/dev/da0s1a\n");
 1896                 printf("                       eg. cd9660:/dev/acd0\n");
 1897                 printf("                       This is equivalent to: ");
 1898                 printf("mount -t cd9660 /dev/acd0 /\n"); 
 1899                 printf("\n");
 1900                 printf("  ?                  List valid disk boot devices\n");
 1901                 printf("  <empty line>       Abort manual input\n");
 1902                 printf("\nmountroot> ");
 1903                 gets(name, sizeof(name), 1);
 1904                 if (name[0] == '\0')
 1905                         return (1);
 1906                 if (name[0] == '?') {
 1907                         printf("\nList of GEOM managed disk devices:\n  ");
 1908                         g_dev_print();
 1909                         continue;
 1910                 }
 1911                 if (!vfs_mountroot_try(name, NULL))
 1912                         return (0);
 1913         }
 1914 }
 1915 
 1916 /*
 1917  * ---------------------------------------------------------------------
 1918  * Functions for querying mount options/arguments from filesystems.
 1919  */
 1920 
 1921 /*
 1922  * Check that no unknown options are given
 1923  */
 1924 int
 1925 vfs_filteropt(struct vfsoptlist *opts, const char **legal)
 1926 {
 1927         struct vfsopt *opt;
 1928         char errmsg[255];
 1929         const char **t, *p, *q;
 1930         int ret = 0;
 1931 
 1932         TAILQ_FOREACH(opt, opts, link) {
 1933                 p = opt->name;
 1934                 q = NULL;
 1935                 if (p[0] == 'n' && p[1] == 'o')
 1936                         q = p + 2;
 1937                 for(t = global_opts; *t != NULL; t++) {
 1938                         if (strcmp(*t, p) == 0)
 1939                                 break;
 1940                         if (q != NULL) {
 1941                                 if (strcmp(*t, q) == 0)
 1942                                         break;
 1943                         }
 1944                 }
 1945                 if (*t != NULL)
 1946                         continue;
 1947                 for(t = legal; *t != NULL; t++) {
 1948                         if (strcmp(*t, p) == 0)
 1949                                 break;
 1950                         if (q != NULL) {
 1951                                 if (strcmp(*t, q) == 0)
 1952                                         break;
 1953                         }
 1954                 }
 1955                 if (*t != NULL)
 1956                         continue;
 1957                 snprintf(errmsg, sizeof(errmsg),
 1958                     "mount option <%s> is unknown", p);
 1959                 printf("%s\n", errmsg);
 1960                 ret = EINVAL;
 1961         }
 1962         if (ret != 0) {
 1963                 TAILQ_FOREACH(opt, opts, link) {
 1964                         if (strcmp(opt->name, "errmsg") == 0) {
 1965                                 strncpy((char *)opt->value, errmsg, opt->len);
 1966                         }
 1967                 }
 1968         }
 1969         return (ret);
 1970 }
 1971 
 1972 /*
 1973  * Get a mount option by its name.
 1974  *
 1975  * Return 0 if the option was found, ENOENT otherwise.
 1976  * If len is non-NULL it will be filled with the length
 1977  * of the option. If buf is non-NULL, it will be filled
 1978  * with the address of the option.
 1979  */
 1980 int
 1981 vfs_getopt(opts, name, buf, len)
 1982         struct vfsoptlist *opts;
 1983         const char *name;
 1984         void **buf;
 1985         int *len;
 1986 {
 1987         struct vfsopt *opt;
 1988 
 1989         KASSERT(opts != NULL, ("vfs_getopt: caller passed 'opts' as NULL"));
 1990 
 1991         TAILQ_FOREACH(opt, opts, link) {
 1992                 if (strcmp(name, opt->name) == 0) {
 1993                         opt->seen = 1;
 1994                         if (len != NULL)
 1995                                 *len = opt->len;
 1996                         if (buf != NULL)
 1997                                 *buf = opt->value;
 1998                         return (0);
 1999                 }
 2000         }
 2001         return (ENOENT);
 2002 }
 2003 
 2004 int
 2005 vfs_getopt_pos(struct vfsoptlist *opts, const char *name)
 2006 {
 2007         struct vfsopt *opt;
 2008 
 2009         if (opts == NULL)
 2010                 return (-1);
 2011 
 2012         TAILQ_FOREACH(opt, opts, link) {
 2013                 if (strcmp(name, opt->name) == 0) {
 2014                         opt->seen = 1;
 2015                         return (opt->pos);
 2016                 }
 2017         }
 2018         return (-1);
 2019 }
 2020 
 2021 char *
 2022 vfs_getopts(struct vfsoptlist *opts, const char *name, int *error)
 2023 {
 2024         struct vfsopt *opt;
 2025 
 2026         *error = 0;
 2027         TAILQ_FOREACH(opt, opts, link) {
 2028                 if (strcmp(name, opt->name) != 0)
 2029                         continue;
 2030                 opt->seen = 1;
 2031                 if (opt->len == 0 ||
 2032                     ((char *)opt->value)[opt->len - 1] != '\0') {
 2033                         *error = EINVAL;
 2034                         return (NULL);
 2035                 }
 2036                 return (opt->value);
 2037         }
 2038         *error = ENOENT;
 2039         return (NULL);
 2040 }
 2041 
 2042 int
 2043 vfs_flagopt(struct vfsoptlist *opts, const char *name, u_int *w, u_int val)
 2044 {
 2045         struct vfsopt *opt;
 2046 
 2047         TAILQ_FOREACH(opt, opts, link) {
 2048                 if (strcmp(name, opt->name) == 0) {
 2049                         opt->seen = 1;
 2050                         if (w != NULL)
 2051                                 *w |= val;
 2052                         return (1);
 2053                 }
 2054         }
 2055         if (w != NULL)
 2056                 *w &= ~val;
 2057         return (0);
 2058 }
 2059 
 2060 int
 2061 vfs_scanopt(struct vfsoptlist *opts, const char *name, const char *fmt, ...)
 2062 {
 2063         va_list ap;
 2064         struct vfsopt *opt;
 2065         int ret;
 2066 
 2067         KASSERT(opts != NULL, ("vfs_getopt: caller passed 'opts' as NULL"));
 2068 
 2069         TAILQ_FOREACH(opt, opts, link) {
 2070                 if (strcmp(name, opt->name) != 0)
 2071                         continue;
 2072                 opt->seen = 1;
 2073                 if (opt->len == 0 || opt->value == NULL)
 2074                         return (0);
 2075                 if (((char *)opt->value)[opt->len - 1] != '\0')
 2076                         return (0);
 2077                 va_start(ap, fmt);
 2078                 ret = vsscanf(opt->value, fmt, ap);
 2079                 va_end(ap);
 2080                 return (ret);
 2081         }
 2082         return (0);
 2083 }
 2084 
 2085 int
 2086 vfs_setopt(struct vfsoptlist *opts, const char *name, void *value, int len)
 2087 {
 2088         struct vfsopt *opt;
 2089 
 2090         TAILQ_FOREACH(opt, opts, link) {
 2091                 if (strcmp(name, opt->name) != 0)
 2092                         continue;
 2093                 opt->seen = 1;
 2094                 if (opt->value == NULL)
 2095                         opt->len = len;
 2096                 else {
 2097                         if (opt->len != len)
 2098                                 return (EINVAL);
 2099                         bcopy(value, opt->value, len);
 2100                 }
 2101                 return (0);
 2102         }
 2103         return (ENOENT);
 2104 }
 2105 
 2106 int
 2107 vfs_setopt_part(struct vfsoptlist *opts, const char *name, void *value, int len)
 2108 {
 2109         struct vfsopt *opt;
 2110 
 2111         TAILQ_FOREACH(opt, opts, link) {
 2112                 if (strcmp(name, opt->name) != 0)
 2113                         continue;
 2114                 opt->seen = 1;
 2115                 if (opt->value == NULL)
 2116                         opt->len = len;
 2117                 else {
 2118                         if (opt->len < len)
 2119                                 return (EINVAL);
 2120                         opt->len = len;
 2121                         bcopy(value, opt->value, len);
 2122                 }
 2123                 return (0);
 2124         }
 2125         return (ENOENT);
 2126 }
 2127 
 2128 int
 2129 vfs_setopts(struct vfsoptlist *opts, const char *name, const char *value)
 2130 {
 2131         struct vfsopt *opt;
 2132 
 2133         TAILQ_FOREACH(opt, opts, link) {
 2134                 if (strcmp(name, opt->name) != 0)
 2135                         continue;
 2136                 opt->seen = 1;
 2137                 if (opt->value == NULL)
 2138                         opt->len = strlen(value) + 1;
 2139                 else if (strlcpy(opt->value, value, opt->len) >= opt->len)
 2140                         return (EINVAL);
 2141                 return (0);
 2142         }
 2143         return (ENOENT);
 2144 }
 2145 
 2146 /*
 2147  * Find and copy a mount option.
 2148  *
 2149  * The size of the buffer has to be specified
 2150  * in len, if it is not the same length as the
 2151  * mount option, EINVAL is returned.
 2152  * Returns ENOENT if the option is not found.
 2153  */
 2154 int
 2155 vfs_copyopt(opts, name, dest, len)
 2156         struct vfsoptlist *opts;
 2157         const char *name;
 2158         void *dest;
 2159         int len;
 2160 {
 2161         struct vfsopt *opt;
 2162 
 2163         KASSERT(opts != NULL, ("vfs_copyopt: caller passed 'opts' as NULL"));
 2164 
 2165         TAILQ_FOREACH(opt, opts, link) {
 2166                 if (strcmp(name, opt->name) == 0) {
 2167                         opt->seen = 1;
 2168                         if (len != opt->len)
 2169                                 return (EINVAL);
 2170                         bcopy(opt->value, dest, opt->len);
 2171                         return (0);
 2172                 }
 2173         }
 2174         return (ENOENT);
 2175 }
 2176 
 2177 /*
 2178  * This is a helper function for filesystems to traverse their
 2179  * vnodes.  See MNT_VNODE_FOREACH() in sys/mount.h
 2180  */
 2181 
 2182 struct vnode *
 2183 __mnt_vnode_next(struct vnode **mvp, struct mount *mp)
 2184 {
 2185         struct vnode *vp;
 2186 
 2187         mtx_assert(MNT_MTX(mp), MA_OWNED);
 2188 
 2189         KASSERT((*mvp)->v_mount == mp, ("marker vnode mount list mismatch"));
 2190         if ((*mvp)->v_yield++ == 500) {
 2191                 MNT_IUNLOCK(mp);
 2192                 (*mvp)->v_yield = 0;
 2193                 uio_yield();
 2194                 MNT_ILOCK(mp);
 2195         }
 2196         vp = TAILQ_NEXT(*mvp, v_nmntvnodes);
 2197         while (vp != NULL && vp->v_type == VMARKER)
 2198                 vp = TAILQ_NEXT(vp, v_nmntvnodes);
 2199 
 2200         /* Check if we are done */
 2201         if (vp == NULL) {
 2202                 __mnt_vnode_markerfree(mvp, mp);
 2203                 return (NULL);
 2204         }
 2205         TAILQ_REMOVE(&mp->mnt_nvnodelist, *mvp, v_nmntvnodes);
 2206         TAILQ_INSERT_AFTER(&mp->mnt_nvnodelist, vp, *mvp, v_nmntvnodes);
 2207         return (vp);
 2208 }
 2209 
 2210 struct vnode *
 2211 __mnt_vnode_first(struct vnode **mvp, struct mount *mp)
 2212 {
 2213         struct vnode *vp;
 2214 
 2215         mtx_assert(MNT_MTX(mp), MA_OWNED);
 2216 
 2217         vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
 2218         while (vp != NULL && vp->v_type == VMARKER)
 2219                 vp = TAILQ_NEXT(vp, v_nmntvnodes);
 2220 
 2221         /* Check if we are done */
 2222         if (vp == NULL) {
 2223                 *mvp = NULL;
 2224                 return (NULL);
 2225         }
 2226         MNT_REF(mp);
 2227         MNT_IUNLOCK(mp);
 2228         *mvp = (struct vnode *) malloc(sizeof(struct vnode),
 2229                                        M_VNODE_MARKER,
 2230                                        M_WAITOK | M_ZERO);
 2231         MNT_ILOCK(mp);
 2232         (*mvp)->v_type = VMARKER;
 2233 
 2234         vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
 2235         while (vp != NULL && vp->v_type == VMARKER)
 2236                 vp = TAILQ_NEXT(vp, v_nmntvnodes);
 2237 
 2238         /* Check if we are done */
 2239         if (vp == NULL) {
 2240                 MNT_IUNLOCK(mp);
 2241                 free(*mvp, M_VNODE_MARKER);
 2242                 MNT_ILOCK(mp);
 2243                 *mvp = NULL;
 2244                 MNT_REL(mp);
 2245                 return (NULL);
 2246         }
 2247         (*mvp)->v_mount = mp;
 2248         TAILQ_INSERT_AFTER(&mp->mnt_nvnodelist, vp, *mvp, v_nmntvnodes);
 2249         return (vp);
 2250 }
 2251 
 2252 
 2253 void
 2254 __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp)
 2255 {
 2256 
 2257         if (*mvp == NULL)
 2258                 return;
 2259 
 2260         mtx_assert(MNT_MTX(mp), MA_OWNED);
 2261 
 2262         KASSERT((*mvp)->v_mount == mp, ("marker vnode mount list mismatch"));
 2263         TAILQ_REMOVE(&mp->mnt_nvnodelist, *mvp, v_nmntvnodes);
 2264         MNT_IUNLOCK(mp);
 2265         free(*mvp, M_VNODE_MARKER);
 2266         MNT_ILOCK(mp);
 2267         *mvp = NULL;
 2268         MNT_REL(mp);
 2269 }
 2270 
 2271 
 2272 int
 2273 __vfs_statfs(struct mount *mp, struct statfs *sbp)
 2274 {
 2275         int error;
 2276 
 2277         error = mp->mnt_op->vfs_statfs(mp, &mp->mnt_stat);
 2278         if (sbp != &mp->mnt_stat)
 2279                 *sbp = mp->mnt_stat;
 2280         return (error);
 2281 }
 2282 
 2283 void
 2284 vfs_mountedfrom(struct mount *mp, const char *from)
 2285 {
 2286 
 2287         bzero(mp->mnt_stat.f_mntfromname, sizeof mp->mnt_stat.f_mntfromname);
 2288         strlcpy(mp->mnt_stat.f_mntfromname, from,
 2289             sizeof mp->mnt_stat.f_mntfromname);
 2290 }
 2291 
 2292 /*
 2293  * ---------------------------------------------------------------------
 2294  * This is the api for building mount args and mounting filesystems from
 2295  * inside the kernel.
 2296  *
 2297  * The API works by accumulation of individual args.  First error is
 2298  * latched.
 2299  *
 2300  * XXX: should be documented in new manpage kernel_mount(9)
 2301  */
 2302 
 2303 /* A memory allocation which must be freed when we are done */
 2304 struct mntaarg {
 2305         SLIST_ENTRY(mntaarg)    next;
 2306 };
 2307 
 2308 /* The header for the mount arguments */
 2309 struct mntarg {
 2310         struct iovec *v;
 2311         int len;
 2312         int error;
 2313         SLIST_HEAD(, mntaarg)   list;
 2314 };
 2315 
 2316 /*
 2317  * Add a boolean argument.
 2318  *
 2319  * flag is the boolean value.
 2320  * name must start with "no".
 2321  */
 2322 struct mntarg *
 2323 mount_argb(struct mntarg *ma, int flag, const char *name)
 2324 {
 2325 
 2326         KASSERT(name[0] == 'n' && name[1] == 'o',
 2327             ("mount_argb(...,%s): name must start with 'no'", name));
 2328 
 2329         return (mount_arg(ma, name + (flag ? 2 : 0), NULL, 0));
 2330 }
 2331 
 2332 /*
 2333  * Add an argument printf style
 2334  */
 2335 struct mntarg *
 2336 mount_argf(struct mntarg *ma, const char *name, const char *fmt, ...)
 2337 {
 2338         va_list ap;
 2339         struct mntaarg *maa;
 2340         struct sbuf *sb;
 2341         int len;
 2342 
 2343         if (ma == NULL) {
 2344                 ma = malloc(sizeof *ma, M_MOUNT, M_WAITOK | M_ZERO);
 2345                 SLIST_INIT(&ma->list);
 2346         }
 2347         if (ma->error)
 2348                 return (ma);
 2349 
 2350         ma->v = realloc(ma->v, sizeof *ma->v * (ma->len + 2),
 2351             M_MOUNT, M_WAITOK);
 2352         ma->v[ma->len].iov_base = (void *)(uintptr_t)name;
 2353         ma->v[ma->len].iov_len = strlen(name) + 1;
 2354         ma->len++;
 2355 
 2356         sb = sbuf_new_auto();
 2357         va_start(ap, fmt);
 2358         sbuf_vprintf(sb, fmt, ap);
 2359         va_end(ap);
 2360         sbuf_finish(sb);
 2361         len = sbuf_len(sb) + 1;
 2362         maa = malloc(sizeof *maa + len, M_MOUNT, M_WAITOK | M_ZERO);
 2363         SLIST_INSERT_HEAD(&ma->list, maa, next);
 2364         bcopy(sbuf_data(sb), maa + 1, len);
 2365         sbuf_delete(sb);
 2366 
 2367         ma->v[ma->len].iov_base = maa + 1;
 2368         ma->v[ma->len].iov_len = len;
 2369         ma->len++;
 2370 
 2371         return (ma);
 2372 }
 2373 
 2374 /*
 2375  * Add an argument which is a userland string.
 2376  */
 2377 struct mntarg *
 2378 mount_argsu(struct mntarg *ma, const char *name, const void *val, int len)
 2379 {
 2380         struct mntaarg *maa;
 2381         char *tbuf;
 2382 
 2383         if (val == NULL)
 2384                 return (ma);
 2385         if (ma == NULL) {
 2386                 ma = malloc(sizeof *ma, M_MOUNT, M_WAITOK | M_ZERO);
 2387                 SLIST_INIT(&ma->list);
 2388         }
 2389         if (ma->error)
 2390                 return (ma);
 2391         maa = malloc(sizeof *maa + len, M_MOUNT, M_WAITOK | M_ZERO);
 2392         SLIST_INSERT_HEAD(&ma->list, maa, next);
 2393         tbuf = (void *)(maa + 1);
 2394         ma->error = copyinstr(val, tbuf, len, NULL);
 2395         return (mount_arg(ma, name, tbuf, -1));
 2396 }
 2397 
 2398 /*
 2399  * Plain argument.
 2400  *
 2401  * If length is -1, treat value as a C string.
 2402  */
 2403 struct mntarg *
 2404 mount_arg(struct mntarg *ma, const char *name, const void *val, int len)
 2405 {
 2406 
 2407         if (ma == NULL) {
 2408                 ma = malloc(sizeof *ma, M_MOUNT, M_WAITOK | M_ZERO);
 2409                 SLIST_INIT(&ma->list);
 2410         }
 2411         if (ma->error)
 2412                 return (ma);
 2413 
 2414         ma->v = realloc(ma->v, sizeof *ma->v * (ma->len + 2),
 2415             M_MOUNT, M_WAITOK);
 2416         ma->v[ma->len].iov_base = (void *)(uintptr_t)name;
 2417         ma->v[ma->len].iov_len = strlen(name) + 1;
 2418         ma->len++;
 2419 
 2420         ma->v[ma->len].iov_base = (void *)(uintptr_t)val;
 2421         if (len < 0)
 2422                 ma->v[ma->len].iov_len = strlen(val) + 1;
 2423         else
 2424                 ma->v[ma->len].iov_len = len;
 2425         ma->len++;
 2426         return (ma);
 2427 }
 2428 
 2429 /*
 2430  * Free a mntarg structure
 2431  */
 2432 static void
 2433 free_mntarg(struct mntarg *ma)
 2434 {
 2435         struct mntaarg *maa;
 2436 
 2437         while (!SLIST_EMPTY(&ma->list)) {
 2438                 maa = SLIST_FIRST(&ma->list);
 2439                 SLIST_REMOVE_HEAD(&ma->list, next);
 2440                 free(maa, M_MOUNT);
 2441         }
 2442         free(ma->v, M_MOUNT);
 2443         free(ma, M_MOUNT);
 2444 }
 2445 
 2446 /*
 2447  * Mount a filesystem
 2448  */
 2449 int
 2450 kernel_mount(struct mntarg *ma, int flags)
 2451 {
 2452         struct uio auio;
 2453         int error;
 2454 
 2455         KASSERT(ma != NULL, ("kernel_mount NULL ma"));
 2456         KASSERT(ma->v != NULL, ("kernel_mount NULL ma->v"));
 2457         KASSERT(!(ma->len & 1), ("kernel_mount odd ma->len (%d)", ma->len));
 2458 
 2459         auio.uio_iov = ma->v;
 2460         auio.uio_iovcnt = ma->len;
 2461         auio.uio_segflg = UIO_SYSSPACE;
 2462 
 2463         error = ma->error;
 2464         if (!error)
 2465                 error = vfs_donmount(curthread, flags, &auio);
 2466         free_mntarg(ma);
 2467         return (error);
 2468 }
 2469 
 2470 /*
 2471  * A printflike function to mount a filesystem.
 2472  */
 2473 int
 2474 kernel_vmount(int flags, ...)
 2475 {
 2476         struct mntarg *ma = NULL;
 2477         va_list ap;
 2478         const char *cp;
 2479         const void *vp;
 2480         int error;
 2481 
 2482         va_start(ap, flags);
 2483         for (;;) {
 2484                 cp = va_arg(ap, const char *);
 2485                 if (cp == NULL)
 2486                         break;
 2487                 vp = va_arg(ap, const void *);
 2488                 ma = mount_arg(ma, cp, vp, (vp != NULL ? -1 : 0));
 2489         }
 2490         va_end(ap);
 2491 
 2492         error = kernel_mount(ma, flags);
 2493         return (error);
 2494 }

Cache object: d01bc8fbda17bbec9d4ec775ec4c16bc


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