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