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/6.1/sys/kern/vfs_mount.c 158179 2006-04-30 16:44:43Z cvs2svn $");
   39 
   40 #include <sys/param.h>
   41 #include <sys/conf.h>
   42 #include <sys/jail.h>
   43 #include <sys/kernel.h>
   44 #include <sys/libkern.h>
   45 #include <sys/mac.h>
   46 #include <sys/malloc.h>
   47 #include <sys/mount.h>
   48 #include <sys/mutex.h>
   49 #include <sys/namei.h>
   50 #include <sys/proc.h>
   51 #include <sys/filedesc.h>
   52 #include <sys/reboot.h>
   53 #include <sys/syscallsubr.h>
   54 #include <sys/sysproto.h>
   55 #include <sys/sx.h>
   56 #include <sys/sysctl.h>
   57 #include <sys/sysent.h>
   58 #include <sys/systm.h>
   59 #include <sys/vnode.h>
   60 
   61 #include <geom/geom.h>
   62 
   63 #include <machine/stdarg.h>
   64 
   65 #include "opt_rootdevname.h"
   66 #include "opt_ddb.h"
   67 #include "opt_mac.h"
   68 
   69 #ifdef DDB
   70 #include <ddb/ddb.h>
   71 #endif
   72 
   73 #define ROOTNAME                "root_device"
   74 #define VFS_MOUNTARG_SIZE_MAX   (1024 * 64)
   75 
   76 static int      vfs_domount(struct thread *td, const char *fstype,
   77                     char *fspath, int fsflags, void *fsdata);
   78 static int      vfs_mount_alloc(struct vnode *dvp, struct vfsconf *vfsp,
   79                     const char *fspath, struct thread *td, struct mount **mpp);
   80 static int      vfs_mountroot_ask(void);
   81 static int      vfs_mountroot_try(const char *mountfrom);
   82 static int      vfs_donmount(struct thread *td, int fsflags,
   83                     struct uio *fsoptions);
   84 static void     free_mntarg(struct mntarg *ma);
   85 static void     vfs_mount_destroy(struct mount *, struct thread *);
   86 
   87 static int      usermount = 0;
   88 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0,
   89     "Unprivileged users may mount and unmount file systems");
   90 
   91 MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount structure");
   92 MALLOC_DEFINE(M_VNODE_MARKER, "vnodemarker", "vnode marker");
   93 
   94 /* List of mounted filesystems. */
   95 struct mntlist mountlist = TAILQ_HEAD_INITIALIZER(mountlist);
   96 
   97 /* For any iteration/modification of mountlist */
   98 struct mtx mountlist_mtx;
   99 MTX_SYSINIT(mountlist, &mountlist_mtx, "mountlist", MTX_DEF);
  100 
  101 TAILQ_HEAD(vfsoptlist, vfsopt);
  102 struct vfsopt {
  103         TAILQ_ENTRY(vfsopt) link;
  104         char    *name;
  105         void    *value;
  106         int     len;
  107 };
  108 
  109 /*
  110  * The vnode of the system's root (/ in the filesystem, without chroot
  111  * active.)
  112  */
  113 struct vnode    *rootvnode;
  114 
  115 /*
  116  * The root filesystem is detailed in the kernel environment variable
  117  * vfs.root.mountfrom, which is expected to be in the general format
  118  *
  119  * <vfsname>:[<path>]
  120  * vfsname   := the name of a VFS known to the kernel and capable
  121  *              of being mounted as root
  122  * path      := disk device name or other data used by the filesystem
  123  *              to locate its physical store
  124  */
  125 
  126 /*
  127  * Global opts, taken by all filesystems
  128  */
  129 static const char *global_opts[] = {
  130         "fstype",
  131         "fspath",
  132         "rdonly",
  133         "ro",
  134         "rw",
  135         "suid",
  136         "exec",
  137         NULL
  138 };
  139 
  140 /*
  141  * The root specifiers we will try if RB_CDROM is specified.
  142  */
  143 static char *cdrom_rootdevnames[] = {
  144         "cd9660:cd0",
  145         "cd9660:acd0",
  146         NULL
  147 };
  148 
  149 /* legacy find-root code */
  150 char            *rootdevnames[2] = {NULL, NULL};
  151 #ifndef ROOTDEVNAME
  152 #  define ROOTDEVNAME NULL
  153 #endif
  154 static const char       *ctrootdevname = ROOTDEVNAME;
  155 
  156 /*
  157  * ---------------------------------------------------------------------
  158  * Functions for building and sanitizing the mount options
  159  */
  160 
  161 /* Remove one mount option. */
  162 static void
  163 vfs_freeopt(struct vfsoptlist *opts, struct vfsopt *opt)
  164 {
  165 
  166         TAILQ_REMOVE(opts, opt, link);
  167         free(opt->name, M_MOUNT);
  168         if (opt->value != NULL)
  169                 free(opt->value, M_MOUNT);
  170 #ifdef INVARIANTS
  171         else if (opt->len != 0)
  172                 panic("%s: mount option with NULL value but length != 0",
  173                     __func__);
  174 #endif
  175         free(opt, M_MOUNT);
  176 }
  177 
  178 /* Release all resources related to the mount options. */
  179 static void
  180 vfs_freeopts(struct vfsoptlist *opts)
  181 {
  182         struct vfsopt *opt;
  183 
  184         while (!TAILQ_EMPTY(opts)) {
  185                 opt = TAILQ_FIRST(opts);
  186                 vfs_freeopt(opts, opt);
  187         }
  188         free(opts, M_MOUNT);
  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 
  198         /* "opt" vs. "opt" or "noopt" vs. "noopt" */
  199         if (strcmp(opt1, opt2) == 0)
  200                 return (1);
  201         /* "noopt" vs. "opt" */
  202         if (strncmp(opt1, "no", 2) == 0 && strcmp(opt1 + 2, opt2) == 0)
  203                 return (1);
  204         /* "opt" vs. "noopt" */
  205         if (strncmp(opt2, "no", 2) == 0 && strcmp(opt1, opt2 + 2) == 0)
  206                 return (1);
  207         return (0);
  208 }
  209 
  210 /*
  211  * If a mount option is specified several times,
  212  * (with or without the "no" prefix) only keep
  213  * the last occurence of it.
  214  */
  215 static void
  216 vfs_sanitizeopts(struct vfsoptlist *opts)
  217 {
  218         struct vfsopt *opt, *opt2, *tmp;
  219 
  220         TAILQ_FOREACH_REVERSE(opt, opts, vfsoptlist, link) {
  221                 opt2 = TAILQ_PREV(opt, vfsoptlist, link);
  222                 while (opt2 != NULL) {
  223                         if (vfs_equalopts(opt->name, opt2->name)) {
  224                                 tmp = TAILQ_PREV(opt2, vfsoptlist, link);
  225                                 vfs_freeopt(opts, opt2);
  226                                 opt2 = tmp;
  227                         } else {
  228                                 opt2 = TAILQ_PREV(opt2, vfsoptlist, link);
  229                         }
  230                 }
  231         }
  232 }
  233 
  234 /*
  235  * Build a linked list of mount options from a struct uio.
  236  */
  237 static int
  238 vfs_buildopts(struct uio *auio, struct vfsoptlist **options)
  239 {
  240         struct vfsoptlist *opts;
  241         struct vfsopt *opt;
  242         size_t memused;
  243         unsigned int i, iovcnt;
  244         int error, namelen, optlen;
  245 
  246         opts = malloc(sizeof(struct vfsoptlist), M_MOUNT, M_WAITOK);
  247         TAILQ_INIT(opts);
  248         memused = 0;
  249         iovcnt = auio->uio_iovcnt;
  250         for (i = 0; i < iovcnt; i += 2) {
  251                 opt = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK);
  252                 namelen = auio->uio_iov[i].iov_len;
  253                 optlen = auio->uio_iov[i + 1].iov_len;
  254                 opt->name = malloc(namelen, M_MOUNT, M_WAITOK);
  255                 opt->value = NULL;
  256                 opt->len = 0;
  257 
  258                 /*
  259                  * Do this early, so jumps to "bad" will free the current
  260                  * option.
  261                  */
  262                 TAILQ_INSERT_TAIL(opts, opt, link);
  263                 memused += sizeof(struct vfsopt) + optlen + namelen;
  264 
  265                 /*
  266                  * Avoid consuming too much memory, and attempts to overflow
  267                  * memused.
  268                  */
  269                 if (memused > VFS_MOUNTARG_SIZE_MAX ||
  270                     optlen > VFS_MOUNTARG_SIZE_MAX ||
  271                     namelen > VFS_MOUNTARG_SIZE_MAX) {
  272                         error = EINVAL;
  273                         goto bad;
  274                 }
  275 
  276                 if (auio->uio_segflg == UIO_SYSSPACE) {
  277                         bcopy(auio->uio_iov[i].iov_base, opt->name, namelen);
  278                 } else {
  279                         error = copyin(auio->uio_iov[i].iov_base, opt->name,
  280                             namelen);
  281                         if (error)
  282                                 goto bad;
  283                 }
  284                 /* Ensure names are null-terminated strings. */
  285                 if (opt->name[namelen - 1] != '\0') {
  286                         error = EINVAL;
  287                         goto bad;
  288                 }
  289                 if (optlen != 0) {
  290                         opt->len = optlen;
  291                         opt->value = malloc(optlen, M_MOUNT, M_WAITOK);
  292                         if (auio->uio_segflg == UIO_SYSSPACE) {
  293                                 bcopy(auio->uio_iov[i + 1].iov_base, opt->value,
  294                                     optlen);
  295                         } else {
  296                                 error = copyin(auio->uio_iov[i + 1].iov_base,
  297                                     opt->value, optlen);
  298                                 if (error)
  299                                         goto bad;
  300                         }
  301                 }
  302         }
  303         vfs_sanitizeopts(opts);
  304         *options = opts;
  305         return (0);
  306 bad:
  307         vfs_freeopts(opts);
  308         return (error);
  309 }
  310 
  311 /*
  312  * Merge the old mount options with the new ones passed
  313  * in the MNT_UPDATE case.
  314  */
  315 static void
  316 vfs_mergeopts(struct vfsoptlist *toopts, struct vfsoptlist *opts)
  317 {
  318         struct vfsopt *opt, *opt2, *new;
  319 
  320         TAILQ_FOREACH(opt, opts, link) {
  321                 /*
  322                  * Check that this option hasn't been redefined
  323                  * nor cancelled with a "no" mount option.
  324                  */
  325                 opt2 = TAILQ_FIRST(toopts);
  326                 while (opt2 != NULL) {
  327                         if (strcmp(opt2->name, opt->name) == 0)
  328                                 goto next;
  329                         if (strncmp(opt2->name, "no", 2) == 0 &&
  330                             strcmp(opt2->name + 2, opt->name) == 0) {
  331                                 vfs_freeopt(toopts, opt2);
  332                                 goto next;
  333                         }
  334                         opt2 = TAILQ_NEXT(opt2, link);
  335                 }
  336                 /* We want this option, duplicate it. */
  337                 new = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK);
  338                 new->name = malloc(strlen(opt->name) + 1, M_MOUNT, M_WAITOK);
  339                 strcpy(new->name, opt->name);
  340                 if (opt->len != 0) {
  341                         new->value = malloc(opt->len, M_MOUNT, M_WAITOK);
  342                         bcopy(opt->value, new->value, opt->len);
  343                 } else {
  344                         new->value = NULL;
  345                 }
  346                 new->len = opt->len;
  347                 TAILQ_INSERT_TAIL(toopts, new, link);
  348 next:
  349                 continue;
  350         }
  351 }
  352 
  353 /*
  354  * ---------------------------------------------------------------------
  355  * Mount a filesystem
  356  */
  357 int
  358 nmount(td, uap)
  359         struct thread *td;
  360         struct nmount_args /* {
  361                 struct iovec *iovp;
  362                 unsigned int iovcnt;
  363                 int flags;
  364         } */ *uap;
  365 {
  366         struct uio *auio;
  367         struct iovec *iov;
  368         unsigned int i;
  369         int error;
  370         u_int iovcnt;
  371 
  372         /* Kick out MNT_ROOTFS early as it is legal internally */
  373         if (uap->flags & MNT_ROOTFS)
  374                 return (EINVAL);
  375 
  376         iovcnt = uap->iovcnt;
  377         /*
  378          * Check that we have an even number of iovec's
  379          * and that we have at least two options.
  380          */
  381         if ((iovcnt & 1) || (iovcnt < 4))
  382                 return (EINVAL);
  383 
  384         error = copyinuio(uap->iovp, iovcnt, &auio);
  385         if (error)
  386                 return (error);
  387         iov = auio->uio_iov;
  388         for (i = 0; i < iovcnt; i++) {
  389                 if (iov->iov_len > MMAXOPTIONLEN) {
  390                         free(auio, M_IOV);
  391                         return (EINVAL);
  392                 }
  393                 iov++;
  394         }
  395         error = vfs_donmount(td, uap->flags, auio);
  396         free(auio, M_IOV);
  397         return (error);
  398 }
  399 
  400 /*
  401  * ---------------------------------------------------------------------
  402  * Various utility functions
  403  */
  404 
  405 void
  406 vfs_ref(struct mount *mp)
  407 {
  408 
  409         MNT_ILOCK(mp);
  410         MNT_REF(mp);
  411         MNT_IUNLOCK(mp);
  412 }
  413 
  414 void
  415 vfs_rel(struct mount *mp)
  416 {
  417 
  418         MNT_ILOCK(mp);
  419         MNT_REL(mp);
  420         MNT_IUNLOCK(mp);
  421 }
  422 
  423 /*
  424  * Allocate and initialize the mount point struct.
  425  */
  426 static int
  427 vfs_mount_alloc(struct vnode *vp, struct vfsconf *vfsp,
  428     const char *fspath, struct thread *td, struct mount **mpp)
  429 {
  430         struct mount *mp;
  431 
  432         mp = malloc(sizeof(struct mount), M_MOUNT, M_WAITOK | M_ZERO);
  433         TAILQ_INIT(&mp->mnt_nvnodelist);
  434         mp->mnt_nvnodelistsize = 0;
  435         mtx_init(&mp->mnt_mtx, "struct mount mtx", NULL, MTX_DEF);
  436         lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0);
  437         (void) vfs_busy(mp, LK_NOWAIT, 0, td);
  438         mp->mnt_ref = 0;
  439         mp->mnt_op = vfsp->vfc_vfsops;
  440         mp->mnt_vfc = vfsp;
  441         vfsp->vfc_refcount++;   /* XXX Unlocked */
  442         mp->mnt_stat.f_type = vfsp->vfc_typenum;
  443         mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
  444         strlcpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
  445         mp->mnt_vnodecovered = vp;
  446         mp->mnt_cred = crdup(td->td_ucred);
  447         mp->mnt_stat.f_owner = td->td_ucred->cr_uid;
  448         strlcpy(mp->mnt_stat.f_mntonname, fspath, MNAMELEN);
  449         mp->mnt_iosize_max = DFLTPHYS;
  450 #ifdef MAC
  451         mac_init_mount(mp);
  452         mac_create_mount(td->td_ucred, mp);
  453 #endif
  454         arc4rand(&mp->mnt_hashseed, sizeof mp->mnt_hashseed, 0);
  455         *mpp = mp;
  456         return (0);
  457 }
  458 
  459 /*
  460  * Destroy the mount struct previously allocated by vfs_mount_alloc().
  461  */
  462 static void
  463 vfs_mount_destroy(struct mount *mp, struct thread *td)
  464 {
  465         int i;
  466 
  467         vfs_unbusy(mp, td);
  468         MNT_ILOCK(mp);
  469         for (i = 0; mp->mnt_ref && i < 3; i++)
  470                 msleep(mp, MNT_MTX(mp), PVFS, "mntref", hz);
  471         /*
  472          * This will always cause a 3 second delay in rebooting due to
  473          * refs on the root mountpoint that never go away.  Most of these
  474          * are held by init which never exits.
  475          */
  476         if (i == 3 && (!rebooting || bootverbose))
  477                 printf("Mount point %s had %d dangling refs\n",
  478                     mp->mnt_stat.f_mntonname, mp->mnt_ref);
  479         if (mp->mnt_holdcnt != 0) {
  480                 printf("Waiting for mount point to be unheld\n");
  481                 while (mp->mnt_holdcnt != 0) {
  482                         mp->mnt_holdcntwaiters++;
  483                         msleep(&mp->mnt_holdcnt, MNT_MTX(mp),
  484                                PZERO, "mntdestroy", 0);
  485                         mp->mnt_holdcntwaiters--;
  486                 }
  487                 printf("mount point unheld\n");
  488         }
  489         if (mp->mnt_writeopcount > 0) {
  490                 printf("Waiting for mount point write ops\n");
  491                 while (mp->mnt_writeopcount > 0) {
  492                         mp->mnt_kern_flag |= MNTK_SUSPEND;
  493                         msleep(&mp->mnt_writeopcount,
  494                                MNT_MTX(mp),
  495                                PZERO, "mntdestroy2", 0);
  496                 }
  497                 printf("mount point write ops completed\n");
  498         }
  499         if (mp->mnt_secondary_writes > 0) {
  500                 printf("Waiting for mount point secondary write ops\n");
  501                 while (mp->mnt_secondary_writes > 0) {
  502                         mp->mnt_kern_flag |= MNTK_SUSPEND;
  503                         msleep(&mp->mnt_secondary_writes,
  504                                MNT_MTX(mp),
  505                                PZERO, "mntdestroy3", 0);
  506                 }
  507                 printf("mount point secondary write ops completed\n");
  508         }
  509         MNT_IUNLOCK(mp);
  510         mp->mnt_vfc->vfc_refcount--;
  511         if (!TAILQ_EMPTY(&mp->mnt_nvnodelist))
  512                 panic("unmount: dangling vnode");
  513         lockdestroy(&mp->mnt_lock);
  514         MNT_ILOCK(mp);
  515         if (mp->mnt_kern_flag & MNTK_MWAIT)
  516                 wakeup(mp);
  517         if (mp->mnt_writeopcount != 0)
  518                 panic("vfs_mount_destroy: nonzero writeopcount");
  519         if (mp->mnt_secondary_writes != 0)
  520                 panic("vfs_mount_destroy: nonzero secondary_writes");
  521         if (mp->mnt_nvnodelistsize != 0)
  522                 panic("vfs_mount_destroy: nonzero nvnodelistsize");
  523         mp->mnt_writeopcount = -1000;
  524         mp->mnt_nvnodelistsize = -1000;
  525         mp->mnt_secondary_writes = -1000;
  526         MNT_IUNLOCK(mp);
  527         mtx_destroy(&mp->mnt_mtx);
  528 #ifdef MAC
  529         mac_destroy_mount(mp);
  530 #endif
  531         if (mp->mnt_opt != NULL)
  532                 vfs_freeopts(mp->mnt_opt);
  533         crfree(mp->mnt_cred);
  534         free(mp, M_MOUNT);
  535 }
  536 
  537 static int
  538 vfs_donmount(struct thread *td, int fsflags, struct uio *fsoptions)
  539 {
  540         struct vfsoptlist *optlist;
  541         char *fstype, *fspath;
  542         int error, fstypelen, fspathlen;
  543 
  544         error = vfs_buildopts(fsoptions, &optlist);
  545         if (error)
  546                 return (error);
  547 
  548         /*
  549          * We need these two options before the others,
  550          * and they are mandatory for any filesystem.
  551          * Ensure they are NUL terminated as well.
  552          */
  553         fstypelen = 0;
  554         error = vfs_getopt(optlist, "fstype", (void **)&fstype, &fstypelen);
  555         if (error || fstype[fstypelen - 1] != '\0') {
  556                 error = EINVAL;
  557                 goto bail;
  558         }
  559         fspathlen = 0;
  560         error = vfs_getopt(optlist, "fspath", (void **)&fspath, &fspathlen);
  561         if (error || fspath[fspathlen - 1] != '\0') {
  562                 error = EINVAL;
  563                 goto bail;
  564         }
  565 
  566         /*
  567          * We need to see if we have the "update" option
  568          * before we call vfs_domount(), since vfs_domount() has special
  569          * logic based on MNT_UPDATE.  This is very important
  570          * when we want to update the root filesystem.
  571          */ 
  572         if (vfs_getopt(optlist, "update", NULL, NULL) == 0)
  573                 fsflags |= MNT_UPDATE;
  574 
  575         if (vfs_getopt(optlist, "async", NULL, NULL) == 0)
  576                 fsflags |= MNT_ASYNC;
  577 
  578         if (vfs_getopt(optlist, "force", NULL, NULL) == 0)
  579                 fsflags |= MNT_FORCE;
  580 
  581         if (vfs_getopt(optlist, "multilabel", NULL, NULL) == 0)
  582                 fsflags |= MNT_MULTILABEL;
  583 
  584         if (vfs_getopt(optlist, "noasync", NULL, NULL) == 0)
  585                 fsflags &= ~MNT_ASYNC;
  586 
  587         if (vfs_getopt(optlist, "noatime", NULL, NULL) == 0)
  588                 fsflags |= MNT_NOATIME;
  589 
  590         if (vfs_getopt(optlist, "noclusterr", NULL, NULL) == 0)
  591                 fsflags |= MNT_NOCLUSTERR;
  592 
  593         if (vfs_getopt(optlist, "noclusterw", NULL, NULL) == 0)
  594                 fsflags |= MNT_NOCLUSTERW;
  595 
  596         if (vfs_getopt(optlist, "noexec", NULL, NULL) == 0)
  597                 fsflags |= MNT_NOEXEC;
  598 
  599         if (vfs_getopt(optlist, "nosuid", NULL, NULL) == 0)
  600                 fsflags |= MNT_NOSUID;
  601 
  602         if (vfs_getopt(optlist, "nosymfollow", NULL, NULL) == 0)
  603                 fsflags |= MNT_NOSYMFOLLOW;
  604 
  605         if (vfs_getopt(optlist, "noro", NULL, NULL) == 0)
  606                 fsflags &= ~MNT_RDONLY;
  607 
  608         if (vfs_getopt(optlist, "ro", NULL, NULL) == 0)
  609                 fsflags |= MNT_RDONLY;
  610 
  611         if (vfs_getopt(optlist, "rdonly", NULL, NULL) == 0)
  612                 fsflags |= MNT_RDONLY;
  613 
  614         if (vfs_getopt(optlist, "rw", NULL, NULL) == 0)
  615                 fsflags &= ~MNT_RDONLY;
  616 
  617         if (vfs_getopt(optlist, "snapshot", NULL, NULL) == 0)
  618                 fsflags |= MNT_SNAPSHOT;
  619 
  620         if (vfs_getopt(optlist, "suiddir", NULL, NULL) == 0)
  621                 fsflags |= MNT_SUIDDIR;
  622 
  623         if (vfs_getopt(optlist, "sync", NULL, NULL) == 0)
  624                 fsflags |= MNT_SYNCHRONOUS;
  625 
  626         if (vfs_getopt(optlist, "union", NULL, NULL) == 0)
  627                 fsflags |= MNT_UNION;
  628 
  629         /*
  630          * Be ultra-paranoid about making sure the type and fspath
  631          * variables will fit in our mp buffers, including the
  632          * terminating NUL.
  633          */
  634         if (fstypelen >= MFSNAMELEN - 1 || fspathlen >= MNAMELEN - 1) {
  635                 error = ENAMETOOLONG;
  636                 goto bail;
  637         }
  638 
  639         mtx_lock(&Giant);
  640         error = vfs_domount(td, fstype, fspath, fsflags, optlist);
  641         mtx_unlock(&Giant);
  642 bail:
  643         if (error)
  644                 vfs_freeopts(optlist);
  645         return (error);
  646 }
  647 
  648 /*
  649  * ---------------------------------------------------------------------
  650  * Old mount API.
  651  */
  652 #ifndef _SYS_SYSPROTO_H_
  653 struct mount_args {
  654         char    *type;
  655         char    *path;
  656         int     flags;
  657         caddr_t data;
  658 };
  659 #endif
  660 /* ARGSUSED */
  661 int
  662 mount(td, uap)
  663         struct thread *td;
  664         struct mount_args /* {
  665                 char *type;
  666                 char *path;
  667                 int flags;
  668                 caddr_t data;
  669         } */ *uap;
  670 {
  671         char *fstype;
  672         struct vfsconf *vfsp = NULL;
  673         struct mntarg *ma = NULL;
  674         int error;
  675 
  676         /* Kick out MNT_ROOTFS early as it is legal internally */
  677         uap->flags &= ~MNT_ROOTFS;
  678 
  679         if (uap->data == NULL)
  680                 return (EINVAL);
  681 
  682         fstype = malloc(MFSNAMELEN, M_TEMP, M_WAITOK);
  683         error = copyinstr(uap->type, fstype, MFSNAMELEN, NULL);
  684         if (!error) {
  685                 mtx_lock(&Giant);       /* XXX ? */
  686                 vfsp = vfs_byname_kld(fstype, td, &error);
  687                 mtx_unlock(&Giant);
  688         }
  689         free(fstype, M_TEMP);
  690         if (error)
  691                 return (error);
  692         if (vfsp == NULL)
  693                 return (ENOENT);
  694         if (vfsp->vfc_vfsops->vfs_cmount == NULL)
  695                 return (EOPNOTSUPP);
  696 
  697         ma = mount_argsu(ma, "fstype", uap->type, MNAMELEN);
  698         ma = mount_argsu(ma, "fspath", uap->path, MNAMELEN);
  699         ma = mount_argb(ma, uap->flags & MNT_RDONLY, "noro");
  700         ma = mount_argb(ma, !(uap->flags & MNT_NOSUID), "nosuid");
  701         ma = mount_argb(ma, !(uap->flags & MNT_NOEXEC), "noexec");
  702 
  703         error = vfsp->vfc_vfsops->vfs_cmount(ma, uap->data, uap->flags, td);
  704         return (error);
  705 }
  706 
  707 
  708 /*
  709  * vfs_domount(): actually attempt a filesystem mount.
  710  */
  711 static int
  712 vfs_domount(
  713         struct thread *td,      /* Flags common to all filesystems. */
  714         const char *fstype,     /* Filesystem type. */
  715         char *fspath,           /* Mount path. */
  716         int fsflags,            /* Flags common to all filesystems. */
  717         void *fsdata            /* Options local to the filesystem. */
  718         )
  719 {
  720         struct vnode *vp;
  721         struct mount *mp;
  722         struct vfsconf *vfsp;
  723         int error, flag = 0, kern_flag = 0;
  724         struct vattr va;
  725         struct nameidata nd;
  726 
  727         mtx_assert(&Giant, MA_OWNED);
  728         /*
  729          * Be ultra-paranoid about making sure the type and fspath
  730          * variables will fit in our mp buffers, including the
  731          * terminating NUL.
  732          */
  733         if (strlen(fstype) >= MFSNAMELEN || strlen(fspath) >= MNAMELEN)
  734                 return (ENAMETOOLONG);
  735 
  736         if (jailed(td->td_ucred))
  737                 return (EPERM);
  738         if (usermount == 0) {
  739                 if ((error = suser(td)) != 0)
  740                         return (error);
  741         }
  742 
  743         /*
  744          * Do not allow NFS export or MNT_SUIDDIR by unprivileged users.
  745          */
  746         if (fsflags & (MNT_EXPORTED | MNT_SUIDDIR)) {
  747                 if ((error = suser(td)) != 0)
  748                         return (error);
  749         }
  750         /*
  751          * Silently enforce MNT_NOSUID and MNT_USER for
  752          * unprivileged users.
  753          */
  754         if (suser(td) != 0)
  755                 fsflags |= MNT_NOSUID | MNT_USER;
  756 
  757         /* Load KLDs before we lock the covered vnode to avoid reversals. */
  758         vfsp = NULL;
  759         if ((fsflags & MNT_UPDATE) == 0) {
  760                 /* Don't try to load KLDs if we're mounting the root. */
  761                 if (fsflags & MNT_ROOTFS)
  762                         vfsp = vfs_byname(fstype);
  763                 else
  764                         vfsp = vfs_byname_kld(fstype, td, &error);
  765                 if (vfsp == NULL)
  766                         return (ENODEV);
  767         }
  768         /*
  769          * Get vnode to be covered
  770          */
  771         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspath, td);
  772         if ((error = namei(&nd)) != 0)
  773                 return (error);
  774         NDFREE(&nd, NDF_ONLY_PNBUF);
  775         vp = nd.ni_vp;
  776         if (fsflags & MNT_UPDATE) {
  777                 if ((vp->v_vflag & VV_ROOT) == 0) {
  778                         vput(vp);
  779                         return (EINVAL);
  780                 }
  781                 mp = vp->v_mount;
  782                 flag = mp->mnt_flag;
  783                 kern_flag = mp->mnt_kern_flag;
  784                 /*
  785                  * We only allow the filesystem to be reloaded if it
  786                  * is currently mounted read-only.
  787                  */
  788                 if ((fsflags & MNT_RELOAD) &&
  789                     ((mp->mnt_flag & MNT_RDONLY) == 0)) {
  790                         vput(vp);
  791                         return (EOPNOTSUPP);    /* Needs translation */
  792                 }
  793                 /*
  794                  * Only privileged root, or (if MNT_USER is set) the user that
  795                  * did the original mount is permitted to update it.
  796                  */
  797                 error = vfs_suser(mp, td);
  798                 if (error) {
  799                         vput(vp);
  800                         return (error);
  801                 }
  802                 if (vfs_busy(mp, LK_NOWAIT, 0, td)) {
  803                         vput(vp);
  804                         return (EBUSY);
  805                 }
  806                 VI_LOCK(vp);
  807                 if ((vp->v_iflag & VI_MOUNT) != 0 ||
  808                     vp->v_mountedhere != NULL) {
  809                         VI_UNLOCK(vp);
  810                         vfs_unbusy(mp, td);
  811                         vput(vp);
  812                         return (EBUSY);
  813                 }
  814                 vp->v_iflag |= VI_MOUNT;
  815                 VI_UNLOCK(vp);
  816                 mp->mnt_flag |= fsflags &
  817                     (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_SNAPSHOT | MNT_ROOTFS);
  818                 VOP_UNLOCK(vp, 0, td);
  819                 mp->mnt_optnew = fsdata;
  820                 vfs_mergeopts(mp->mnt_optnew, mp->mnt_opt);
  821         } else {
  822                 /*
  823                  * If the user is not root, ensure that they own the directory
  824                  * onto which we are attempting to mount.
  825                  */
  826                 error = VOP_GETATTR(vp, &va, td->td_ucred, td);
  827                 if (error) {
  828                         vput(vp);
  829                         return (error);
  830                 }
  831                 if (va.va_uid != td->td_ucred->cr_uid) {
  832                         if ((error = suser(td)) != 0) {
  833                                 vput(vp);
  834                                 return (error);
  835                         }
  836                 }
  837                 error = vinvalbuf(vp, V_SAVE, td, 0, 0);
  838                 if (error != 0) {
  839                         vput(vp);
  840                         return (error);
  841                 }
  842                 if (vp->v_type != VDIR) {
  843                         vput(vp);
  844                         return (ENOTDIR);
  845                 }
  846                 VI_LOCK(vp);
  847                 if ((vp->v_iflag & VI_MOUNT) != 0 ||
  848                     vp->v_mountedhere != NULL) {
  849                         VI_UNLOCK(vp);
  850                         vput(vp);
  851                         return (EBUSY);
  852                 }
  853                 vp->v_iflag |= VI_MOUNT;
  854                 VI_UNLOCK(vp);
  855 
  856                 /*
  857                  * Allocate and initialize the filesystem.
  858                  */
  859                 error = vfs_mount_alloc(vp, vfsp, fspath, td, &mp);
  860                 if (error) {
  861                         vput(vp);
  862                         return (error);
  863                 }
  864                 VOP_UNLOCK(vp, 0, td);
  865 
  866                 /* XXXMAC: pass to vfs_mount_alloc? */
  867                 mp->mnt_optnew = fsdata;
  868         }
  869 
  870         /*
  871          * Set the mount level flags.
  872          */
  873         if (fsflags & MNT_RDONLY)
  874                 mp->mnt_flag |= MNT_RDONLY;
  875         mp->mnt_flag &=~ MNT_UPDATEMASK;
  876         mp->mnt_flag |= fsflags & (MNT_UPDATEMASK | MNT_FORCE | MNT_ROOTFS);
  877         /*
  878          * Mount the filesystem.
  879          * XXX The final recipients of VFS_MOUNT just overwrite the ndp they
  880          * get.  No freeing of cn_pnbuf.
  881          */
  882         error = VFS_MOUNT(mp, td);
  883         if (!error) {
  884                 if (mp->mnt_opt != NULL)
  885                         vfs_freeopts(mp->mnt_opt);
  886                 mp->mnt_opt = mp->mnt_optnew;
  887                 (void)VFS_STATFS(mp, &mp->mnt_stat, td);
  888         }
  889         /*
  890          * Prevent external consumers of mount options from reading
  891          * mnt_optnew.
  892         */
  893         mp->mnt_optnew = NULL;
  894         if (mp->mnt_flag & MNT_UPDATE) {
  895                 mp->mnt_flag &=
  896                     ~(MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_SNAPSHOT);
  897                 if (error) {
  898                         mp->mnt_flag = flag;
  899                         mp->mnt_kern_flag = kern_flag;
  900                 }
  901                 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
  902                         if (mp->mnt_syncer == NULL)
  903                                 error = vfs_allocate_syncvnode(mp);
  904                 } else {
  905                         if (mp->mnt_syncer != NULL)
  906                                 vrele(mp->mnt_syncer);
  907                         mp->mnt_syncer = NULL;
  908                 }
  909                 vfs_unbusy(mp, td);
  910                 VI_LOCK(vp);
  911                 vp->v_iflag &= ~VI_MOUNT;
  912                 VI_UNLOCK(vp);
  913                 vrele(vp);
  914                 return (error);
  915         }
  916         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  917         /*
  918          * Put the new filesystem on the mount list after root.
  919          */
  920         cache_purge(vp);
  921         if (!error) {
  922                 struct vnode *newdp;
  923 
  924                 VI_LOCK(vp);
  925                 vp->v_iflag &= ~VI_MOUNT;
  926                 VI_UNLOCK(vp);
  927                 vp->v_mountedhere = mp;
  928                 mtx_lock(&mountlist_mtx);
  929                 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
  930                 mtx_unlock(&mountlist_mtx);
  931                 vfs_event_signal(NULL, VQ_MOUNT, 0);
  932                 if (VFS_ROOT(mp, LK_EXCLUSIVE, &newdp, td))
  933                         panic("mount: lost mount");
  934                 mountcheckdirs(vp, newdp);
  935                 vput(newdp);
  936                 VOP_UNLOCK(vp, 0, td);
  937                 if ((mp->mnt_flag & MNT_RDONLY) == 0)
  938                         error = vfs_allocate_syncvnode(mp);
  939                 vfs_unbusy(mp, td);
  940                 if (error)
  941                         vrele(vp);
  942         } else {
  943                 VI_LOCK(vp);
  944                 vp->v_iflag &= ~VI_MOUNT;
  945                 VI_UNLOCK(vp);
  946                 vfs_mount_destroy(mp, td);
  947                 vput(vp);
  948         }
  949         return (error);
  950 }
  951 
  952 /*
  953  * ---------------------------------------------------------------------
  954  * Unmount a filesystem.
  955  *
  956  * Note: unmount takes a path to the vnode mounted on as argument,
  957  * not special file (as before).
  958  */
  959 #ifndef _SYS_SYSPROTO_H_
  960 struct unmount_args {
  961         char    *path;
  962         int     flags;
  963 };
  964 #endif
  965 /* ARGSUSED */
  966 int
  967 unmount(td, uap)
  968         struct thread *td;
  969         register struct unmount_args /* {
  970                 char *path;
  971                 int flags;
  972         } */ *uap;
  973 {
  974         struct mount *mp;
  975         char *pathbuf;
  976         int error, id0, id1;
  977 
  978         if (jailed(td->td_ucred))
  979                 return (EPERM);
  980         if (usermount == 0) {
  981                 if ((error = suser(td)) != 0)
  982                         return (error);
  983         }
  984 
  985         pathbuf = malloc(MNAMELEN, M_TEMP, M_WAITOK);
  986         error = copyinstr(uap->path, pathbuf, MNAMELEN, NULL);
  987         if (error) {
  988                 free(pathbuf, M_TEMP);
  989                 return (error);
  990         }
  991         if (uap->flags & MNT_BYFSID) {
  992                 /* Decode the filesystem ID. */
  993                 if (sscanf(pathbuf, "FSID:%d:%d", &id0, &id1) != 2) {
  994                         free(pathbuf, M_TEMP);
  995                         return (EINVAL);
  996                 }
  997 
  998                 mtx_lock(&mountlist_mtx);
  999                 TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) {
 1000                         if (mp->mnt_stat.f_fsid.val[0] == id0 &&
 1001                             mp->mnt_stat.f_fsid.val[1] == id1)
 1002                                 break;
 1003                 }
 1004                 mtx_unlock(&mountlist_mtx);
 1005         } else {
 1006                 mtx_lock(&mountlist_mtx);
 1007                 TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) {
 1008                         if (strcmp(mp->mnt_stat.f_mntonname, pathbuf) == 0)
 1009                                 break;
 1010                 }
 1011                 mtx_unlock(&mountlist_mtx);
 1012         }
 1013         free(pathbuf, M_TEMP);
 1014         if (mp == NULL) {
 1015                 /*
 1016                  * Previously we returned ENOENT for a nonexistent path and
 1017                  * EINVAL for a non-mountpoint.  We cannot tell these apart
 1018                  * now, so in the !MNT_BYFSID case return the more likely
 1019                  * EINVAL for compatibility.
 1020                  */
 1021                 return ((uap->flags & MNT_BYFSID) ? ENOENT : EINVAL);
 1022         }
 1023 
 1024         /*
 1025          * Only privileged root, or (if MNT_USER is set) the user that did the
 1026          * original mount is permitted to unmount this filesystem.
 1027          */
 1028         error = vfs_suser(mp, td);
 1029         if (error)
 1030                 return (error);
 1031 
 1032         /*
 1033          * Don't allow unmounting the root filesystem.
 1034          */
 1035         if (mp->mnt_flag & MNT_ROOTFS)
 1036                 return (EINVAL);
 1037         mtx_lock(&Giant);
 1038         error = dounmount(mp, uap->flags, td);
 1039         mtx_unlock(&Giant);
 1040         return (error);
 1041 }
 1042 
 1043 /*
 1044  * Do the actual filesystem unmount.
 1045  */
 1046 int
 1047 dounmount(mp, flags, td)
 1048         struct mount *mp;
 1049         int flags;
 1050         struct thread *td;
 1051 {
 1052         struct vnode *coveredvp, *fsrootvp;
 1053         int error;
 1054         int async_flag;
 1055 
 1056         mtx_assert(&Giant, MA_OWNED);
 1057 
 1058         if ((coveredvp = mp->mnt_vnodecovered) != NULL)
 1059                 vn_lock(coveredvp, LK_EXCLUSIVE | LK_RETRY, td);
 1060         MNT_ILOCK(mp);
 1061         if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
 1062                 MNT_IUNLOCK(mp);
 1063                 if (coveredvp)
 1064                         VOP_UNLOCK(coveredvp, 0, td);
 1065                 return (EBUSY);
 1066         }
 1067         mp->mnt_kern_flag |= MNTK_UNMOUNT;
 1068         /* Allow filesystems to detect that a forced unmount is in progress. */
 1069         if (flags & MNT_FORCE)
 1070                 mp->mnt_kern_flag |= MNTK_UNMOUNTF;
 1071         error = lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK |
 1072             ((flags & MNT_FORCE) ? 0 : LK_NOWAIT), MNT_MTX(mp), td);
 1073         if (error) {
 1074                 MNT_ILOCK(mp);
 1075                 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
 1076                 if (mp->mnt_kern_flag & MNTK_MWAIT)
 1077                         wakeup(mp);
 1078                 MNT_IUNLOCK(mp);
 1079                 if (coveredvp)
 1080                         VOP_UNLOCK(coveredvp, 0, td);
 1081                 return (error);
 1082         }
 1083         vn_start_write(NULL, &mp, V_WAIT);
 1084 
 1085         if (mp->mnt_flag & MNT_EXPUBLIC)
 1086                 vfs_setpublicfs(NULL, NULL, NULL);
 1087 
 1088         vfs_msync(mp, MNT_WAIT);
 1089         async_flag = mp->mnt_flag & MNT_ASYNC;
 1090         mp->mnt_flag &= ~MNT_ASYNC;
 1091         cache_purgevfs(mp);     /* remove cache entries for this file sys */
 1092         if (mp->mnt_syncer != NULL)
 1093                 vrele(mp->mnt_syncer);
 1094         /*
 1095          * For forced unmounts, move process cdir/rdir refs on the fs root
 1096          * vnode to the covered vnode.  For non-forced unmounts we want
 1097          * such references to cause an EBUSY error.
 1098          */
 1099         if ((flags & MNT_FORCE) &&
 1100             VFS_ROOT(mp, LK_EXCLUSIVE, &fsrootvp, td) == 0) {
 1101                 if (mp->mnt_vnodecovered != NULL)
 1102                         mountcheckdirs(fsrootvp, mp->mnt_vnodecovered);
 1103                 if (fsrootvp == rootvnode) {
 1104                         vrele(rootvnode);
 1105                         rootvnode = NULL;
 1106                 }
 1107                 vput(fsrootvp);
 1108         }
 1109         if (((mp->mnt_flag & MNT_RDONLY) ||
 1110              (error = VFS_SYNC(mp, MNT_WAIT, td)) == 0) ||
 1111             (flags & MNT_FORCE)) {
 1112                 error = VFS_UNMOUNT(mp, flags, td);
 1113         }
 1114         vn_finished_write(mp);
 1115         if (error) {
 1116                 /* Undo cdir/rdir and rootvnode changes made above. */
 1117                 if ((flags & MNT_FORCE) &&
 1118                     VFS_ROOT(mp, LK_EXCLUSIVE, &fsrootvp, td) == 0) {
 1119                         if (mp->mnt_vnodecovered != NULL)
 1120                                 mountcheckdirs(mp->mnt_vnodecovered, fsrootvp);
 1121                         if (rootvnode == NULL) {
 1122                                 rootvnode = fsrootvp;
 1123                                 vref(rootvnode);
 1124                         }
 1125                         vput(fsrootvp);
 1126                 }
 1127                 if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL)
 1128                         (void) vfs_allocate_syncvnode(mp);
 1129                 MNT_ILOCK(mp);
 1130                 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
 1131                 mp->mnt_flag |= async_flag;
 1132                 lockmgr(&mp->mnt_lock, LK_RELEASE, NULL, td);
 1133                 if (mp->mnt_kern_flag & MNTK_MWAIT)
 1134                         wakeup(mp);
 1135                 MNT_IUNLOCK(mp);
 1136                 if (coveredvp)
 1137                         VOP_UNLOCK(coveredvp, 0, td);
 1138                 return (error);
 1139         }
 1140         mtx_lock(&mountlist_mtx);
 1141         TAILQ_REMOVE(&mountlist, mp, mnt_list);
 1142         mtx_unlock(&mountlist_mtx);
 1143         if (coveredvp != NULL) {
 1144                 coveredvp->v_mountedhere = NULL;
 1145                 vput(coveredvp);
 1146         }
 1147         vfs_event_signal(NULL, VQ_UNMOUNT, 0);
 1148         vfs_mount_destroy(mp, td);
 1149         return (0);
 1150 }
 1151 
 1152 /*
 1153  * ---------------------------------------------------------------------
 1154  * Mounting of root filesystem
 1155  *
 1156  */
 1157 
 1158 struct root_hold_token {
 1159         const char                      *who;
 1160         LIST_ENTRY(root_hold_token)     list;
 1161 };
 1162 
 1163 static LIST_HEAD(, root_hold_token)     root_holds =
 1164     LIST_HEAD_INITIALIZER(&root_holds);
 1165 
 1166 struct root_hold_token *
 1167 root_mount_hold(const char *identifier)
 1168 {
 1169         struct root_hold_token *h;
 1170 
 1171         h = malloc(sizeof *h, M_DEVBUF, M_ZERO | M_WAITOK);
 1172         h->who = identifier;
 1173         mtx_lock(&mountlist_mtx);
 1174         LIST_INSERT_HEAD(&root_holds, h, list);
 1175         mtx_unlock(&mountlist_mtx);
 1176         return (h);
 1177 }
 1178 
 1179 void
 1180 root_mount_rel(struct root_hold_token *h)
 1181 {
 1182 
 1183         mtx_lock(&mountlist_mtx);
 1184         LIST_REMOVE(h, list);
 1185         wakeup(&root_holds);
 1186         mtx_unlock(&mountlist_mtx);
 1187         free(h, M_DEVBUF);
 1188 }
 1189 
 1190 static void
 1191 root_mount_wait(void)
 1192 {
 1193         struct root_hold_token *h;
 1194 
 1195         for (;;) {
 1196                 DROP_GIANT();
 1197                 g_waitidle();
 1198                 PICKUP_GIANT();
 1199                 mtx_lock(&mountlist_mtx);
 1200                 if (LIST_EMPTY(&root_holds)) {
 1201                         mtx_unlock(&mountlist_mtx);
 1202                         break;
 1203                 }
 1204                 printf("Root mount waiting for:");
 1205                 LIST_FOREACH(h, &root_holds, list)
 1206                         printf(" %s", h->who);
 1207                 printf("\n");
 1208                 msleep(&root_holds, &mountlist_mtx, PZERO | PDROP, "roothold",
 1209                     hz);
 1210         }
 1211 }
 1212 
 1213 static void
 1214 set_rootvnode(struct thread *td)
 1215 {
 1216         struct proc *p;
 1217 
 1218         if (VFS_ROOT(TAILQ_FIRST(&mountlist), LK_EXCLUSIVE, &rootvnode, td))
 1219                 panic("Cannot find root vnode");
 1220 
 1221         p = td->td_proc;
 1222         FILEDESC_LOCK(p->p_fd);
 1223 
 1224         if (p->p_fd->fd_cdir != NULL)
 1225                 vrele(p->p_fd->fd_cdir);
 1226         p->p_fd->fd_cdir = rootvnode;
 1227         VREF(rootvnode);
 1228 
 1229         if (p->p_fd->fd_rdir != NULL)
 1230                 vrele(p->p_fd->fd_rdir);
 1231         p->p_fd->fd_rdir = rootvnode;
 1232         VREF(rootvnode);
 1233 
 1234         FILEDESC_UNLOCK(p->p_fd);
 1235 
 1236         VOP_UNLOCK(rootvnode, 0, td);
 1237 }
 1238 
 1239 /*
 1240  * Mount /devfs as our root filesystem, but do not put it on the mountlist
 1241  * yet.  Create a /dev -> / symlink so that absolute pathnames will lookup.
 1242  */
 1243 
 1244 static void
 1245 devfs_first(void)
 1246 {
 1247         struct thread *td = curthread;
 1248         struct vfsconf *vfsp;
 1249         struct mount *mp = NULL;
 1250         int error;
 1251 
 1252         vfsp = vfs_byname("devfs");
 1253         KASSERT(vfsp != NULL, ("Could not find devfs by name"));
 1254         if (vfsp == NULL) 
 1255                 return;
 1256 
 1257         error = vfs_mount_alloc(NULLVP, vfsp, "/dev", td, &mp);
 1258         KASSERT(error == 0, ("vfs_mount_alloc failed %d", error));
 1259         if (error)
 1260                 return;
 1261 
 1262         error = VFS_MOUNT(mp, curthread);
 1263         KASSERT(error == 0, ("VFS_MOUNT(devfs) failed %d", error));
 1264         if (error)
 1265                 return;
 1266 
 1267         mtx_lock(&mountlist_mtx);
 1268         TAILQ_INSERT_HEAD(&mountlist, mp, mnt_list);
 1269         mtx_unlock(&mountlist_mtx);
 1270 
 1271         set_rootvnode(td);
 1272 
 1273         error = kern_symlink(td, "/", "dev", UIO_SYSSPACE);
 1274         if (error)
 1275                 printf("kern_symlink /dev -> / returns %d\n", error);
 1276 }
 1277 
 1278 /*
 1279  * Surgically move our devfs to be mounted on /dev.
 1280  */
 1281 
 1282 static void
 1283 devfs_fixup(struct thread *td)
 1284 {
 1285         struct nameidata nd;
 1286         int error;
 1287         struct vnode *vp, *dvp;
 1288         struct mount *mp;
 1289 
 1290         /* Remove our devfs mount from the mountlist and purge the cache */
 1291         mtx_lock(&mountlist_mtx);
 1292         mp = TAILQ_FIRST(&mountlist);
 1293         TAILQ_REMOVE(&mountlist, mp, mnt_list);
 1294         mtx_unlock(&mountlist_mtx);
 1295         cache_purgevfs(mp);
 1296 
 1297         VFS_ROOT(mp, LK_EXCLUSIVE, &dvp, td);
 1298         VI_LOCK(dvp);
 1299         dvp->v_iflag &= ~VI_MOUNT;
 1300         dvp->v_mountedhere = NULL;
 1301         VI_UNLOCK(dvp);
 1302 
 1303         /* Set up the real rootvnode, and purge the cache */
 1304         TAILQ_FIRST(&mountlist)->mnt_vnodecovered = NULL;
 1305         set_rootvnode(td);
 1306         cache_purgevfs(rootvnode->v_mount);
 1307 
 1308         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, "/dev", td);
 1309         error = namei(&nd);
 1310         if (error) {
 1311                 printf("Lookup of /dev for devfs, error: %d\n", error);
 1312                 return;
 1313         }
 1314         NDFREE(&nd, NDF_ONLY_PNBUF);
 1315         vp = nd.ni_vp;
 1316         if (vp->v_type != VDIR) {
 1317                 vput(vp);
 1318         }
 1319         error = vinvalbuf(vp, V_SAVE, td, 0, 0);
 1320         if (error) {
 1321                 vput(vp);
 1322         }
 1323         cache_purge(vp);
 1324         mp->mnt_vnodecovered = vp;
 1325         vp->v_mountedhere = mp;
 1326         mtx_lock(&mountlist_mtx);
 1327         TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
 1328         mtx_unlock(&mountlist_mtx);
 1329         VOP_UNLOCK(vp, 0, td);
 1330         vput(dvp);
 1331         vfs_unbusy(mp, td);
 1332 
 1333         /* Unlink the no longer needed /dev/dev -> / symlink */
 1334         kern_unlink(td, "/dev/dev", UIO_SYSSPACE);
 1335 }
 1336 
 1337 /*
 1338  * Find and mount the root filesystem
 1339  */
 1340 void
 1341 vfs_mountroot(void)
 1342 {
 1343         char *cp;
 1344         int error, i, asked = 0;
 1345 
 1346         root_mount_wait();
 1347 
 1348         devfs_first();
 1349 
 1350         /*
 1351          * We are booted with instructions to prompt for the root filesystem.
 1352          */
 1353         if (boothowto & RB_ASKNAME) {
 1354                 if (!vfs_mountroot_ask())
 1355                         return;
 1356                 asked = 1;
 1357         }
 1358 
 1359         /*
 1360          * The root filesystem information is compiled in, and we are
 1361          * booted with instructions to use it.
 1362          */
 1363         if (ctrootdevname != NULL && (boothowto & RB_DFLTROOT)) {
 1364                 if (!vfs_mountroot_try(ctrootdevname))
 1365                         return;
 1366                 ctrootdevname = NULL;
 1367         }
 1368 
 1369         /*
 1370          * We've been given the generic "use CDROM as root" flag.  This is
 1371          * necessary because one media may be used in many different
 1372          * devices, so we need to search for them.
 1373          */
 1374         if (boothowto & RB_CDROM) {
 1375                 for (i = 0; cdrom_rootdevnames[i] != NULL; i++) {
 1376                         if (!vfs_mountroot_try(cdrom_rootdevnames[i]))
 1377                                 return;
 1378                 }
 1379         }
 1380 
 1381         /*
 1382          * Try to use the value read by the loader from /etc/fstab, or
 1383          * supplied via some other means.  This is the preferred
 1384          * mechanism.
 1385          */
 1386         cp = getenv("vfs.root.mountfrom");
 1387         if (cp != NULL) {
 1388                 error = vfs_mountroot_try(cp);
 1389                 freeenv(cp);
 1390                 if (!error)
 1391                         return;
 1392         }
 1393 
 1394         /*
 1395          * Try values that may have been computed by code during boot
 1396          */
 1397         if (!vfs_mountroot_try(rootdevnames[0]))
 1398                 return;
 1399         if (!vfs_mountroot_try(rootdevnames[1]))
 1400                 return;
 1401 
 1402         /*
 1403          * If we (still) have a compiled-in default, try it.
 1404          */
 1405         if (ctrootdevname != NULL)
 1406                 if (!vfs_mountroot_try(ctrootdevname))
 1407                         return;
 1408         /*
 1409          * Everything so far has failed, prompt on the console if we haven't
 1410          * already tried that.
 1411          */
 1412         if (!asked)
 1413                 if (!vfs_mountroot_ask())
 1414                         return;
 1415 
 1416         panic("Root mount failed, startup aborted.");
 1417 }
 1418 
 1419 /*
 1420  * Mount (mountfrom) as the root filesystem.
 1421  */
 1422 static int
 1423 vfs_mountroot_try(const char *mountfrom)
 1424 {
 1425         struct mount    *mp;
 1426         char            *vfsname, *path;
 1427         time_t          timebase;
 1428         int             error;
 1429         char            patt[32];
 1430 
 1431         vfsname = NULL;
 1432         path    = NULL;
 1433         mp      = NULL;
 1434         error   = EINVAL;
 1435 
 1436         if (mountfrom == NULL)
 1437                 return (error);         /* don't complain */
 1438         printf("Trying to mount root from %s\n", mountfrom);
 1439 
 1440         /* parse vfs name and path */
 1441         vfsname = malloc(MFSNAMELEN, M_MOUNT, M_WAITOK);
 1442         path = malloc(MNAMELEN, M_MOUNT, M_WAITOK);
 1443         vfsname[0] = path[0] = 0;
 1444         sprintf(patt, "%%%d[a-z0-9]:%%%ds", MFSNAMELEN, MNAMELEN);
 1445         if (sscanf(mountfrom, patt, vfsname, path) < 1)
 1446                 goto out;
 1447 
 1448         if (path[0] == '\0')
 1449                 strcpy(path, ROOTNAME);
 1450 
 1451         error = kernel_vmount(
 1452             MNT_RDONLY | MNT_ROOTFS,
 1453             "fstype", vfsname,
 1454             "fspath", "/",
 1455             "from", path,
 1456             NULL);
 1457         if (error == 0) {
 1458                 /*
 1459                  * We mount devfs prior to mounting the / FS, so the first
 1460                  * entry will typically be devfs.
 1461                  */
 1462                 mp = TAILQ_FIRST(&mountlist);
 1463                 KASSERT(mp != NULL, ("%s: mountlist is empty", __func__));
 1464 
 1465                 /*
 1466                  * Iterate over all currently mounted file systems and use
 1467                  * the time stamp found to check and/or initialize the RTC.
 1468                  * Typically devfs has no time stamp and the only other FS
 1469                  * is the actual / FS.
 1470                  * Call inittodr() only once and pass it the largest of the
 1471                  * timestamps we encounter.
 1472                  */
 1473                 timebase = 0;
 1474                 do {
 1475                         if (mp->mnt_time > timebase)
 1476                                 timebase = mp->mnt_time;
 1477                         mp = TAILQ_NEXT(mp, mnt_list);
 1478                 } while (mp != NULL);
 1479                 inittodr(timebase);
 1480 
 1481                 devfs_fixup(curthread);
 1482         }
 1483 out:
 1484         free(path, M_MOUNT);
 1485         free(vfsname, M_MOUNT);
 1486         return (error);
 1487 }
 1488 
 1489 /*
 1490  * ---------------------------------------------------------------------
 1491  * Interactive root filesystem selection code.
 1492  */
 1493 
 1494 static int
 1495 vfs_mountroot_ask(void)
 1496 {
 1497         char name[128];
 1498 
 1499         for(;;) {
 1500                 printf("\nManual root filesystem specification:\n");
 1501                 printf("  <fstype>:<device>  Mount <device> using filesystem <fstype>\n");
 1502 #if defined(__i386__) || defined(__ia64__)
 1503                 printf("                       eg. ufs:da0s1a\n");
 1504 #else
 1505                 printf("                       eg. ufs:/dev/da0a\n");
 1506 #endif
 1507                 printf("  ?                  List valid disk boot devices\n");
 1508                 printf("  <empty line>       Abort manual input\n");
 1509                 printf("\nmountroot> ");
 1510                 gets(name, sizeof(name), 1);
 1511                 if (name[0] == '\0')
 1512                         return (1);
 1513                 if (name[0] == '?') {
 1514                         printf("\nList of GEOM managed disk devices:\n  ");
 1515                         g_dev_print();
 1516                         continue;
 1517                 }
 1518                 if (!vfs_mountroot_try(name))
 1519                         return (0);
 1520         }
 1521 }
 1522 
 1523 /*
 1524  * ---------------------------------------------------------------------
 1525  * Functions for querying mount options/arguments from filesystems.
 1526  */
 1527 
 1528 /*
 1529  * Check that no unknown options are given
 1530  */
 1531 int
 1532 vfs_filteropt(struct vfsoptlist *opts, const char **legal)
 1533 {
 1534         struct vfsopt *opt;
 1535         const char **t, *p;
 1536         
 1537 
 1538         TAILQ_FOREACH(opt, opts, link) {
 1539                 p = opt->name;
 1540                 if (p[0] == 'n' && p[1] == 'o')
 1541                         p += 2;
 1542                 for(t = global_opts; *t != NULL; t++)
 1543                         if (!strcmp(*t, p))
 1544                                 break;
 1545                 if (*t != NULL)
 1546                         continue;
 1547                 for(t = legal; *t != NULL; t++)
 1548                         if (!strcmp(*t, p))
 1549                                 break;
 1550                 if (*t != NULL)
 1551                         continue;
 1552                 printf("mount option <%s> is unknown\n", p);
 1553                 return (EINVAL);
 1554         }
 1555         return (0);
 1556 }
 1557 
 1558 /*
 1559  * Get a mount option by its name.
 1560  *
 1561  * Return 0 if the option was found, ENOENT otherwise.
 1562  * If len is non-NULL it will be filled with the length
 1563  * of the option. If buf is non-NULL, it will be filled
 1564  * with the address of the option.
 1565  */
 1566 int
 1567 vfs_getopt(opts, name, buf, len)
 1568         struct vfsoptlist *opts;
 1569         const char *name;
 1570         void **buf;
 1571         int *len;
 1572 {
 1573         struct vfsopt *opt;
 1574 
 1575         KASSERT(opts != NULL, ("vfs_getopt: caller passed 'opts' as NULL"));
 1576 
 1577         TAILQ_FOREACH(opt, opts, link) {
 1578                 if (strcmp(name, opt->name) == 0) {
 1579                         if (len != NULL)
 1580                                 *len = opt->len;
 1581                         if (buf != NULL)
 1582                                 *buf = opt->value;
 1583                         return (0);
 1584                 }
 1585         }
 1586         return (ENOENT);
 1587 }
 1588 
 1589 char *
 1590 vfs_getopts(struct vfsoptlist *opts, const char *name, int *error)
 1591 {
 1592         struct vfsopt *opt;
 1593 
 1594         *error = 0;
 1595         TAILQ_FOREACH(opt, opts, link) {
 1596                 if (strcmp(name, opt->name) != 0)
 1597                         continue;
 1598                 if (((char *)opt->value)[opt->len - 1] != '\0') {
 1599                         *error = EINVAL;
 1600                         return (NULL);
 1601                 }
 1602                 return (opt->value);
 1603         }
 1604         return (NULL);
 1605 }
 1606 
 1607 int
 1608 vfs_flagopt(struct vfsoptlist *opts, const char *name, u_int *w, u_int val)
 1609 {
 1610         struct vfsopt *opt;
 1611 
 1612         TAILQ_FOREACH(opt, opts, link) {
 1613                 if (strcmp(name, opt->name) == 0) {
 1614                         if (w != NULL)
 1615                                 *w |= val;
 1616                         return (1);
 1617                 }
 1618         }
 1619         if (w != NULL)
 1620                 *w &= ~val;
 1621         return (0);
 1622 }
 1623 
 1624 int
 1625 vfs_scanopt(struct vfsoptlist *opts, const char *name, const char *fmt, ...)
 1626 {
 1627         va_list ap;
 1628         struct vfsopt *opt;
 1629         int ret;
 1630 
 1631         KASSERT(opts != NULL, ("vfs_getopt: caller passed 'opts' as NULL"));
 1632 
 1633         TAILQ_FOREACH(opt, opts, link) {
 1634                 if (strcmp(name, opt->name) != 0)
 1635                         continue;
 1636                 if (((char *)opt->value)[opt->len - 1] != '\0')
 1637                         return (0);
 1638                 va_start(ap, fmt);
 1639                 ret = vsscanf(opt->value, fmt, ap);
 1640                 va_end(ap);
 1641                 return (ret);
 1642         }
 1643         return (0);
 1644 }
 1645 
 1646 /*
 1647  * Find and copy a mount option.
 1648  *
 1649  * The size of the buffer has to be specified
 1650  * in len, if it is not the same length as the
 1651  * mount option, EINVAL is returned.
 1652  * Returns ENOENT if the option is not found.
 1653  */
 1654 int
 1655 vfs_copyopt(opts, name, dest, len)
 1656         struct vfsoptlist *opts;
 1657         const char *name;
 1658         void *dest;
 1659         int len;
 1660 {
 1661         struct vfsopt *opt;
 1662 
 1663         KASSERT(opts != NULL, ("vfs_copyopt: caller passed 'opts' as NULL"));
 1664 
 1665         TAILQ_FOREACH(opt, opts, link) {
 1666                 if (strcmp(name, opt->name) == 0) {
 1667                         if (len != opt->len)
 1668                                 return (EINVAL);
 1669                         bcopy(opt->value, dest, opt->len);
 1670                         return (0);
 1671                 }
 1672         }
 1673         return (ENOENT);
 1674 }
 1675 
 1676 /*
 1677  * This is a helper function for filesystems to traverse their
 1678  * vnodes.  See MNT_VNODE_FOREACH() in sys/mount.h
 1679  */
 1680 
 1681 struct vnode *
 1682 __mnt_vnode_next(struct vnode **mvp, struct mount *mp)
 1683 {
 1684         struct vnode *vp;
 1685 
 1686         mtx_assert(MNT_MTX(mp), MA_OWNED);
 1687 
 1688         KASSERT((*mvp)->v_mount == mp, ("marker vnode mount list mismatch"));
 1689         vp = TAILQ_NEXT(*mvp, v_nmntvnodes);
 1690         while (vp != NULL && vp->v_type == VMARKER) 
 1691                 vp = TAILQ_NEXT(vp, v_nmntvnodes);
 1692         
 1693         /* Check if we are done */
 1694         if (vp == NULL) {
 1695                 __mnt_vnode_markerfree(mvp, mp);
 1696                 return (NULL);
 1697         }
 1698         TAILQ_REMOVE(&mp->mnt_nvnodelist, *mvp, v_nmntvnodes);
 1699         TAILQ_INSERT_AFTER(&mp->mnt_nvnodelist, vp, *mvp, v_nmntvnodes);
 1700         return (vp);
 1701 }
 1702 
 1703 struct vnode *
 1704 __mnt_vnode_first(struct vnode **mvp, struct mount *mp)
 1705 {
 1706         struct vnode *vp;
 1707 
 1708         mtx_assert(MNT_MTX(mp), MA_OWNED);
 1709 
 1710         vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
 1711         while (vp != NULL && vp->v_type == VMARKER) 
 1712                 vp = TAILQ_NEXT(vp, v_nmntvnodes);
 1713         
 1714         /* Check if we are done */
 1715         if (vp == NULL) {
 1716                 *mvp = NULL;
 1717                 return (NULL);
 1718         }
 1719         mp->mnt_holdcnt++;
 1720         MNT_IUNLOCK(mp);
 1721         *mvp = (struct vnode *) malloc(sizeof(struct vnode),
 1722                                        M_VNODE_MARKER,
 1723                                        M_WAITOK | M_ZERO);
 1724         MNT_ILOCK(mp);
 1725         (*mvp)->v_type = VMARKER;
 1726 
 1727         vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
 1728         while (vp != NULL && vp->v_type == VMARKER) 
 1729                 vp = TAILQ_NEXT(vp, v_nmntvnodes);
 1730         
 1731         /* Check if we are done */
 1732         if (vp == NULL) {
 1733                 MNT_IUNLOCK(mp);
 1734                 free(*mvp, M_VNODE_MARKER);
 1735                 MNT_ILOCK(mp);
 1736                 *mvp = NULL;
 1737                 mp->mnt_holdcnt--;
 1738                 if (mp->mnt_holdcnt == 0 && mp->mnt_holdcntwaiters != 0)
 1739                         wakeup(&mp->mnt_holdcnt);
 1740                 return (NULL);
 1741         }
 1742         mp->mnt_markercnt++;
 1743         (*mvp)->v_mount = mp;
 1744         TAILQ_INSERT_AFTER(&mp->mnt_nvnodelist, vp, *mvp, v_nmntvnodes);
 1745         return (vp);
 1746 }
 1747 
 1748 
 1749 void
 1750 __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp)
 1751 {
 1752 
 1753         if (*mvp == NULL)
 1754                 return;
 1755         
 1756         mtx_assert(MNT_MTX(mp), MA_OWNED);
 1757 
 1758         KASSERT((*mvp)->v_mount == mp, ("marker vnode mount list mismatch"));
 1759         TAILQ_REMOVE(&mp->mnt_nvnodelist, *mvp, v_nmntvnodes);
 1760         MNT_IUNLOCK(mp);
 1761         free(*mvp, M_VNODE_MARKER);
 1762         MNT_ILOCK(mp);
 1763         *mvp = NULL;
 1764 
 1765         mp->mnt_markercnt--;
 1766         mp->mnt_holdcnt--;
 1767         if (mp->mnt_holdcnt == 0 && mp->mnt_holdcntwaiters != 0)
 1768                 wakeup(&mp->mnt_holdcnt);
 1769 }
 1770 
 1771 
 1772 int
 1773 __vfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
 1774 {
 1775         int error;
 1776 
 1777         error = mp->mnt_op->vfs_statfs(mp, &mp->mnt_stat, td);
 1778         if (sbp != &mp->mnt_stat)
 1779                 *sbp = mp->mnt_stat;
 1780         return (error);
 1781 }
 1782 
 1783 void
 1784 vfs_mountedfrom(struct mount *mp, const char *from)
 1785 {
 1786 
 1787         bzero(mp->mnt_stat.f_mntfromname, sizeof mp->mnt_stat.f_mntfromname);
 1788         strlcpy(mp->mnt_stat.f_mntfromname, from,
 1789             sizeof mp->mnt_stat.f_mntfromname);
 1790 }
 1791 
 1792 /*
 1793  * ---------------------------------------------------------------------
 1794  * This is the api for building mount args and mounting filesystems from
 1795  * inside the kernel.
 1796  *
 1797  * The API works by accumulation of individual args.  First error is
 1798  * latched.
 1799  *
 1800  * XXX: should be documented in new manpage kernel_mount(9)
 1801  */
 1802 
 1803 /* A memory allocation which must be freed when we are done */
 1804 struct mntaarg {
 1805         SLIST_ENTRY(mntaarg)    next;
 1806 };
 1807 
 1808 /* The header for the mount arguments */
 1809 struct mntarg {
 1810         struct iovec *v;
 1811         int len;
 1812         int error;
 1813         SLIST_HEAD(, mntaarg)   list;
 1814 };
 1815 
 1816 /*
 1817  * Add a boolean argument.
 1818  *
 1819  * flag is the boolean value.
 1820  * name must start with "no".
 1821  */
 1822 struct mntarg *
 1823 mount_argb(struct mntarg *ma, int flag, const char *name)
 1824 {
 1825 
 1826         KASSERT(name[0] == 'n' && name[1] == 'o',
 1827             ("mount_argb(...,%s): name must start with 'no'", name));
 1828 
 1829         return (mount_arg(ma, name + (flag ? 2 : 0), NULL, 0));
 1830 }
 1831 
 1832 /*
 1833  * Add an argument printf style
 1834  */
 1835 struct mntarg *
 1836 mount_argf(struct mntarg *ma, const char *name, const char *fmt, ...)
 1837 {
 1838         va_list ap;
 1839         struct mntaarg *maa;
 1840         struct sbuf *sb;
 1841         int len;
 1842 
 1843         if (ma == NULL) {
 1844                 ma = malloc(sizeof *ma, M_MOUNT, M_WAITOK | M_ZERO);
 1845                 SLIST_INIT(&ma->list);
 1846         }
 1847         if (ma->error)
 1848                 return (ma);
 1849 
 1850         ma->v = realloc(ma->v, sizeof *ma->v * (ma->len + 2),
 1851             M_MOUNT, M_WAITOK);
 1852         ma->v[ma->len].iov_base = (void *)(uintptr_t)name;
 1853         ma->v[ma->len].iov_len = strlen(name) + 1;
 1854         ma->len++;
 1855 
 1856         sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
 1857         va_start(ap, fmt);
 1858         sbuf_vprintf(sb, fmt, ap);
 1859         va_end(ap);
 1860         sbuf_finish(sb);
 1861         len = sbuf_len(sb) + 1;
 1862         maa = malloc(sizeof *maa + len, M_MOUNT, M_WAITOK | M_ZERO);
 1863         SLIST_INSERT_HEAD(&ma->list, maa, next);
 1864         bcopy(sbuf_data(sb), maa + 1, len);
 1865         sbuf_delete(sb);
 1866 
 1867         ma->v[ma->len].iov_base = maa + 1;
 1868         ma->v[ma->len].iov_len = len;
 1869         ma->len++;
 1870 
 1871         return (ma);
 1872 }
 1873 
 1874 /*
 1875  * Add an argument which is a userland string.
 1876  */
 1877 struct mntarg *
 1878 mount_argsu(struct mntarg *ma, const char *name, const void *val, int len)
 1879 {
 1880         struct mntaarg *maa;
 1881         char *tbuf;
 1882 
 1883         if (val == NULL)
 1884                 return (ma);
 1885         if (ma == NULL) {
 1886                 ma = malloc(sizeof *ma, M_MOUNT, M_WAITOK | M_ZERO);
 1887                 SLIST_INIT(&ma->list);
 1888         }
 1889         if (ma->error)
 1890                 return (ma);
 1891         maa = malloc(sizeof *maa + len, M_MOUNT, M_WAITOK | M_ZERO);
 1892         SLIST_INSERT_HEAD(&ma->list, maa, next);
 1893         tbuf = (void *)(maa + 1);
 1894         ma->error = copyinstr(val, tbuf, len, NULL);
 1895         return (mount_arg(ma, name, tbuf, -1));
 1896 }
 1897 
 1898 /*
 1899  * Plain argument.
 1900  *
 1901  * If length is -1, use printf.
 1902  */
 1903 struct mntarg *
 1904 mount_arg(struct mntarg *ma, const char *name, const void *val, int len)
 1905 {
 1906 
 1907         if (ma == NULL) {
 1908                 ma = malloc(sizeof *ma, M_MOUNT, M_WAITOK | M_ZERO);
 1909                 SLIST_INIT(&ma->list);
 1910         }
 1911         if (ma->error)
 1912                 return (ma);
 1913 
 1914         ma->v = realloc(ma->v, sizeof *ma->v * (ma->len + 2),
 1915             M_MOUNT, M_WAITOK);
 1916         ma->v[ma->len].iov_base = (void *)(uintptr_t)name;
 1917         ma->v[ma->len].iov_len = strlen(name) + 1;
 1918         ma->len++;
 1919 
 1920         ma->v[ma->len].iov_base = (void *)(uintptr_t)val;
 1921         if (len < 0)
 1922                 ma->v[ma->len].iov_len = strlen(val) + 1;
 1923         else
 1924                 ma->v[ma->len].iov_len = len;
 1925         ma->len++;
 1926         return (ma);
 1927 }
 1928 
 1929 /*
 1930  * Free a mntarg structure
 1931  */
 1932 static void
 1933 free_mntarg(struct mntarg *ma)
 1934 {
 1935         struct mntaarg *maa;
 1936 
 1937         while (!SLIST_EMPTY(&ma->list)) {
 1938                 maa = SLIST_FIRST(&ma->list);
 1939                 SLIST_REMOVE_HEAD(&ma->list, next);
 1940                 free(maa, M_MOUNT);
 1941         }
 1942         free(ma->v, M_MOUNT);
 1943         free(ma, M_MOUNT);
 1944 }
 1945 
 1946 /*
 1947  * Mount a filesystem
 1948  */
 1949 int
 1950 kernel_mount(struct mntarg *ma, int flags)
 1951 {
 1952         struct uio auio;
 1953         int error;
 1954 
 1955         KASSERT(ma != NULL, ("kernel_mount NULL ma"));
 1956         KASSERT(ma->v != NULL, ("kernel_mount NULL ma->v"));
 1957         KASSERT(!(ma->len & 1), ("kernel_mount odd ma->len (%d)", ma->len));
 1958 
 1959         auio.uio_iov = ma->v;
 1960         auio.uio_iovcnt = ma->len;
 1961         auio.uio_segflg = UIO_SYSSPACE;
 1962 
 1963         error = ma->error;
 1964         if (!error)
 1965                 error = vfs_donmount(curthread, flags, &auio);
 1966         free_mntarg(ma);
 1967         return (error);
 1968 }
 1969 
 1970 /*
 1971  * A printflike function to mount a filesystem.
 1972  */
 1973 int
 1974 kernel_vmount(int flags, ...)
 1975 {
 1976         struct mntarg *ma = NULL;
 1977         va_list ap;
 1978         const char *cp;
 1979         const void *vp;
 1980         int error;
 1981 
 1982         va_start(ap, flags);
 1983         for (;;) {
 1984                 cp = va_arg(ap, const char *);
 1985                 if (cp == NULL)
 1986                         break;
 1987                 vp = va_arg(ap, const void *);
 1988                 ma = mount_arg(ma, cp, vp, -1);
 1989         }
 1990         va_end(ap);
 1991 
 1992         error = kernel_mount(ma, flags);
 1993         return (error);
 1994 }

Cache object: a535210cd96ad3e6f74234628fd5671f


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