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) 1989, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  * (c) UNIX System Laboratories, Inc.
    5  * All or some portions of this file are derived from material licensed
    6  * to the University of California by American Telephone and Telegraph
    7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
    8  * the permission of UNIX System Laboratories, Inc.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 4. Neither the name of the University nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  * Copyright (c) 1999 Michael Smith
   35  * All rights reserved.
   36  * Copyright (c) 1999 Poul-Henning Kamp
   37  * All rights reserved.
   38  *
   39  * Redistribution and use in source and binary forms, with or without
   40  * modification, are permitted provided that the following conditions
   41  * are met:
   42  * 1. Redistributions of source code must retain the above copyright
   43  *    notice, this list of conditions and the following disclaimer.
   44  * 2. Redistributions in binary form must reproduce the above copyright
   45  *    notice, this list of conditions and the following disclaimer in the
   46  *    documentation and/or other materials provided with the distribution.
   47  *
   48  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   58  * SUCH DAMAGE.
   59  */
   60 
   61 #include <sys/cdefs.h>
   62 __FBSDID("$FreeBSD$");
   63 
   64 #include <sys/param.h>
   65 #include <sys/conf.h>
   66 #include <sys/cons.h>
   67 #include <sys/jail.h>
   68 #include <sys/kernel.h>
   69 #include <sys/linker.h>
   70 #include <sys/mac.h>
   71 #include <sys/malloc.h>
   72 #include <sys/mount.h>
   73 #include <sys/mutex.h>
   74 #include <sys/namei.h>
   75 #include <sys/proc.h>
   76 #include <sys/filedesc.h>
   77 #include <sys/reboot.h>
   78 #include <sys/sysproto.h>
   79 #include <sys/sx.h>
   80 #include <sys/sysctl.h>
   81 #include <sys/sysent.h>
   82 #include <sys/systm.h>
   83 #include <sys/vnode.h>
   84 
   85 #include <geom/geom.h>
   86 
   87 #include <machine/stdarg.h>
   88 
   89 #include "opt_rootdevname.h"
   90 #include "opt_ddb.h"
   91 #include "opt_mac.h"
   92 
   93 #ifdef DDB
   94 #include <ddb/ddb.h>
   95 #endif
   96 
   97 #define ROOTNAME                "root_device"
   98 #define VFS_MOUNTARG_SIZE_MAX   (1024 * 64)
   99 
  100 static void     gets(char *cp);
  101 static int      vfs_domount(struct thread *td, const char *fstype,
  102                     char *fspath, int fsflags, void *fsdata, int compat);
  103 static int      vfs_mount_alloc(struct vnode *dvp, struct vfsconf *vfsp,
  104                     const char *fspath, struct thread *td, struct mount **mpp);
  105 static int      vfs_mountroot_ask(void);
  106 static int      vfs_mountroot_try(const char *mountfrom);
  107 static int      vfs_donmount(struct thread *td, int fsflags,
  108                     struct uio *fsoptions);
  109 
  110 static int      usermount = 0;
  111 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0,
  112     "Unprivileged users may mount and unmount file systems");
  113 
  114 MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount structure");
  115 
  116 /* List of mounted filesystems. */
  117 struct mntlist mountlist = TAILQ_HEAD_INITIALIZER(mountlist);
  118 
  119 /* For any iteration/modification of mountlist */
  120 struct mtx mountlist_mtx;
  121 
  122 /*
  123  * The vnode of the system's root (/ in the filesystem, without chroot
  124  * active.)
  125  */
  126 struct vnode    *rootvnode;
  127 
  128 /*
  129  * The root filesystem is detailed in the kernel environment variable
  130  * vfs.root.mountfrom, which is expected to be in the general format
  131  *
  132  * <vfsname>:[<path>]
  133  * vfsname   := the name of a VFS known to the kernel and capable
  134  *              of being mounted as root
  135  * path      := disk device name or other data used by the filesystem
  136  *              to locate its physical store
  137  */
  138 
  139 /*
  140  * The root specifiers we will try if RB_CDROM is specified.
  141  */
  142 static char *cdrom_rootdevnames[] = {
  143         "cd9660:cd0",
  144         "cd9660:acd0",
  145         NULL
  146 };
  147 
  148 /* legacy find-root code */
  149 char            *rootdevnames[2] = {NULL, NULL};
  150 struct cdev *rootdev = NULL;
  151 #ifdef ROOTDEVNAME
  152 const char      *ctrootdevname = ROOTDEVNAME;
  153 #else
  154 const char      *ctrootdevname = NULL;
  155 #endif
  156 
  157 /*
  158  * Has to be dynamic as the value of rootdev can change; however, it can't
  159  * change after the root is mounted, so a user process can't access this
  160  * sysctl until after the value is unchangeable.
  161  */
  162 static int
  163 sysctl_rootdev(SYSCTL_HANDLER_ARGS)
  164 {
  165         int error;
  166 
  167         /* _RD prevents this from happening. */
  168         KASSERT(req->newptr == NULL, ("Attempt to change root device name"));
  169 
  170         if (rootdev != NULL)
  171                 error = sysctl_handle_string(oidp, rootdev->si_name, 0, req);
  172         else
  173                 error = sysctl_handle_string(oidp, "", 0, req);
  174 
  175         return (error);
  176 }
  177 
  178 SYSCTL_PROC(_kern, OID_AUTO, rootdev, CTLTYPE_STRING | CTLFLAG_RD,
  179     0, 0, sysctl_rootdev, "A", "Root file system device");
  180 
  181 /* Remove one mount option. */
  182 static void
  183 vfs_freeopt(struct vfsoptlist *opts, struct vfsopt *opt)
  184 {
  185 
  186         TAILQ_REMOVE(opts, opt, link);
  187         free(opt->name, M_MOUNT);
  188         if (opt->value != NULL)
  189                 free(opt->value, M_MOUNT);
  190 #ifdef INVARIANTS
  191         else if (opt->len != 0)
  192                 panic("%s: mount option with NULL value but length != 0",
  193                     __func__);
  194 #endif
  195         free(opt, M_MOUNT);
  196 }
  197 
  198 /* Release all resources related to the mount options. */
  199 static void
  200 vfs_freeopts(struct vfsoptlist *opts)
  201 {
  202         struct vfsopt *opt;
  203 
  204         while (!TAILQ_EMPTY(opts)) {
  205                 opt = TAILQ_FIRST(opts);
  206                 vfs_freeopt(opts, opt);
  207         }
  208         free(opts, M_MOUNT);
  209 }
  210 
  211 /*
  212  * Check if options are equal (with or without the "no" prefix).
  213  */
  214 static int
  215 vfs_equalopts(const char *opt1, const char *opt2)
  216 {
  217 
  218         /* "opt" vs. "opt" or "noopt" vs. "noopt" */
  219         if (strcmp(opt1, opt2) == 0)
  220                 return (1);
  221         /* "noopt" vs. "opt" */
  222         if (strncmp(opt1, "no", 2) == 0 && strcmp(opt1 + 2, opt2) == 0)
  223                 return (1);
  224         /* "opt" vs. "noopt" */
  225         if (strncmp(opt2, "no", 2) == 0 && strcmp(opt1, opt2 + 2) == 0)
  226                 return (1);
  227         return (0);
  228 }
  229 
  230 /*
  231  * If a mount option is specified several times,
  232  * (with or without the "no" prefix) only keep
  233  * the last occurence of it.
  234  */
  235 static void
  236 vfs_sanitizeopts(struct vfsoptlist *opts)
  237 {
  238         struct vfsopt *opt, *opt2, *tmp;
  239 
  240         TAILQ_FOREACH_REVERSE(opt, opts, vfsoptlist, link) {
  241                 opt2 = TAILQ_PREV(opt, vfsoptlist, link);
  242                 while (opt2 != NULL) {
  243                         if (vfs_equalopts(opt->name, opt2->name)) {
  244                                 tmp = TAILQ_PREV(opt2, vfsoptlist, link);
  245                                 vfs_freeopt(opts, opt2);
  246                                 opt2 = tmp;
  247                         } else {
  248                                 opt2 = TAILQ_PREV(opt2, vfsoptlist, link);
  249                         }
  250                 }
  251         }
  252 }
  253 
  254 /*
  255  * Build a linked list of mount options from a struct uio.
  256  */
  257 static int
  258 vfs_buildopts(struct uio *auio, struct vfsoptlist **options)
  259 {
  260         struct vfsoptlist *opts;
  261         struct vfsopt *opt;
  262         size_t memused;
  263         unsigned int i, iovcnt;
  264         int error, namelen, optlen;
  265 
  266         opts = malloc(sizeof(struct vfsoptlist), M_MOUNT, M_WAITOK);
  267         TAILQ_INIT(opts);
  268         memused = 0;
  269         iovcnt = auio->uio_iovcnt;
  270         for (i = 0; i < iovcnt; i += 2) {
  271                 opt = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK);
  272                 namelen = auio->uio_iov[i].iov_len;
  273                 optlen = auio->uio_iov[i + 1].iov_len;
  274                 opt->name = malloc(namelen, M_MOUNT, M_WAITOK);
  275                 opt->value = NULL;
  276                 opt->len = optlen;
  277 
  278                 /*
  279                  * Do this early, so jumps to "bad" will free the current
  280                  * option.
  281                  */
  282                 TAILQ_INSERT_TAIL(opts, opt, link);
  283                 memused += sizeof(struct vfsopt) + optlen + namelen;
  284 
  285                 /*
  286                  * Avoid consuming too much memory, and attempts to overflow
  287                  * memused.
  288                  */
  289                 if (memused > VFS_MOUNTARG_SIZE_MAX ||
  290                     optlen > VFS_MOUNTARG_SIZE_MAX ||
  291                     namelen > VFS_MOUNTARG_SIZE_MAX) {
  292                         error = EINVAL;
  293                         goto bad;
  294                 }
  295 
  296                 if (auio->uio_segflg == UIO_SYSSPACE) {
  297                         bcopy(auio->uio_iov[i].iov_base, opt->name, namelen);
  298                 } else {
  299                         error = copyin(auio->uio_iov[i].iov_base, opt->name,
  300                             namelen);
  301                         if (error)
  302                                 goto bad;
  303                 }
  304                 /* Ensure names are null-terminated strings. */
  305                 if (opt->name[namelen - 1] != '\0') {
  306                         error = EINVAL;
  307                         goto bad;
  308                 }
  309                 if (optlen != 0) {
  310                         opt->value = malloc(optlen, M_MOUNT, M_WAITOK);
  311                         if (auio->uio_segflg == UIO_SYSSPACE) {
  312                                 bcopy(auio->uio_iov[i + 1].iov_base, opt->value,
  313                                     optlen);
  314                         } else {
  315                                 error = copyin(auio->uio_iov[i + 1].iov_base,
  316                                     opt->value, optlen);
  317                                 if (error)
  318                                         goto bad;
  319                         }
  320                 }
  321         }
  322         vfs_sanitizeopts(opts);
  323         *options = opts;
  324         return (0);
  325 bad:
  326         vfs_freeopts(opts);
  327         return (error);
  328 }
  329 
  330 /*
  331  * Merge the old mount options with the new ones passed
  332  * in the MNT_UPDATE case.
  333  */
  334 static void
  335 vfs_mergeopts(struct vfsoptlist *toopts, struct vfsoptlist *opts)
  336 {
  337         struct vfsopt *opt, *opt2, *new;
  338 
  339         TAILQ_FOREACH(opt, opts, link) {
  340                 /*
  341                  * Check that this option hasn't been redefined
  342                  * nor cancelled with a "no" mount option.
  343                  */
  344                 opt2 = TAILQ_FIRST(toopts);
  345                 while (opt2 != NULL) {
  346                         if (strcmp(opt2->name, opt->name) == 0)
  347                                 goto next;
  348                         if (strncmp(opt2->name, "no", 2) == 0 &&
  349                             strcmp(opt2->name + 2, opt->name) == 0) {
  350                                 vfs_freeopt(toopts, opt2);
  351                                 goto next;
  352                         }
  353                         opt2 = TAILQ_NEXT(opt2, link);
  354                 }
  355                 /* We want this option, duplicate it. */
  356                 new = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK);
  357                 new->name = malloc(strlen(opt->name) + 1, M_MOUNT, M_WAITOK);
  358                 strcpy(new->name, opt->name);
  359                 if (opt->len != 0) {
  360                         new->value = malloc(opt->len, M_MOUNT, M_WAITOK);
  361                         bcopy(opt->value, new->value, opt->len);
  362                 } else {
  363                         new->value = NULL;
  364                 }
  365                 new->len = opt->len;
  366                 TAILQ_INSERT_TAIL(toopts, new, link);
  367 next:
  368                 continue;
  369         }
  370 }
  371 
  372 /*
  373  * New mount API.
  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         iovcnt = uap->iovcnt;
  391         /*
  392          * Check that we have an even number of iovec's
  393          * and that we have at least two options.
  394          */
  395         if ((iovcnt & 1) || (iovcnt < 4))
  396                 return (EINVAL);
  397         error = copyinuio(uap->iovp, iovcnt, &auio);
  398         if (error)
  399                 return (error);
  400         iov = auio->uio_iov;
  401         for (i = 0; i < iovcnt; i++) {
  402                 if (iov->iov_len > MMAXOPTIONLEN) {
  403                         free(auio, M_IOV);
  404                         return (EINVAL);
  405                 }
  406                 iov++;
  407         }
  408         error = vfs_donmount(td, uap->flags, auio);
  409         free(auio, M_IOV);
  410         return (error);
  411 }
  412 
  413 int
  414 kernel_mount(struct iovec *iovp, u_int iovcnt, int flags)
  415 {
  416         struct uio auio;
  417         int error;
  418 
  419         /*
  420          * Check that we have an even number of iovec's
  421          * and that we have at least two options.
  422          */
  423         if ((iovcnt & 1) || (iovcnt < 4))
  424                 return (EINVAL);
  425 
  426         auio.uio_iov = iovp;
  427         auio.uio_iovcnt = iovcnt;
  428         auio.uio_segflg = UIO_SYSSPACE;
  429 
  430         error = vfs_donmount(curthread, flags, &auio);
  431         return (error);
  432 }
  433 
  434 int
  435 kernel_vmount(int flags, ...)
  436 {
  437         struct iovec *iovp;
  438         struct uio auio;
  439         va_list ap;
  440         u_int iovcnt, iovlen, len;
  441         const char *cp;
  442         char *buf, *pos;
  443         size_t n;
  444         int error, i;
  445 
  446         len = 0;
  447         va_start(ap, flags);
  448         for (iovcnt = 0; (cp = va_arg(ap, const char *)) != NULL; iovcnt++)
  449                 len += strlen(cp) + 1;
  450         va_end(ap);
  451 
  452         if (iovcnt < 4 || iovcnt & 1)
  453                 return (EINVAL);
  454 
  455         iovlen = iovcnt * sizeof (struct iovec);
  456         MALLOC(iovp, struct iovec *, iovlen, M_MOUNT, M_WAITOK);
  457         MALLOC(buf, char *, len, M_MOUNT, M_WAITOK);
  458         pos = buf;
  459         va_start(ap, flags);
  460         for (i = 0; i < iovcnt; i++) {
  461                 cp = va_arg(ap, const char *);
  462                 copystr(cp, pos, len - (pos - buf), &n);
  463                 iovp[i].iov_base = pos;
  464                 iovp[i].iov_len = n;
  465                 pos += n;
  466         }
  467         va_end(ap);
  468 
  469         auio.uio_iov = iovp;
  470         auio.uio_iovcnt = iovcnt;
  471         auio.uio_segflg = UIO_SYSSPACE;
  472 
  473         error = vfs_donmount(curthread, flags, &auio);
  474         FREE(iovp, M_MOUNT);
  475         FREE(buf, M_MOUNT);
  476         return (error);
  477 }
  478 
  479 /*
  480  * Allocate and initialize the mount point struct.
  481  */
  482 static int
  483 vfs_mount_alloc(struct vnode *vp, struct vfsconf *vfsp,
  484     const char *fspath, struct thread *td, struct mount **mpp)
  485 {
  486         struct mount *mp;
  487 
  488         mp = malloc(sizeof(struct mount), M_MOUNT, M_WAITOK | M_ZERO);
  489         TAILQ_INIT(&mp->mnt_nvnodelist);
  490         mp->mnt_nvnodelistsize = 0;
  491         mtx_init(&mp->mnt_mtx, "struct mount mtx", NULL, MTX_DEF);
  492         lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, LK_NOPAUSE);
  493         vfs_busy(mp, LK_NOWAIT, 0, td);
  494         mp->mnt_op = vfsp->vfc_vfsops;
  495         mp->mnt_vfc = vfsp;
  496         vfsp->vfc_refcount++;
  497         mp->mnt_stat.f_type = vfsp->vfc_typenum;
  498         mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
  499         strlcpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
  500         mp->mnt_vnodecovered = vp;
  501         mp->mnt_cred = crdup(td->td_ucred);
  502         mp->mnt_stat.f_owner = td->td_ucred->cr_uid;
  503         strlcpy(mp->mnt_stat.f_mntonname, fspath, MNAMELEN);
  504         mp->mnt_iosize_max = DFLTPHYS;
  505 #ifdef MAC
  506         mac_init_mount(mp);
  507         mac_create_mount(td->td_ucred, mp);
  508 #endif
  509         *mpp = mp;
  510         return (0);
  511 }
  512 
  513 /*
  514  * Destroy the mount struct previously allocated by vfs_mount_alloc().
  515  */
  516 void
  517 vfs_mount_destroy(struct mount *mp, struct thread *td)
  518 {
  519 
  520         mp->mnt_vfc->vfc_refcount--;
  521         if (!TAILQ_EMPTY(&mp->mnt_nvnodelist))
  522                 panic("unmount: dangling vnode");
  523         vfs_unbusy(mp,td);
  524         lockdestroy(&mp->mnt_lock);
  525         mtx_destroy(&mp->mnt_mtx);
  526         if (mp->mnt_kern_flag & MNTK_MWAIT)
  527                 wakeup(mp);
  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          * Be ultra-paranoid about making sure the type and fspath
  568          * variables will fit in our mp buffers, including the
  569          * terminating NUL.
  570          */
  571         if (fstypelen >= MFSNAMELEN - 1 || fspathlen >= MNAMELEN - 1) {
  572                 error = ENAMETOOLONG;
  573                 goto bail;
  574         }
  575 
  576         error = vfs_domount(td, fstype, fspath, fsflags, optlist, 0);
  577 bail:
  578         if (error)
  579                 vfs_freeopts(optlist);
  580         return (error);
  581 }
  582 
  583 /*
  584  * Old mount API.
  585  */
  586 #ifndef _SYS_SYSPROTO_H_
  587 struct mount_args {
  588         char    *type;
  589         char    *path;
  590         int     flags;
  591         caddr_t data;
  592 };
  593 #endif
  594 /* ARGSUSED */
  595 int
  596 mount(td, uap)
  597         struct thread *td;
  598         struct mount_args /* {
  599                 char *type;
  600                 char *path;
  601                 int flags;
  602                 caddr_t data;
  603         } */ *uap;
  604 {
  605         char *fstype;
  606         char *fspath;
  607         int error;
  608 
  609         fstype = malloc(MFSNAMELEN, M_TEMP, M_WAITOK);
  610         fspath = malloc(MNAMELEN, M_TEMP, M_WAITOK);
  611 
  612         /*
  613          * vfs_mount() actually takes a kernel string for `type' and
  614          * `path' now, so extract them.
  615          */
  616         error = copyinstr(uap->type, fstype, MFSNAMELEN, NULL);
  617         if (error == 0)
  618                 error = copyinstr(uap->path, fspath, MNAMELEN, NULL);
  619         if (error == 0)
  620                 error = vfs_domount(td, fstype, fspath, uap->flags,
  621                     uap->data, 1);
  622         free(fstype, M_TEMP);
  623         free(fspath, M_TEMP);
  624         return (error);
  625 }
  626 
  627 /*
  628  * vfs_mount(): actually attempt a filesystem mount.
  629  *
  630  * This routine is designed to be a "generic" entry point for routines
  631  * that wish to mount a filesystem. All parameters except `fsdata' are
  632  * pointers into kernel space. `fsdata' is currently still a pointer
  633  * into userspace.
  634  */
  635 int
  636 vfs_mount(td, fstype, fspath, fsflags, fsdata)
  637         struct thread *td;
  638         const char *fstype;
  639         char *fspath;
  640         int fsflags;
  641         void *fsdata;
  642 {
  643 
  644         return (vfs_domount(td, fstype, fspath, fsflags, fsdata, 1));
  645 }
  646 
  647 /*
  648  * vfs_domount(): actually attempt a filesystem mount.
  649  */
  650 static int
  651 vfs_domount(
  652         struct thread *td,      /* Flags common to all filesystems. */
  653         const char *fstype,     /* Filesystem type. */
  654         char *fspath,           /* Mount path. */
  655         int fsflags,            /* Flags common to all filesystems. */
  656         void *fsdata,           /* Options local to the filesystem. */
  657         int compat              /* Invocation from compat syscall. */
  658         )
  659 {
  660         linker_file_t lf;
  661         struct vnode *vp;
  662         struct mount *mp;
  663         struct vfsconf *vfsp;
  664         int error, flag = 0, kern_flag = 0;
  665         struct vattr va;
  666         struct nameidata nd;
  667 
  668         /*
  669          * Be ultra-paranoid about making sure the type and fspath
  670          * variables will fit in our mp buffers, including the
  671          * terminating NUL.
  672          */
  673         if (strlen(fstype) >= MFSNAMELEN || strlen(fspath) >= MNAMELEN)
  674                 return (ENAMETOOLONG);
  675 
  676         if (jailed(td->td_ucred))
  677                 return (EPERM);
  678         if (usermount == 0) {
  679                 if ((error = suser(td)) != 0)
  680                         return (error);
  681         }
  682 
  683         /*
  684          * Do not allow NFS export or MNT_SUIDDIR by unprivileged users.
  685          */
  686         if (fsflags & (MNT_EXPORTED | MNT_SUIDDIR)) {
  687                 if ((error = suser(td)) != 0)
  688                         return (error);
  689         }
  690         /*
  691          * Silently enforce MNT_NODEV, MNT_NOSUID and MNT_USER for
  692          * unprivileged users.
  693          */
  694         if (suser(td) != 0)
  695                 fsflags |= MNT_NODEV | MNT_NOSUID | MNT_USER;
  696         /*
  697          * Get vnode to be covered
  698          */
  699         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspath, td);
  700         if ((error = namei(&nd)) != 0)
  701                 return (error);
  702         NDFREE(&nd, NDF_ONLY_PNBUF);
  703         vp = nd.ni_vp;
  704         if (fsflags & MNT_UPDATE) {
  705                 if ((vp->v_vflag & VV_ROOT) == 0) {
  706                         vput(vp);
  707                         return (EINVAL);
  708                 }
  709                 mp = vp->v_mount;
  710                 flag = mp->mnt_flag;
  711                 kern_flag = mp->mnt_kern_flag;
  712                 /*
  713                  * We only allow the filesystem to be reloaded if it
  714                  * is currently mounted read-only.
  715                  */
  716                 if ((fsflags & MNT_RELOAD) &&
  717                     ((mp->mnt_flag & MNT_RDONLY) == 0)) {
  718                         vput(vp);
  719                         return (EOPNOTSUPP);    /* Needs translation */
  720                 }
  721                 /*
  722                  * Only privileged root, or (if MNT_USER is set) the user that
  723                  * did the original mount is permitted to update it.
  724                  */
  725                 error = vfs_suser(mp, td);
  726                 if (error) {
  727                         vput(vp);
  728                         return (error);
  729                 }
  730                 if (vfs_busy(mp, LK_NOWAIT, 0, td)) {
  731                         vput(vp);
  732                         return (EBUSY);
  733                 }
  734                 VI_LOCK(vp);
  735                 if ((vp->v_iflag & VI_MOUNT) != 0 ||
  736                     vp->v_mountedhere != NULL) {
  737                         VI_UNLOCK(vp);
  738                         vfs_unbusy(mp, td);
  739                         vput(vp);
  740                         return (EBUSY);
  741                 }
  742                 vp->v_iflag |= VI_MOUNT;
  743                 VI_UNLOCK(vp);
  744                 mp->mnt_flag |= fsflags &
  745                     (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_SNAPSHOT);
  746                 VOP_UNLOCK(vp, 0, td);
  747                 if (compat == 0) {
  748                         mp->mnt_optnew = fsdata;
  749                         vfs_mergeopts(mp->mnt_optnew, mp->mnt_opt);
  750                 }
  751         } else {
  752                 /*
  753                  * If the user is not root, ensure that they own the directory
  754                  * onto which we are attempting to mount.
  755                  */
  756                 error = VOP_GETATTR(vp, &va, td->td_ucred, td);
  757                 if (error) {
  758                         vput(vp);
  759                         return (error);
  760                 }
  761                 if (va.va_uid != td->td_ucred->cr_uid) {
  762                         if ((error = suser(td)) != 0) {
  763                                 vput(vp);
  764                                 return (error);
  765                         }
  766                 }
  767                 if ((error = vinvalbuf(vp, V_SAVE, td->td_ucred, td, 0, 0)) != 0) {
  768                         vput(vp);
  769                         return (error);
  770                 }
  771                 if (vp->v_type != VDIR) {
  772                         vput(vp);
  773                         return (ENOTDIR);
  774                 }
  775                 vfsp = vfs_byname(fstype);
  776                 if (vfsp == NULL) {
  777                         /* Only load modules for root (very important!). */
  778                         if ((error = suser(td)) != 0) {
  779                                 vput(vp);
  780                                 return (error);
  781                         }
  782                         error = securelevel_gt(td->td_ucred, 0);
  783                         if (error) {
  784                                 vput(vp);
  785                                 return (error);
  786                         }
  787                         error = linker_load_module(NULL, fstype, NULL, NULL, &lf);
  788                         if (error || lf == NULL) {
  789                                 vput(vp);
  790                                 if (lf == NULL)
  791                                         error = ENODEV;
  792                                 return (error);
  793                         }
  794                         lf->userrefs++;
  795                         /* Look up again to see if the VFS was loaded. */
  796                         vfsp = vfs_byname(fstype);
  797                         if (vfsp == NULL) {
  798                                 lf->userrefs--;
  799                                 linker_file_unload(lf, LINKER_UNLOAD_FORCE);
  800                                 vput(vp);
  801                                 return (ENODEV);
  802                         }
  803                 }
  804                 VI_LOCK(vp);
  805                 if ((vp->v_iflag & VI_MOUNT) != 0 ||
  806                     vp->v_mountedhere != NULL) {
  807                         VI_UNLOCK(vp);
  808                         vput(vp);
  809                         return (EBUSY);
  810                 }
  811                 vp->v_iflag |= VI_MOUNT;
  812                 VI_UNLOCK(vp);
  813 
  814                 /*
  815                  * Allocate and initialize the filesystem.
  816                  */
  817                 error = vfs_mount_alloc(vp, vfsp, fspath, td, &mp);
  818                 if (error) {
  819                         vput(vp);
  820                         return (error);
  821                 }
  822                 VOP_UNLOCK(vp, 0, td);
  823 
  824                 /* XXXMAC: pass to vfs_mount_alloc? */
  825                 if (compat == 0)
  826                         mp->mnt_optnew = fsdata;
  827         }
  828         /*
  829          * Check if the fs implements the type VFS_[O]MOUNT()
  830          * function we are looking for.
  831          */
  832         if ((compat == 0) == (mp->mnt_op->vfs_omount != NULL)) {
  833                 printf("%s doesn't support the %s mount syscall\n",
  834                     mp->mnt_vfc->vfc_name, compat ? "old" : "new");
  835                 VI_LOCK(vp);
  836                 vp->v_iflag &= ~VI_MOUNT;
  837                 VI_UNLOCK(vp);
  838                 if (mp->mnt_flag & MNT_UPDATE)
  839                         vfs_unbusy(mp, td);
  840                 else
  841                         vfs_mount_destroy(mp, td);
  842                 vrele(vp);
  843                 return (EOPNOTSUPP);
  844         }
  845 
  846         /*
  847          * Set the mount level flags.
  848          */
  849         if (fsflags & MNT_RDONLY)
  850                 mp->mnt_flag |= MNT_RDONLY;
  851         else if (mp->mnt_flag & MNT_RDONLY)
  852                 mp->mnt_kern_flag |= MNTK_WANTRDWR;
  853         mp->mnt_flag &=~ MNT_UPDATEMASK;
  854         mp->mnt_flag |= fsflags & (MNT_UPDATEMASK | MNT_FORCE);
  855         /*
  856          * Mount the filesystem.
  857          * XXX The final recipients of VFS_MOUNT just overwrite the ndp they
  858          * get.  No freeing of cn_pnbuf.
  859          */
  860         if (compat)
  861             error = VFS_OMOUNT(mp, fspath, fsdata, td);
  862         else
  863             error = VFS_MOUNT(mp, td);
  864         if (!error) {
  865                 if (mp->mnt_opt != NULL)
  866                         vfs_freeopts(mp->mnt_opt);
  867                 mp->mnt_opt = mp->mnt_optnew;
  868         }
  869         /*
  870          * Prevent external consumers of mount options from reading
  871          * mnt_optnew.
  872         */
  873         mp->mnt_optnew = NULL;
  874         if (mp->mnt_flag & MNT_UPDATE) {
  875                 if (mp->mnt_kern_flag & MNTK_WANTRDWR)
  876                         mp->mnt_flag &= ~MNT_RDONLY;
  877                 mp->mnt_flag &=
  878                     ~(MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_SNAPSHOT);
  879                 mp->mnt_kern_flag &= ~MNTK_WANTRDWR;
  880                 if (error) {
  881                         mp->mnt_flag = flag;
  882                         mp->mnt_kern_flag = kern_flag;
  883                 }
  884                 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
  885                         if (mp->mnt_syncer == NULL)
  886                                 error = vfs_allocate_syncvnode(mp);
  887                 } else {
  888                         if (mp->mnt_syncer != NULL)
  889                                 vrele(mp->mnt_syncer);
  890                         mp->mnt_syncer = NULL;
  891                 }
  892                 vfs_unbusy(mp, td);
  893                 VI_LOCK(vp);
  894                 vp->v_iflag &= ~VI_MOUNT;
  895                 VI_UNLOCK(vp);
  896                 vrele(vp);
  897                 return (error);
  898         }
  899         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  900         /*
  901          * Put the new filesystem on the mount list after root.
  902          */
  903         cache_purge(vp);
  904         if (!error) {
  905                 struct vnode *newdp;
  906 
  907                 VI_LOCK(vp);
  908                 vp->v_iflag &= ~VI_MOUNT;
  909                 VI_UNLOCK(vp);
  910                 vp->v_mountedhere = mp;
  911                 mtx_lock(&mountlist_mtx);
  912                 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
  913                 mtx_unlock(&mountlist_mtx);
  914                 vfs_event_signal(NULL, VQ_MOUNT, 0);
  915                 if (VFS_ROOT(mp, &newdp, td))
  916                         panic("mount: lost mount");
  917                 mountcheckdirs(vp, newdp);
  918                 vput(newdp);
  919                 VOP_UNLOCK(vp, 0, td);
  920                 if ((mp->mnt_flag & MNT_RDONLY) == 0)
  921                         error = vfs_allocate_syncvnode(mp);
  922                 vfs_unbusy(mp, td);
  923                 if (error || (error = VFS_START(mp, 0, td)) != 0)
  924                         vrele(vp);
  925         } else {
  926                 VI_LOCK(vp);
  927                 vp->v_iflag &= ~VI_MOUNT;
  928                 VI_UNLOCK(vp);
  929                 vfs_mount_destroy(mp, td);
  930                 vput(vp);
  931         }
  932         return (error);
  933 }
  934 
  935 /*
  936  * Unmount a filesystem.
  937  *
  938  * Note: unmount takes a path to the vnode mounted on as argument,
  939  * not special file (as before).
  940  */
  941 #ifndef _SYS_SYSPROTO_H_
  942 struct unmount_args {
  943         char    *path;
  944         int     flags;
  945 };
  946 #endif
  947 /* ARGSUSED */
  948 int
  949 unmount(td, uap)
  950         struct thread *td;
  951         register struct unmount_args /* {
  952                 char *path;
  953                 int flags;
  954         } */ *uap;
  955 {
  956         struct mount *mp;
  957         char *pathbuf;
  958         int error, id0, id1;
  959 
  960         if (jailed(td->td_ucred))
  961                 return (EPERM);
  962         if (usermount == 0) {
  963                 if ((error = suser(td)) != 0)
  964                         return (error);
  965         }
  966 
  967         pathbuf = malloc(MNAMELEN, M_TEMP, M_WAITOK);
  968         error = copyinstr(uap->path, pathbuf, MNAMELEN, NULL);
  969         if (error) {
  970                 free(pathbuf, M_TEMP);
  971                 return (error);
  972         }
  973         if (uap->flags & MNT_BYFSID) {
  974                 /* Decode the filesystem ID. */
  975                 if (sscanf(pathbuf, "FSID:%d:%d", &id0, &id1) != 2) {
  976                         free(pathbuf, M_TEMP);
  977                         return (EINVAL);
  978                 }
  979 
  980                 mtx_lock(&mountlist_mtx);
  981                 TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) {
  982                         if (mp->mnt_stat.f_fsid.val[0] == id0 &&
  983                             mp->mnt_stat.f_fsid.val[1] == id1)
  984                                 break;
  985                 }
  986                 mtx_unlock(&mountlist_mtx);
  987         } else {
  988                 mtx_lock(&mountlist_mtx);
  989                 TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) {
  990                         if (strcmp(mp->mnt_stat.f_mntonname, pathbuf) == 0)
  991                                 break;
  992                 }
  993                 mtx_unlock(&mountlist_mtx);
  994         }
  995         free(pathbuf, M_TEMP);
  996         if (mp == NULL) {
  997                 /*
  998                  * Previously we returned ENOENT for a nonexistent path and
  999                  * EINVAL for a non-mountpoint.  We cannot tell these apart
 1000                  * now, so in the !MNT_BYFSID case return the more likely
 1001                  * EINVAL for compatibility.
 1002                  */
 1003                 return ((uap->flags & MNT_BYFSID) ? ENOENT : EINVAL);
 1004         }
 1005 
 1006         /*
 1007          * Only privileged root, or (if MNT_USER is set) the user that did the
 1008          * original mount is permitted to unmount this filesystem.
 1009          */
 1010         error = vfs_suser(mp, td);
 1011         if (error)
 1012                 return (error);
 1013 
 1014         /*
 1015          * Don't allow unmounting the root filesystem.
 1016          */
 1017         if (mp->mnt_flag & MNT_ROOTFS)
 1018                 return (EINVAL);
 1019         return (dounmount(mp, uap->flags, td));
 1020 }
 1021 
 1022 /*
 1023  * Do the actual filesystem unmount.
 1024  */
 1025 int
 1026 dounmount(mp, flags, td)
 1027         struct mount *mp;
 1028         int flags;
 1029         struct thread *td;
 1030 {
 1031         struct vnode *coveredvp, *fsrootvp;
 1032         int error;
 1033         int async_flag;
 1034 
 1035         mtx_lock(&mountlist_mtx);
 1036         if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
 1037                 mtx_unlock(&mountlist_mtx);
 1038                 return (EBUSY);
 1039         }
 1040         mp->mnt_kern_flag |= MNTK_UNMOUNT;
 1041         /* Allow filesystems to detect that a forced unmount is in progress. */
 1042         if (flags & MNT_FORCE)
 1043                 mp->mnt_kern_flag |= MNTK_UNMOUNTF;
 1044         error = lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK |
 1045             ((flags & MNT_FORCE) ? 0 : LK_NOWAIT), &mountlist_mtx, td);
 1046         if (error) {
 1047                 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
 1048                 if (mp->mnt_kern_flag & MNTK_MWAIT)
 1049                         wakeup(mp);
 1050                 return (error);
 1051         }
 1052         vn_start_write(NULL, &mp, V_WAIT);
 1053 
 1054         if (mp->mnt_flag & MNT_EXPUBLIC)
 1055                 vfs_setpublicfs(NULL, NULL, NULL);
 1056 
 1057         vfs_msync(mp, MNT_WAIT);
 1058         async_flag = mp->mnt_flag & MNT_ASYNC;
 1059         mp->mnt_flag &= ~MNT_ASYNC;
 1060         cache_purgevfs(mp);     /* remove cache entries for this file sys */
 1061         if (mp->mnt_syncer != NULL)
 1062                 vrele(mp->mnt_syncer);
 1063         /*
 1064          * For forced unmounts, move process cdir/rdir refs on the fs root
 1065          * vnode to the covered vnode.  For non-forced unmounts we want
 1066          * such references to cause an EBUSY error.
 1067          */
 1068         if ((flags & MNT_FORCE) && VFS_ROOT(mp, &fsrootvp, td) == 0) {
 1069                 if (mp->mnt_vnodecovered != NULL)
 1070                         mountcheckdirs(fsrootvp, mp->mnt_vnodecovered);
 1071                 if (fsrootvp == rootvnode) {
 1072                         vrele(rootvnode);
 1073                         rootvnode = NULL;
 1074                 }
 1075                 vput(fsrootvp);
 1076         }
 1077         if (((mp->mnt_flag & MNT_RDONLY) ||
 1078              (error = VFS_SYNC(mp, MNT_WAIT, td->td_ucred, td)) == 0) ||
 1079             (flags & MNT_FORCE)) {
 1080                 error = VFS_UNMOUNT(mp, flags, td);
 1081         }
 1082         vn_finished_write(mp);
 1083         if (error) {
 1084                 /* Undo cdir/rdir and rootvnode changes made above. */
 1085                 if ((flags & MNT_FORCE) && VFS_ROOT(mp, &fsrootvp, td) == 0) {
 1086                         if (mp->mnt_vnodecovered != NULL)
 1087                                 mountcheckdirs(mp->mnt_vnodecovered, fsrootvp);
 1088                         if (rootvnode == NULL) {
 1089                                 rootvnode = fsrootvp;
 1090                                 vref(rootvnode);
 1091                         }
 1092                         vput(fsrootvp);
 1093                 }
 1094                 if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL)
 1095                         (void) vfs_allocate_syncvnode(mp);
 1096                 mtx_lock(&mountlist_mtx);
 1097                 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
 1098                 mp->mnt_flag |= async_flag;
 1099                 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK,
 1100                     &mountlist_mtx, td);
 1101                 if (mp->mnt_kern_flag & MNTK_MWAIT)
 1102                         wakeup(mp);
 1103                 return (error);
 1104         }
 1105         mtx_lock(&mountlist_mtx);
 1106         TAILQ_REMOVE(&mountlist, mp, mnt_list);
 1107         if ((coveredvp = mp->mnt_vnodecovered) != NULL)
 1108                 coveredvp->v_mountedhere = NULL;
 1109         mtx_unlock(&mountlist_mtx);
 1110         vfs_event_signal(NULL, VQ_UNMOUNT, 0);
 1111         vfs_mount_destroy(mp, td);
 1112         if (coveredvp != NULL)
 1113                 vrele(coveredvp);
 1114         return (0);
 1115 }
 1116 
 1117 /*
 1118  * Lookup a filesystem type, and if found allocate and initialize
 1119  * a mount structure for it.
 1120  *
 1121  * Devname is usually updated by mount(8) after booting.
 1122  */
 1123 int
 1124 vfs_rootmountalloc(fstypename, devname, mpp)
 1125         char *fstypename;
 1126         char *devname;
 1127         struct mount **mpp;
 1128 {
 1129         struct thread *td = curthread;  /* XXX */
 1130         struct vfsconf *vfsp;
 1131         struct mount *mp;
 1132         int error;
 1133 
 1134         if (fstypename == NULL)
 1135                 return (ENODEV);
 1136         vfsp = vfs_byname(fstypename);
 1137         if (vfsp == NULL)
 1138                 return (ENODEV);
 1139         error = vfs_mount_alloc(NULLVP, vfsp, "/", td, &mp);
 1140         if (error)
 1141                 return (error);
 1142         mp->mnt_flag |= MNT_RDONLY | MNT_ROOTFS;
 1143         strlcpy(mp->mnt_stat.f_mntfromname, devname, MNAMELEN);
 1144         *mpp = mp;
 1145         return (0);
 1146 }
 1147 
 1148 /*
 1149  * Find and mount the root filesystem
 1150  */
 1151 void
 1152 vfs_mountroot(void)
 1153 {
 1154         char *cp;
 1155         int error, i, asked = 0;
 1156 
 1157 
 1158         /*
 1159          * Wait for GEOM to settle down
 1160          */
 1161         DROP_GIANT();
 1162         g_waitidle();
 1163         PICKUP_GIANT();
 1164 
 1165         /*
 1166          * We are booted with instructions to prompt for the root filesystem.
 1167          */
 1168         if (boothowto & RB_ASKNAME) {
 1169                 if (!vfs_mountroot_ask())
 1170                         return;
 1171                 asked = 1;
 1172         }
 1173 
 1174         /*
 1175          * The root filesystem information is compiled in, and we are
 1176          * booted with instructions to use it.
 1177          */
 1178         if (ctrootdevname != NULL && (boothowto & RB_DFLTROOT)) {
 1179                 if (!vfs_mountroot_try(ctrootdevname))
 1180                         return;
 1181                 ctrootdevname = NULL;
 1182         }
 1183 
 1184         /*
 1185          * We've been given the generic "use CDROM as root" flag.  This is
 1186          * necessary because one media may be used in many different
 1187          * devices, so we need to search for them.
 1188          */
 1189         if (boothowto & RB_CDROM) {
 1190                 for (i = 0; cdrom_rootdevnames[i] != NULL; i++) {
 1191                         if (!vfs_mountroot_try(cdrom_rootdevnames[i]))
 1192                                 return;
 1193                 }
 1194         }
 1195 
 1196         /*
 1197          * Try to use the value read by the loader from /etc/fstab, or
 1198          * supplied via some other means.  This is the preferred
 1199          * mechanism.
 1200          */
 1201         cp = getenv("vfs.root.mountfrom");
 1202         if (cp != NULL) {
 1203                 error = vfs_mountroot_try(cp);
 1204                 freeenv(cp);
 1205                 if (!error)
 1206                         return;
 1207         }
 1208 
 1209         /*
 1210          * Try values that may have been computed by code during boot
 1211          */
 1212         if (!vfs_mountroot_try(rootdevnames[0]))
 1213                 return;
 1214         if (!vfs_mountroot_try(rootdevnames[1]))
 1215                 return;
 1216 
 1217         /*
 1218          * If we (still) have a compiled-in default, try it.
 1219          */
 1220         if (ctrootdevname != NULL)
 1221                 if (!vfs_mountroot_try(ctrootdevname))
 1222                         return;
 1223 
 1224         /*
 1225          * Everything so far has failed, prompt on the console if we haven't
 1226          * already tried that.
 1227          */
 1228         if (!asked)
 1229                 if (!vfs_mountroot_ask())
 1230                         return;
 1231         panic("Root mount failed, startup aborted.");
 1232 }
 1233 
 1234 /*
 1235  * Mount (mountfrom) as the root filesystem.
 1236  */
 1237 static int
 1238 vfs_mountroot_try(const char *mountfrom)
 1239 {
 1240         struct mount    *mp;
 1241         char            *vfsname, *path;
 1242         const char      *devname;
 1243         int             error;
 1244         char            patt[32];
 1245         int             s;
 1246 
 1247         vfsname = NULL;
 1248         path    = NULL;
 1249         mp      = NULL;
 1250         error   = EINVAL;
 1251 
 1252         if (mountfrom == NULL)
 1253                 return (error);         /* don't complain */
 1254 
 1255         s = splcam();                   /* Overkill, but annoying without it */
 1256         printf("Mounting root from %s\n", mountfrom);
 1257         splx(s);
 1258 
 1259         /* parse vfs name and path */
 1260         vfsname = malloc(MFSNAMELEN, M_MOUNT, M_WAITOK);
 1261         path = malloc(MNAMELEN, M_MOUNT, M_WAITOK);
 1262         vfsname[0] = path[0] = 0;
 1263         sprintf(patt, "%%%d[a-z0-9]:%%%ds", MFSNAMELEN, MNAMELEN);
 1264         if (sscanf(mountfrom, patt, vfsname, path) < 1)
 1265                 goto done;
 1266 
 1267         /* allocate a root mount */
 1268         error = vfs_rootmountalloc(vfsname, path[0] != 0 ? path : ROOTNAME,
 1269             &mp);
 1270         if (error != 0) {
 1271                 printf("Can't allocate root mount for filesystem '%s': %d\n",
 1272                        vfsname, error);
 1273                 goto done;
 1274         }
 1275 
 1276         /*
 1277          * do our best to set rootdev
 1278          * XXX: This does not belong here!
 1279          */
 1280         if (path[0] != '\0') {
 1281                 struct cdev *diskdev;
 1282                 diskdev = getdiskbyname(path);
 1283                 if (diskdev != NULL)
 1284                         rootdev = diskdev;
 1285                 else
 1286                         printf("setrootbyname failed\n");
 1287         }
 1288 
 1289         /* If the root device is a type "memory disk", mount RW */
 1290         if (rootdev != NULL && devsw(rootdev) != NULL) {
 1291                 devname = devtoname(rootdev);
 1292                 if (devname[0] == 'm' && devname[1] == 'd')
 1293                         mp->mnt_flag &= ~MNT_RDONLY;
 1294         }
 1295 
 1296         error = VFS_OMOUNT(mp, NULL, NULL, curthread);
 1297 
 1298 done:
 1299         if (vfsname != NULL)
 1300                 free(vfsname, M_MOUNT);
 1301         if (path != NULL)
 1302                 free(path, M_MOUNT);
 1303         if (error != 0) {
 1304                 if (mp != NULL)
 1305                         vfs_mount_destroy(mp, curthread);
 1306                 printf("Root mount failed: %d\n", error);
 1307         } else {
 1308 
 1309                 /* register with list of mounted filesystems */
 1310                 mtx_lock(&mountlist_mtx);
 1311                 TAILQ_INSERT_HEAD(&mountlist, mp, mnt_list);
 1312                 mtx_unlock(&mountlist_mtx);
 1313 
 1314                 /* sanity check system clock against root fs timestamp */
 1315                 inittodr(mp->mnt_time);
 1316                 vfs_unbusy(mp, curthread);
 1317                 error = VFS_START(mp, 0, curthread);
 1318         }
 1319         return (error);
 1320 }
 1321 
 1322 /*
 1323  * Spin prompting on the console for a suitable root filesystem
 1324  */
 1325 static int
 1326 vfs_mountroot_ask(void)
 1327 {
 1328         char name[128];
 1329 
 1330         for(;;) {
 1331                 printf("\nManual root filesystem specification:\n");
 1332                 printf("  <fstype>:<device>  Mount <device> using filesystem <fstype>\n");
 1333 #if defined(__i386__) || defined(__ia64__)
 1334                 printf("                       eg. ufs:da0s1a\n");
 1335 #else
 1336                 printf("                       eg. ufs:/dev/da0a\n");
 1337 #endif
 1338                 printf("  ?                  List valid disk boot devices\n");
 1339                 printf("  <empty line>       Abort manual input\n");
 1340                 printf("\nmountroot> ");
 1341                 gets(name);
 1342                 if (name[0] == '\0')
 1343                         return (1);
 1344                 if (name[0] == '?') {
 1345                         printf("\nList of GEOM managed disk devices:\n  ");
 1346                         g_dev_print();
 1347                         continue;
 1348                 }
 1349                 if (!vfs_mountroot_try(name))
 1350                         return (0);
 1351         }
 1352 }
 1353 
 1354 /*
 1355  * Local helper function for vfs_mountroot_ask.
 1356  */
 1357 static void
 1358 gets(char *cp)
 1359 {
 1360         char *lp;
 1361         int c;
 1362 
 1363         lp = cp;
 1364         for (;;) {
 1365                 printf("%c", c = cngetc() & 0177);
 1366                 switch (c) {
 1367                 case -1:
 1368                 case '\n':
 1369                 case '\r':
 1370                         *lp++ = '\0';
 1371                         return;
 1372                 case '\b':
 1373                 case '\177':
 1374                         if (lp > cp) {
 1375                                 printf(" \b");
 1376                                 lp--;
 1377                         }
 1378                         continue;
 1379                 case '#':
 1380                         lp--;
 1381                         if (lp < cp)
 1382                                 lp = cp;
 1383                         continue;
 1384                 case '@':
 1385                 case 'u' & 037:
 1386                         lp = cp;
 1387                         printf("%c", '\n');
 1388                         continue;
 1389                 default:
 1390                         *lp++ = c;
 1391                 }
 1392         }
 1393 }
 1394 
 1395 /*
 1396  * Convert a given name to the cdev pointer of the device, which is probably
 1397  * but not by definition, a disk.  Mount a DEVFS (on nothing), look the name
 1398  * up, extract the cdev from the vnode and unmount it again.  Unfortunately
 1399  * we cannot use the vnode directly (because we unmount the DEVFS again)
 1400  * so the filesystems still have to do the bdevvp() stunt.
 1401  */
 1402 struct cdev *
 1403 getdiskbyname(char *name)
 1404 {
 1405         char *cp = name;
 1406         struct cdev *dev = NULL;
 1407         struct thread *td = curthread;
 1408         struct vfsconf *vfsp;
 1409         struct mount *mp = NULL;
 1410         struct vnode *vroot = NULL;
 1411         struct nameidata nid;
 1412         int error;
 1413 
 1414         if (!bcmp(cp, "/dev/", 5))
 1415                 cp += 5;
 1416 
 1417         do {
 1418                 vfsp = vfs_byname("devfs");
 1419                 if (vfsp == NULL)
 1420                         break;
 1421                 error = vfs_mount_alloc(NULLVP, vfsp, "/dev", td, &mp);
 1422                 if (error)
 1423                         break;
 1424                 mp->mnt_flag |= MNT_RDONLY;
 1425 
 1426                 error = VFS_MOUNT(mp, curthread);
 1427                 if (error)
 1428                         break;
 1429                 VFS_START(mp, 0, td);
 1430                 VFS_ROOT(mp, &vroot, td);
 1431                 VOP_UNLOCK(vroot, 0, td);
 1432 
 1433                 NDINIT(&nid, LOOKUP, NOCACHE|FOLLOW,
 1434                     UIO_SYSSPACE, cp, curthread);
 1435                 nid.ni_startdir = vroot;
 1436                 nid.ni_pathlen = strlen(cp);
 1437                 nid.ni_cnd.cn_cred = curthread->td_ucred;
 1438                 nid.ni_cnd.cn_nameptr = cp;
 1439 
 1440                 error = lookup(&nid);
 1441                 if (error)
 1442                         break;
 1443                 dev = vn_todev (nid.ni_vp);
 1444                 NDFREE(&nid, 0);
 1445         } while (0);
 1446 
 1447         if (vroot != NULL)
 1448                 VFS_UNMOUNT(mp, 0, td);
 1449         if (mp != NULL)
 1450                 vfs_mount_destroy(mp, td);
 1451         return (dev);
 1452 }
 1453 
 1454 /* Show the struct cdev *for a disk specified by name */
 1455 #ifdef DDB
 1456 DB_SHOW_COMMAND(disk, db_getdiskbyname)
 1457 {
 1458         struct cdev *dev;
 1459 
 1460         if (modif[0] == '\0') {
 1461                 db_error("usage: show disk/devicename");
 1462                 return;
 1463         }
 1464         dev = getdiskbyname(modif);
 1465         if (dev != NULL)
 1466                 db_printf("struct cdev *= %p\n", dev);
 1467         else
 1468                 db_printf("No disk device matched.\n");
 1469 }
 1470 #endif
 1471 
 1472 /*
 1473  * Get a mount option by its name.
 1474  *
 1475  * Return 0 if the option was found, ENOENT otherwise.
 1476  * If len is non-NULL it will be filled with the length
 1477  * of the option. If buf is non-NULL, it will be filled
 1478  * with the address of the option.
 1479  */
 1480 int
 1481 vfs_getopt(opts, name, buf, len)
 1482         struct vfsoptlist *opts;
 1483         const char *name;
 1484         void **buf;
 1485         int *len;
 1486 {
 1487         struct vfsopt *opt;
 1488 
 1489         KASSERT(opts != NULL, ("vfs_getopt: caller passed 'opts' as NULL"));
 1490 
 1491         TAILQ_FOREACH(opt, opts, link) {
 1492                 if (strcmp(name, opt->name) == 0) {
 1493                         if (len != NULL)
 1494                                 *len = opt->len;
 1495                         if (buf != NULL)
 1496                                 *buf = opt->value;
 1497                         return (0);
 1498                 }
 1499         }
 1500         return (ENOENT);
 1501 }
 1502 
 1503 /*
 1504  * Find and copy a mount option.
 1505  *
 1506  * The size of the buffer has to be specified
 1507  * in len, if it is not the same length as the
 1508  * mount option, EINVAL is returned.
 1509  * Returns ENOENT if the option is not found.
 1510  */
 1511 int
 1512 vfs_copyopt(opts, name, dest, len)
 1513         struct vfsoptlist *opts;
 1514         const char *name;
 1515         void *dest;
 1516         int len;
 1517 {
 1518         struct vfsopt *opt;
 1519 
 1520         KASSERT(opts != NULL, ("vfs_copyopt: caller passed 'opts' as NULL"));
 1521 
 1522         TAILQ_FOREACH(opt, opts, link) {
 1523                 if (strcmp(name, opt->name) == 0) {
 1524                         if (len != opt->len)
 1525                                 return (EINVAL);
 1526                         bcopy(opt->value, dest, opt->len);
 1527                         return (0);
 1528                 }
 1529         }
 1530         return (ENOENT);
 1531 }
 1532 
 1533 
 1534 /*
 1535  * This is a helper function for filesystems to traverse their
 1536  * vnodes.  See MNT_VNODE_FOREACH() in sys/mount.h
 1537  */
 1538 
 1539 struct vnode *
 1540 __mnt_vnode_next(struct vnode **nvp, struct mount *mp)
 1541 {
 1542         struct vnode *vp;
 1543 
 1544         mtx_assert(&mp->mnt_mtx, MA_OWNED);
 1545         vp = *nvp;
 1546         /* Check if we are done */
 1547         if (vp == NULL)
 1548                 return (NULL);
 1549         /* If our next vnode is no longer ours, start over */
 1550         if (vp->v_mount != mp) 
 1551                 vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
 1552         /* Save pointer to next vnode in list */
 1553         if (vp != NULL)
 1554                 *nvp = TAILQ_NEXT(vp, v_nmntvnodes);
 1555         else
 1556                 *nvp = NULL;
 1557         return (vp);
 1558 }

Cache object: 1405a7cd8ff445622b563d049dc2b331


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