Deleted Added
full compact
vfs_mount.c (107850) vfs_mount.c (107855)
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 *
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 107850 2002-12-14 02:07:32Z alfred $
64 * $FreeBSD: head/sys/kern/vfs_mount.c 107855 2002-12-14 08:18:06Z 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
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 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);
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 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)
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 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);
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 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);
818 error = vfs_mount(td, fstype, fspath, uap->flags, 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 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
819 free(fstype, M_TEMP);
820 free(fspath, M_TEMP);
821 return (error);
822}
823
824/*
825 * vfs_mount(): actually attempt a filesystem mount.
826 *
827 * This routine is designed to be a "generic" entry point for routines
828 * that wish to mount a filesystem. All parameters except `fsdata' are
829 * pointers into kernel space. `fsdata' is currently still a pointer
830 * into userspace.
831 */
832int
833vfs_mount(td, fstype, fspath, fsflags, fsdata)
834 struct thread *td;
835 const char *fstype;
836 char *fspath;
837 int fsflags;
838 void *fsdata;
839{
840 linker_file_t lf;
841 struct vnode *vp;
842 struct mount *mp;
843 struct vfsconf *vfsp;
844 int error, flag = 0, kern_flag = 0;
845 struct vattr va;
846 struct nameidata nd;
847
848 /*
849 * Be ultra-paranoid about making sure the type and fspath
850 * variables will fit in our mp buffers, including the
851 * terminating NUL.
852 */
853 if (strlen(fstype) >= MFSNAMELEN || strlen(fspath) >= MNAMELEN)
854 return (ENAMETOOLONG);
855
856 if (usermount == 0) {
857 error = suser(td);
858 if (error)
859 return (error);
860 }
861 /*
862 * Do not allow NFS export by non-root users.
863 */
864 if (fsflags & MNT_EXPORTED) {
865 error = suser(td);
866 if (error)
867 return (error);
868 }
869 /*
870 * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users.
871 */
872 if (suser(td))
873 fsflags |= MNT_NOSUID | MNT_NODEV;
874 /*
875 * Get vnode to be covered
876 */
877 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspath, td);
878 if ((error = namei(&nd)) != 0)
879 return (error);
880 NDFREE(&nd, NDF_ONLY_PNBUF);
881 vp = nd.ni_vp;
882 if (fsflags & MNT_UPDATE) {
883 if ((vp->v_vflag & VV_ROOT) == 0) {
884 vput(vp);
885 return (EINVAL);
886 }
887 mp = vp->v_mount;
888 flag = mp->mnt_flag;
889 kern_flag = mp->mnt_kern_flag;
890 /*
891 * We only allow the filesystem to be reloaded if it
892 * is currently mounted read-only.
893 */
894 if ((fsflags & MNT_RELOAD) &&
895 ((mp->mnt_flag & MNT_RDONLY) == 0)) {
896 vput(vp);
897 return (EOPNOTSUPP); /* Needs translation */
898 }
899 /*
900 * Only root, or the user that did the original mount is
901 * permitted to update it.
902 */
903 if (mp->mnt_cred->cr_uid != td->td_ucred->cr_uid) {
904 error = suser(td);
905 if (error) {
906 vput(vp);
907 return (error);
908 }
909 }
910 if (vfs_busy(mp, LK_NOWAIT, 0, td)) {
911 vput(vp);
912 return (EBUSY);
913 }
914 VI_LOCK(vp);
915 if ((vp->v_iflag & VI_MOUNT) != 0 ||
916 vp->v_mountedhere != NULL) {
917 VI_UNLOCK(vp);
918 vfs_unbusy(mp, td);
919 vput(vp);
920 return (EBUSY);
921 }
922 vp->v_iflag |= VI_MOUNT;
923 VI_UNLOCK(vp);
924 mp->mnt_flag |= fsflags &
925 (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_SNAPSHOT);
926 VOP_UNLOCK(vp, 0, td);
927 goto update;
928 }
929 /*
930 * If the user is not root, ensure that they own the directory
931 * onto which we are attempting to mount.
932 */
933 error = VOP_GETATTR(vp, &va, td->td_ucred, td);
934 if (error) {
935 vput(vp);
936 return (error);
937 }
938 if (va.va_uid != td->td_ucred->cr_uid) {
939 error = suser(td);
940 if (error) {
941 vput(vp);
942 return (error);
943 }
944 }
945 if ((error = vinvalbuf(vp, V_SAVE, td->td_ucred, td, 0, 0)) != 0) {
946 vput(vp);
947 return (error);
948 }
949 if (vp->v_type != VDIR) {
950 vput(vp);
951 return (ENOTDIR);
952 }
953 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
954 if (!strcmp(vfsp->vfc_name, fstype))
955 break;
956 if (vfsp == NULL) {
957 /* Only load modules for root (very important!). */
958 error = suser(td);
959 if (error) {
960 vput(vp);
961 return (error);
962 }
963 error = securelevel_gt(td->td_ucred, 0);
964 if (error) {
965 vput(vp);
966 return (error);
967 }
968 error = linker_load_module(NULL, fstype, NULL, NULL, &lf);
969 if (error || lf == NULL) {
970 vput(vp);
971 if (lf == NULL)
972 error = ENODEV;
973 return (error);
974 }
975 lf->userrefs++;
976 /* Look up again to see if the VFS was loaded. */
977 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
978 if (!strcmp(vfsp->vfc_name, fstype))
979 break;
980 if (vfsp == NULL) {
981 lf->userrefs--;
982 linker_file_unload(lf);
983 vput(vp);
984 return (ENODEV);
985 }
986 }
987 VI_LOCK(vp);
988 if ((vp->v_iflag & VI_MOUNT) != 0 ||
989 vp->v_mountedhere != NULL) {
990 VI_UNLOCK(vp);
991 vput(vp);
992 return (EBUSY);
993 }
994 vp->v_iflag |= VI_MOUNT;
995 VI_UNLOCK(vp);
996
997 /*
998 * Allocate and initialize the filesystem.
999 */
1000 mp = malloc(sizeof(struct mount), M_MOUNT, M_WAITOK | M_ZERO);
1001 TAILQ_INIT(&mp->mnt_nvnodelist);
1002 TAILQ_INIT(&mp->mnt_reservedvnlist);
1003 lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, LK_NOPAUSE);
1004 (void)vfs_busy(mp, LK_NOWAIT, 0, td);
1005 mp->mnt_op = vfsp->vfc_vfsops;
1006 mp->mnt_vfc = vfsp;
1007 vfsp->vfc_refcount++;
1008 mp->mnt_stat.f_type = vfsp->vfc_typenum;
1009 mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
1010 strlcpy(mp->mnt_stat.f_fstypename, fstype, MFSNAMELEN);
1011 mp->mnt_vnodecovered = vp;
1012 mp->mnt_cred = crdup(td->td_ucred);
1013 mp->mnt_stat.f_owner = td->td_ucred->cr_uid;
1014 strlcpy(mp->mnt_stat.f_mntonname, fspath, MNAMELEN);
1015 mp->mnt_iosize_max = DFLTPHYS;
1016#ifdef MAC
1017 mac_init_mount(mp);
1018 mac_create_mount(td->td_ucred, mp);
1019#endif
1020 VOP_UNLOCK(vp, 0, td);
1021update:
1022 /*
1023 * Check if the fs implements the old VFS_MOUNT()
1024 * function, since the old system call was used.
1025 */
1026 if (mp->mnt_op->vfs_mount == NULL) {
1027 printf("%s doesn't support the old mount syscall\n",
1028 mp->mnt_vfc->vfc_name);
1029 VI_LOCK(vp);
1030 vp->v_iflag &= ~VI_MOUNT;
1031 VI_UNLOCK(vp);
1032 if (mp->mnt_flag & MNT_UPDATE)
1033 vfs_unbusy(mp, td);
1034 else {
1035 mp->mnt_vfc->vfc_refcount--;
1036 vfs_unbusy(mp, td);
1037#ifdef MAC
1038 mac_destroy_mount(mp);
1039#endif
1040 free(mp, M_MOUNT);
1041 }
1042 vrele(vp);
1043 return (EOPNOTSUPP);
1044 }
1045
1046 /*
1047 * Set the mount level flags.
1048 */
1049 if (fsflags & MNT_RDONLY)
1050 mp->mnt_flag |= MNT_RDONLY;
1051 else if (mp->mnt_flag & MNT_RDONLY)
1052 mp->mnt_kern_flag |= MNTK_WANTRDWR;
1053 mp->mnt_flag &=~ MNT_UPDATEMASK;
1054 mp->mnt_flag |= fsflags & (MNT_UPDATEMASK | MNT_FORCE);
1055 /*
1056 * Mount the filesystem.
1057 * XXX The final recipients of VFS_MOUNT just overwrite the ndp they
1058 * get. No freeing of cn_pnbuf.
1059 */
1060 error = VFS_MOUNT(mp, fspath, fsdata, &nd, td);
1061 if (mp->mnt_flag & MNT_UPDATE) {
1062 if (mp->mnt_kern_flag & MNTK_WANTRDWR)
1063 mp->mnt_flag &= ~MNT_RDONLY;
1064 mp->mnt_flag &=~
1065 (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_SNAPSHOT);
1066 mp->mnt_kern_flag &=~ MNTK_WANTRDWR;
1067 if (error) {
1068 mp->mnt_flag = flag;
1069 mp->mnt_kern_flag = kern_flag;
1070 }
1071 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
1072 if (mp->mnt_syncer == NULL)
1073 error = vfs_allocate_syncvnode(mp);
1074 } else {
1075 if (mp->mnt_syncer != NULL)
1076 vrele(mp->mnt_syncer);
1077 mp->mnt_syncer = NULL;
1078 }
1079 vfs_unbusy(mp, td);
1080 VI_LOCK(vp);
1081 vp->v_iflag &= ~VI_MOUNT;
1082 VI_UNLOCK(vp);
1083 vrele(vp);
1084 return (error);
1085 }
1086 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1087 /*
1088 * Put the new filesystem on the mount list after root.
1089 */
1090 cache_purge(vp);
1091 if (!error) {
1092 struct vnode *newdp;
1093
1094 VI_LOCK(vp);
1095 vp->v_iflag &= ~VI_MOUNT;
1096 VI_UNLOCK(vp);
1097 vp->v_mountedhere = mp;
1098 mtx_lock(&mountlist_mtx);
1099 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
1100 mtx_unlock(&mountlist_mtx);
1101 if (VFS_ROOT(mp, &newdp))
1102 panic("mount: lost mount");
1103 checkdirs(vp, newdp);
1104 vput(newdp);
1105 VOP_UNLOCK(vp, 0, td);
1106 if ((mp->mnt_flag & MNT_RDONLY) == 0)
1107 error = vfs_allocate_syncvnode(mp);
1108 vfs_unbusy(mp, td);
1109 if ((error = VFS_START(mp, 0, td)) != 0)
1110 vrele(vp);
1111 } else {
1112 VI_LOCK(vp);
1113 vp->v_iflag &= ~VI_MOUNT;
1114 VI_UNLOCK(vp);
1115 mp->mnt_vfc->vfc_refcount--;
1116 vfs_unbusy(mp, td);
1117#ifdef MAC
1118 mac_destroy_mount(mp);
1119#endif
1120 free(mp, M_MOUNT);
1121 vput(vp);
1122 }
1123 return (error);
1124}
1125
1126/*
1127 * Scan all active processes to see if any of them have a current
1128 * or root directory of `olddp'. If so, replace them with the new
1129 * mount point.
1130 */
1131static void
1132checkdirs(olddp, newdp)
1133 struct vnode *olddp, *newdp;
1134{
1135 struct filedesc *fdp;
1136 struct proc *p;
1137 int nrele;
1138
1139 if (vrefcnt(olddp) == 1)
1140 return;
1141 sx_slock(&allproc_lock);
1142 LIST_FOREACH(p, &allproc, p_list) {
1143 PROC_LOCK(p);
1144 fdp = p->p_fd;
1145 if (fdp == NULL) {
1146 PROC_UNLOCK(p);
1147 continue;
1148 }
1149 nrele = 0;
1150 FILEDESC_LOCK(fdp);
1151 if (fdp->fd_cdir == olddp) {
1152 VREF(newdp);
1153 fdp->fd_cdir = newdp;
1154 nrele++;
1155 }
1156 if (fdp->fd_rdir == olddp) {
1157 VREF(newdp);
1158 fdp->fd_rdir = newdp;
1159 nrele++;
1160 }
1161 FILEDESC_UNLOCK(fdp);
1162 PROC_UNLOCK(p);
1163 while (nrele--)
1164 vrele(olddp);
1165 }
1166 sx_sunlock(&allproc_lock);
1167 if (rootvnode == olddp) {
1168 vrele(rootvnode);
1169 VREF(newdp);
1170 rootvnode = newdp;
1171 }
1172}
1173
1174/*
1175 * Unmount a filesystem.
1176 *
1177 * Note: unmount takes a path to the vnode mounted on as argument,
1178 * not special file (as before).
1179 */
1180#ifndef _SYS_SYSPROTO_H_
1181struct unmount_args {
1182 char *path;
1183 int flags;
1184};
1185#endif
1186/* ARGSUSED */
1187int
1188unmount(td, uap)
1189 struct thread *td;
1190 register struct unmount_args /* {
1191 char *path;
1192 int flags;
1193 } */ *uap;
1194{
1195 register struct vnode *vp;
1196 struct mount *mp;
1197 int error;
1198 struct nameidata nd;
1199
1201 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1202 uap->path, td);
1200 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 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 */
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}
1201 if ((error = namei(&nd)) != 0)
1202 return (error);
1203 vp = nd.ni_vp;
1204 NDFREE(&nd, NDF_ONLY_PNBUF);
1205 mp = vp->v_mount;
1206
1207 /*
1208 * Only root, or the user that did the original mount is
1209 * permitted to unmount this filesystem.
1210 */
1211 if (mp->mnt_cred->cr_uid != td->td_ucred->cr_uid) {
1212 error = suser(td);
1213 if (error) {
1214 vput(vp);
1215 return (error);
1216 }
1217 }
1218
1219 /*
1220 * Don't allow unmounting the root filesystem.
1221 */
1222 if (mp->mnt_flag & MNT_ROOTFS) {
1223 vput(vp);
1224 return (EINVAL);
1225 }
1226
1227 /*
1228 * Must be the root of the filesystem
1229 */
1230 if ((vp->v_vflag & VV_ROOT) == 0) {
1231 vput(vp);
1232 return (EINVAL);
1233 }
1234 vput(vp);
1235 return (dounmount(mp, uap->flags, td));
1236}
1237
1238/*
1239 * Do the actual filesystem unmount.
1240 */
1241int
1242dounmount(mp, flags, td)
1243 struct mount *mp;
1244 int flags;
1245 struct thread *td;
1246{
1247 struct vnode *coveredvp, *fsrootvp;
1248 int error;
1249 int async_flag;
1250
1251 mtx_lock(&mountlist_mtx);
1252 if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
1253 mtx_unlock(&mountlist_mtx);
1254 return (EBUSY);
1255 }
1256 mp->mnt_kern_flag |= MNTK_UNMOUNT;
1257 /* Allow filesystems to detect that a forced unmount is in progress. */
1258 if (flags & MNT_FORCE)
1259 mp->mnt_kern_flag |= MNTK_UNMOUNTF;
1260 error = lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK |
1261 ((flags & MNT_FORCE) ? 0 : LK_NOWAIT), &mountlist_mtx, td);
1262 if (error) {
1263 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
1264 if (mp->mnt_kern_flag & MNTK_MWAIT)
1265 wakeup(mp);
1266 return (error);
1267 }
1268 vn_start_write(NULL, &mp, V_WAIT);
1269
1270 if (mp->mnt_flag & MNT_EXPUBLIC)
1271 vfs_setpublicfs(NULL, NULL, NULL);
1272
1273 vfs_msync(mp, MNT_WAIT);
1274 async_flag = mp->mnt_flag & MNT_ASYNC;
1275 mp->mnt_flag &=~ MNT_ASYNC;
1276 cache_purgevfs(mp); /* remove cache entries for this file sys */
1277 if (mp->mnt_syncer != NULL)
1278 vrele(mp->mnt_syncer);
1279 /* Move process cdir/rdir refs on fs root to underlying vnode. */
1280 if (VFS_ROOT(mp, &fsrootvp) == 0) {
1281 if (mp->mnt_vnodecovered != NULL)
1282 checkdirs(fsrootvp, mp->mnt_vnodecovered);
1283 if (fsrootvp == rootvnode) {
1284 vrele(rootvnode);
1285 rootvnode = NULL;
1286 }
1287 vput(fsrootvp);
1288 }
1289 if (((mp->mnt_flag & MNT_RDONLY) ||
1290 (error = VFS_SYNC(mp, MNT_WAIT, td->td_ucred, td)) == 0) ||
1291 (flags & MNT_FORCE)) {
1292 error = VFS_UNMOUNT(mp, flags, td);
1293 }
1294 vn_finished_write(mp);
1295 if (error) {
1296 /* Undo cdir/rdir and rootvnode changes made above. */
1297 if (VFS_ROOT(mp, &fsrootvp) == 0) {
1298 if (mp->mnt_vnodecovered != NULL)
1299 checkdirs(mp->mnt_vnodecovered, fsrootvp);
1300 if (rootvnode == NULL) {
1301 rootvnode = fsrootvp;
1302 vref(rootvnode);
1303 }
1304 vput(fsrootvp);
1305 }
1306 if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL)
1307 (void) vfs_allocate_syncvnode(mp);
1308 mtx_lock(&mountlist_mtx);
1309 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
1310 mp->mnt_flag |= async_flag;
1311 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK,
1312 &mountlist_mtx, td);
1313 if (mp->mnt_kern_flag & MNTK_MWAIT)
1314 wakeup(mp);
1315 return (error);
1316 }
1317 crfree(mp->mnt_cred);
1318 mtx_lock(&mountlist_mtx);
1319 TAILQ_REMOVE(&mountlist, mp, mnt_list);
1320 if ((coveredvp = mp->mnt_vnodecovered) != NULL)
1321 coveredvp->v_mountedhere = NULL;
1322 mp->mnt_vfc->vfc_refcount--;
1323 if (!TAILQ_EMPTY(&mp->mnt_nvnodelist))
1324 panic("unmount: dangling vnode");
1325 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_mtx, td);
1326 lockdestroy(&mp->mnt_lock);
1327 if (coveredvp != NULL)
1328 vrele(coveredvp);
1329 if (mp->mnt_kern_flag & MNTK_MWAIT)
1330 wakeup(mp);
1331#ifdef MAC
1332 mac_destroy_mount(mp);
1333#endif
1334 if (mp->mnt_op->vfs_mount == NULL)
1335 vfs_freeopts(mp->mnt_opt);
1336 free(mp, M_MOUNT);
1337 return (0);
1338}
1339
1340/*
1341 * Lookup a filesystem type, and if found allocate and initialize
1342 * a mount structure for it.
1343 *
1344 * Devname is usually updated by mount(8) after booting.
1345 */
1346int
1347vfs_rootmountalloc(fstypename, devname, mpp)
1348 char *fstypename;
1349 char *devname;
1350 struct mount **mpp;
1351{
1352 struct thread *td = curthread; /* XXX */
1353 struct vfsconf *vfsp;
1354 struct mount *mp;
1355
1356 if (fstypename == NULL)
1357 return (ENODEV);
1358 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
1359 if (!strcmp(vfsp->vfc_name, fstypename))
1360 break;
1361 if (vfsp == NULL)
1362 return (ENODEV);
1363 mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK | M_ZERO);
1364 lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, LK_NOPAUSE);
1365 (void)vfs_busy(mp, LK_NOWAIT, 0, td);
1366 TAILQ_INIT(&mp->mnt_nvnodelist);
1367 TAILQ_INIT(&mp->mnt_reservedvnlist);
1368 mp->mnt_vfc = vfsp;
1369 mp->mnt_op = vfsp->vfc_vfsops;
1370 mp->mnt_flag = MNT_RDONLY;
1371 mp->mnt_vnodecovered = NULLVP;
1372 mp->mnt_cred = crdup(td->td_ucred);
1373 vfsp->vfc_refcount++;
1374 mp->mnt_iosize_max = DFLTPHYS;
1375 mp->mnt_stat.f_type = vfsp->vfc_typenum;
1376 mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
1377 strlcpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
1378 mp->mnt_stat.f_mntonname[0] = '/';
1379 mp->mnt_stat.f_mntonname[1] = 0;
1380 strlcpy(mp->mnt_stat.f_mntfromname, devname, MNAMELEN);
1381#ifdef MAC
1382 mac_init_mount(mp);
1383 mac_create_mount(td->td_ucred, mp);
1384#endif
1385 *mpp = mp;
1386 return (0);
1387}
1388
1389/*
1390 * Find and mount the root filesystem
1391 */
1392void
1393vfs_mountroot(void)
1394{
1395 char *cp;
1396 int i, error;
1397
1398 g_waitidle();
1399
1400 /*
1401 * The root filesystem information is compiled in, and we are
1402 * booted with instructions to use it.
1403 */
1404#ifdef ROOTDEVNAME
1405 if ((boothowto & RB_DFLTROOT) &&
1406 !vfs_mountroot_try(ROOTDEVNAME))
1407 return;
1408#endif
1409 /*
1410 * We are booted with instructions to prompt for the root filesystem,
1411 * or to use the compiled-in default when it doesn't exist.
1412 */
1413 if (boothowto & (RB_DFLTROOT | RB_ASKNAME)) {
1414 if (!vfs_mountroot_ask())
1415 return;
1416 }
1417
1418 /*
1419 * We've been given the generic "use CDROM as root" flag. This is
1420 * necessary because one media may be used in many different
1421 * devices, so we need to search for them.
1422 */
1423 if (boothowto & RB_CDROM) {
1424 for (i = 0; cdrom_rootdevnames[i] != NULL; i++) {
1425 if (!vfs_mountroot_try(cdrom_rootdevnames[i]))
1426 return;
1427 }
1428 }
1429
1430 /*
1431 * Try to use the value read by the loader from /etc/fstab, or
1432 * supplied via some other means. This is the preferred
1433 * mechanism.
1434 */
1435 if ((cp = getenv("vfs.root.mountfrom")) != NULL) {
1436 error = vfs_mountroot_try(cp);
1437 freeenv(cp);
1438 if (!error)
1439 return;
1440 }
1441
1442 /*
1443 * Try values that may have been computed by the machine-dependant
1444 * legacy code.
1445 */
1446 if (!vfs_mountroot_try(rootdevnames[0]))
1447 return;
1448 if (!vfs_mountroot_try(rootdevnames[1]))
1449 return;
1450
1451 /*
1452 * If we have a compiled-in default, and haven't already tried it, try
1453 * it now.
1454 */
1455#ifdef ROOTDEVNAME
1456 if (!(boothowto & RB_DFLTROOT))
1457 if (!vfs_mountroot_try(ROOTDEVNAME))
1458 return;
1459#endif
1460
1461 /*
1462 * Everything so far has failed, prompt on the console if we haven't
1463 * already tried that.
1464 */
1465 if (!(boothowto & (RB_DFLTROOT | RB_ASKNAME)) && !vfs_mountroot_ask())
1466 return;
1467 panic("Root mount failed, startup aborted.");
1468}
1469
1470/*
1471 * Mount (mountfrom) as the root filesystem.
1472 */
1473static int
1474vfs_mountroot_try(char *mountfrom)
1475{
1476 struct mount *mp;
1477 char *vfsname, *path;
1478 const char *devname;
1479 int error;
1480 char patt[32];
1481 int s;
1482
1483 vfsname = NULL;
1484 path = NULL;
1485 mp = NULL;
1486 error = EINVAL;
1487
1488 if (mountfrom == NULL)
1489 return(error); /* don't complain */
1490
1491 s = splcam(); /* Overkill, but annoying without it */
1492 printf("Mounting root from %s\n", mountfrom);
1493 splx(s);
1494
1495 /* parse vfs name and path */
1496 vfsname = malloc(MFSNAMELEN, M_MOUNT, M_WAITOK);
1497 path = malloc(MNAMELEN, M_MOUNT, M_WAITOK);
1498 vfsname[0] = path[0] = 0;
1499 sprintf(patt, "%%%d[a-z0-9]:%%%zds", MFSNAMELEN, MNAMELEN);
1500 if (sscanf(mountfrom, patt, vfsname, path) < 1)
1501 goto done;
1502
1503 /* allocate a root mount */
1504 error = vfs_rootmountalloc(vfsname, path[0] != 0 ? path : ROOTNAME,
1505 &mp);
1506 if (error != 0) {
1507 printf("Can't allocate root mount for filesystem '%s': %d\n",
1508 vfsname, error);
1509 goto done;
1510 }
1511 mp->mnt_flag |= MNT_ROOTFS;
1512
1513 /* do our best to set rootdev */
1514 if ((path[0] != 0) && setrootbyname(path))
1515 printf("setrootbyname failed\n");
1516
1517 /* If the root device is a type "memory disk", mount RW */
1518 if (rootdev != NODEV && devsw(rootdev) != NULL) {
1519 devname = devtoname(rootdev);
1520 if (devname[0] == 'm' && devname[1] == 'd')
1521 mp->mnt_flag &= ~MNT_RDONLY;
1522 }
1523
1524 /*
1525 * Set the mount path to be something useful, because the
1526 * filesystem code isn't responsible now for initialising
1527 * f_mntonname unless they want to override the default
1528 * (which is `path'.)
1529 */
1530 strlcpy(mp->mnt_stat.f_mntonname, "/", MNAMELEN);
1531
1532 error = VFS_MOUNT(mp, NULL, NULL, NULL, curthread);
1533
1534done:
1535 if (vfsname != NULL)
1536 free(vfsname, M_MOUNT);
1537 if (path != NULL)
1538 free(path, M_MOUNT);
1539 if (error != 0) {
1540 if (mp != NULL) {
1541 vfs_unbusy(mp, curthread);
1542#ifdef MAC
1543 mac_destroy_mount(mp);
1544#endif
1545 free(mp, M_MOUNT);
1546 }
1547 printf("Root mount failed: %d\n", error);
1548 } else {
1549
1550 /* register with list of mounted filesystems */
1551 mtx_lock(&mountlist_mtx);
1552 TAILQ_INSERT_HEAD(&mountlist, mp, mnt_list);
1553 mtx_unlock(&mountlist_mtx);
1554
1555 /* sanity check system clock against root fs timestamp */
1556 inittodr(mp->mnt_time);
1557 vfs_unbusy(mp, curthread);
1558 error = VFS_START(mp, 0, curthread);
1559 }
1560 return(error);
1561}
1562
1563/*
1564 * Spin prompting on the console for a suitable root filesystem
1565 */
1566static int
1567vfs_mountroot_ask(void)
1568{
1569 char name[128];
1570 int i;
1571 dev_t dev;
1572
1573 for(;;) {
1574 printf("\nManual root filesystem specification:\n");
1575 printf(" <fstype>:<device> Mount <device> using filesystem <fstype>\n");
1576#if defined(__i386__) || defined(__ia64__)
1577 printf(" eg. ufs:da0s1a\n");
1578#else
1579 printf(" eg. ufs:da0a\n");
1580#endif
1581 printf(" ? List valid disk boot devices\n");
1582 printf(" <empty line> Abort manual input\n");
1583 printf("\nmountroot> ");
1584 gets(name);
1585 if (name[0] == 0)
1586 return(1);
1587 if (name[0] == '?') {
1588 if (!g_dev_print()) {
1589 printf("Possibly valid devices for 'ufs' root:\n");
1590 for (i = 0; i < NUMCDEVSW; i++) {
1591 dev = makedev(i, 0);
1592 if (devsw(dev) != NULL)
1593 printf(" \"%s\"", devsw(dev)->d_name);
1594 }
1595 }
1596 printf("\n");
1597 continue;
1598 }
1599 if (!vfs_mountroot_try(name))
1600 return(0);
1601 }
1602}
1603
1604/*
1605 * Local helper function for vfs_mountroot_ask.
1606 */
1607static void
1608gets(char *cp)
1609{
1610 char *lp;
1611 int c;
1612
1613 lp = cp;
1614 for (;;) {
1615 printf("%c", c = cngetc() & 0177);
1616 switch (c) {
1617 case -1:
1618 case '\n':
1619 case '\r':
1620 *lp++ = '\0';
1621 return;
1622 case '\b':
1623 case '\177':
1624 if (lp > cp) {
1625 printf(" \b");
1626 lp--;
1627 }
1628 continue;
1629 case '#':
1630 lp--;
1631 if (lp < cp)
1632 lp = cp;
1633 continue;
1634 case '@':
1635 case 'u' & 037:
1636 lp = cp;
1637 printf("%c", '\n');
1638 continue;
1639 default:
1640 *lp++ = c;
1641 }
1642 }
1643}
1644
1645/*
1646 * Convert a given name to the dev_t of the disk-like device
1647 * it refers to.
1648 */
1649dev_t
1650getdiskbyname(char *name) {
1651 char *cp;
1652 dev_t dev;
1653
1654 cp = name;
1655 if (!bcmp(cp, "/dev/", 5))
1656 cp += 5;
1657
1658 dev = NODEV;
1659 EVENTHANDLER_INVOKE(dev_clone, cp, strlen(cp), &dev);
1660 return (dev);
1661}
1662
1663/*
1664 * Set rootdev to match (name), given that we expect it to
1665 * refer to a disk-like device.
1666 */
1667static int
1668setrootbyname(char *name)
1669{
1670 dev_t diskdev;
1671
1672 diskdev = getdiskbyname(name);
1673 if (diskdev != NODEV) {
1674 rootdev = diskdev;
1675 return (0);
1676 }
1677
1678 return (1);
1679}
1680
1681/* Show the dev_t for a disk specified by name */
1682#ifdef DDB
1683DB_SHOW_COMMAND(disk, db_getdiskbyname)
1684{
1685 dev_t dev;
1686
1687 if (modif[0] == '\0') {
1688 db_error("usage: show disk/devicename");
1689 return;
1690 }
1691 dev = getdiskbyname(modif);
1692 if (dev != NODEV)
1693 db_printf("dev_t = %p\n", dev);
1694 else
1695 db_printf("No disk device matched.\n");
1696}
1697#endif
1698
1699/*
1700 * Get a mount option by its name.
1701 *
1702 * Return 0 if the option was found, ENOENT otherwise.
1703 * If len is non-NULL it will be filled with the length
1704 * of the option. If buf is non-NULL, it will be filled
1705 * with the address of the option.
1706 */
1707int
1708vfs_getopt(opts, name, buf, len)
1709 struct vfsoptlist *opts;
1710 const char *name;
1711 void **buf;
1712 int *len;
1713{
1714 struct vfsopt *opt;
1715
1716 TAILQ_FOREACH(opt, opts, link) {
1717 if (strcmp(name, opt->name) == 0) {
1718 if (len != NULL)
1719 *len = opt->len;
1720 if (buf != NULL)
1721 *buf = opt->value;
1722 return (0);
1723 }
1724 }
1725 return (ENOENT);
1726}
1727
1728/*
1729 * Find and copy a mount option.
1730 *
1731 * The size of the buffer has to be specified
1732 * in len, if it is not the same length as the
1733 * mount option, EINVAL is returned.
1734 * Returns ENOENT if the option is not found.
1735 */
1736int
1737vfs_copyopt(opts, name, dest, len)
1738 struct vfsoptlist *opts;
1739 const char *name;
1740 void *dest;
1741 int len;
1742{
1743 struct vfsopt *opt;
1744
1745 TAILQ_FOREACH(opt, opts, link) {
1746 if (strcmp(name, opt->name) == 0) {
1747 if (len != opt->len)
1748 return (EINVAL);
1749 bcopy(opt->value, dest, opt->len);
1750 return (0);
1751 }
1752 }
1753 return (ENOENT);
1754}