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