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

Cache object: 5fcad4b855c006ec0f17a40a112f4973


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