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

Cache object: e386a9de8ae767940dee4c33cb700656


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