FreeBSD/Linux Kernel Cross Reference
sys/kern/vfs_mount.c
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: releng/5.0/sys/kern/vfs_mount.c 108086 2002-12-19 09:40:13Z alfred $
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
100 static void checkdirs(struct vnode *olddp, struct vnode *newdp);
101 static int vfs_nmount(struct thread *td, int, struct uio *);
102 static int vfs_mountroot_try(char *mountfrom);
103 static int vfs_mountroot_ask(void);
104 static void gets(char *cp);
105
106 static int usermount = 0; /* if 1, non-root can mount fs. */
107 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, "");
108
109 MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount structure");
110
111 /* List of mounted filesystems. */
112 struct mntlist mountlist = TAILQ_HEAD_INITIALIZER(mountlist);
113
114 /* For any iteration/modification of mountlist */
115 struct mtx mountlist_mtx;
116
117 /* For any iteration/modification of mnt_vnodelist */
118 struct mtx mntvnode_mtx;
119
120 /*
121 * The vnode of the system's root (/ in the filesystem, without chroot
122 * active.)
123 */
124 struct 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 */
140 static char *cdrom_rootdevnames[] = {
141 "cd9660:cd0a",
142 "cd9660:acd0a",
143 "cd9660:wcd0a",
144 NULL
145 };
146
147 /* legacy find-root code */
148 char *rootdevnames[2] = {NULL, NULL};
149 static int setrootbyname(char *name);
150 dev_t rootdev = NODEV;
151
152 /* Remove one mount option. */
153 static void
154 vfs_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. */
170 static void
171 vfs_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 */
187 static void
188 vfs_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 */
217 static int
218 vfs_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);
260 bad:
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 */
269 static void
270 vfs_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);
302 next:
303 continue;
304 }
305 }
306
307 /*
308 * New mount API.
309 */
310 int
311 nmount(td, uap)
312 struct thread *td;
313 struct nmount_args /* {
314 struct iovec *iovp;
315 unsigned int iovcnt;
316 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 = 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, uap->flags, &auio);
356 finish:
357 if (needfree != NULL)
358 free(needfree, M_TEMP);
359 return (error);
360 }
361
362 int
363 kernel_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
386 int
387 kernel_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 */
434 static int
435 vfs_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
659 update:
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);
776 bad:
777 vfs_freeopts(optlist);
778 return (error);
779 }
780
781 /*
782 * Old mount API.
783 */
784 #ifndef _SYS_SYSPROTO_H_
785 struct mount_args {
786 char *type;
787 char *path;
788 int flags;
789 caddr_t data;
790 };
791 #endif
792 /* ARGSUSED */
793 int
794 mount(td, uap)
795 struct thread *td;
796 struct mount_args /* {
797 char *type;
798 char *path;
799 int flags;
800 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(uap->type, fstype, MFSNAMELEN, NULL);
815 if (error == 0)
816 error = copyinstr(uap->path, fspath, MNAMELEN, NULL);
817 if (error == 0)
818 error = vfs_mount(td, fstype, fspath, uap->flags,
819 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 */
833 int
834 vfs_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);
1022 update:
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 */
1132 static void
1133 checkdirs(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_
1182 struct unmount_args {
1183 char *path;
1184 int flags;
1185 };
1186 #endif
1187 /* ARGSUSED */
1188 int
1189 unmount(td, uap)
1190 struct thread *td;
1191 register struct unmount_args /* {
1192 char *path;
1193 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 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, uap->flags, td));
1238 }
1239
1240 /*
1241 * Do the actual filesystem unmount.
1242 */
1243 int
1244 dounmount(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 */
1348 int
1349 vfs_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 */
1394 void
1395 vfs_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 */
1475 static int
1476 vfs_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
1536 done:
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 */
1568 static int
1569 vfs_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 */
1609 static void
1610 gets(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 */
1651 dev_t
1652 getdiskbyname(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 */
1669 static int
1670 setrootbyname(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
1685 DB_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 */
1709 int
1710 vfs_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 */
1738 int
1739 vfs_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 }
Cache object: 6591e6f0aeab811c0d9033e4fb210462
|