FreeBSD/Linux Kernel Cross Reference
sys/kern/vfs_mount.c
1 /*-
2 * Copyright (c) 1999-2004 Poul-Henning Kamp
3 * Copyright (c) 1999 Michael Smith
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD$");
39
40 #include <sys/param.h>
41 #include <sys/conf.h>
42 #include <sys/jail.h>
43 #include <sys/kernel.h>
44 #include <sys/libkern.h>
45 #include <sys/mac.h>
46 #include <sys/malloc.h>
47 #include <sys/mount.h>
48 #include <sys/mutex.h>
49 #include <sys/namei.h>
50 #include <sys/proc.h>
51 #include <sys/filedesc.h>
52 #include <sys/reboot.h>
53 #include <sys/syscallsubr.h>
54 #include <sys/sysproto.h>
55 #include <sys/sx.h>
56 #include <sys/sysctl.h>
57 #include <sys/sysent.h>
58 #include <sys/systm.h>
59 #include <sys/vnode.h>
60 #include <vm/uma.h>
61
62 #include <geom/geom.h>
63
64 #include <machine/stdarg.h>
65
66 #include <security/audit/audit.h>
67
68 #include "opt_rootdevname.h"
69 #include "opt_ddb.h"
70 #include "opt_mac.h"
71
72 #ifdef DDB
73 #include <ddb/ddb.h>
74 #endif
75
76 #define ROOTNAME "root_device"
77 #define VFS_MOUNTARG_SIZE_MAX (1024 * 64)
78
79 static int vfs_domount(struct thread *td, const char *fstype,
80 char *fspath, int fsflags, void *fsdata);
81 static int vfs_mount_alloc(struct vnode *dvp, struct vfsconf *vfsp,
82 const char *fspath, struct thread *td, struct mount **mpp);
83 static int vfs_mountroot_ask(void);
84 static int vfs_mountroot_try(const char *mountfrom);
85 static int vfs_donmount(struct thread *td, int fsflags,
86 struct uio *fsoptions);
87 static void free_mntarg(struct mntarg *ma);
88 static void vfs_mount_destroy(struct mount *);
89 static int vfs_getopt_pos(struct vfsoptlist *opts, const char *name);
90
91 static int usermount = 0;
92 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0,
93 "Unprivileged users may mount and unmount file systems");
94
95 MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount structure");
96 MALLOC_DEFINE(M_VNODE_MARKER, "vnodemarker", "vnode marker");
97 static uma_zone_t mount_zone;
98
99 /* List of mounted filesystems. */
100 struct mntlist mountlist = TAILQ_HEAD_INITIALIZER(mountlist);
101
102 /* For any iteration/modification of mountlist */
103 struct mtx mountlist_mtx;
104 MTX_SYSINIT(mountlist, &mountlist_mtx, "mountlist", MTX_DEF);
105
106 TAILQ_HEAD(vfsoptlist, vfsopt);
107 struct vfsopt {
108 TAILQ_ENTRY(vfsopt) link;
109 char *name;
110 void *value;
111 int len;
112 };
113
114 /*
115 * The vnode of the system's root (/ in the filesystem, without chroot
116 * active.)
117 */
118 struct vnode *rootvnode;
119
120 /*
121 * The root filesystem is detailed in the kernel environment variable
122 * vfs.root.mountfrom, which is expected to be in the general format
123 *
124 * <vfsname>:[<path>]
125 * vfsname := the name of a VFS known to the kernel and capable
126 * of being mounted as root
127 * path := disk device name or other data used by the filesystem
128 * to locate its physical store
129 */
130
131 /*
132 * Global opts, taken by all filesystems
133 */
134 static const char *global_opts[] = {
135 "errmsg",
136 "fstype",
137 "fspath",
138 "rdonly",
139 "ro",
140 "rw",
141 "suid",
142 "exec",
143 "update",
144 NULL
145 };
146
147 /*
148 * The root specifiers we will try if RB_CDROM is specified.
149 */
150 static char *cdrom_rootdevnames[] = {
151 "cd9660:cd0",
152 "cd9660:acd0",
153 NULL
154 };
155
156 /* legacy find-root code */
157 char *rootdevnames[2] = {NULL, NULL};
158 #ifndef ROOTDEVNAME
159 # define ROOTDEVNAME NULL
160 #endif
161 static const char *ctrootdevname = ROOTDEVNAME;
162
163 /*
164 * ---------------------------------------------------------------------
165 * Functions for building and sanitizing the mount options
166 */
167
168 /* Remove one mount option. */
169 static void
170 vfs_freeopt(struct vfsoptlist *opts, struct vfsopt *opt)
171 {
172
173 TAILQ_REMOVE(opts, opt, link);
174 free(opt->name, M_MOUNT);
175 if (opt->value != NULL)
176 free(opt->value, M_MOUNT);
177 #ifdef INVARIANTS
178 else if (opt->len != 0)
179 panic("%s: mount option with NULL value but length != 0",
180 __func__);
181 #endif
182 free(opt, M_MOUNT);
183 }
184
185 /* Release all resources related to the mount options. */
186 static void
187 vfs_freeopts(struct vfsoptlist *opts)
188 {
189 struct vfsopt *opt;
190
191 while (!TAILQ_EMPTY(opts)) {
192 opt = TAILQ_FIRST(opts);
193 vfs_freeopt(opts, opt);
194 }
195 free(opts, M_MOUNT);
196 }
197
198 void
199 vfs_deleteopt(struct vfsoptlist *opts, const char *name)
200 {
201 struct vfsopt *opt, *temp;
202
203 TAILQ_FOREACH_SAFE(opt, opts, link, temp) {
204 if (strcmp(opt->name, name) == 0)
205 vfs_freeopt(opts, opt);
206 }
207 }
208
209 /*
210 * Check if options are equal (with or without the "no" prefix).
211 */
212 static int
213 vfs_equalopts(const char *opt1, const char *opt2)
214 {
215
216 /* "opt" vs. "opt" or "noopt" vs. "noopt" */
217 if (strcmp(opt1, opt2) == 0)
218 return (1);
219 /* "noopt" vs. "opt" */
220 if (strncmp(opt1, "no", 2) == 0 && strcmp(opt1 + 2, opt2) == 0)
221 return (1);
222 /* "opt" vs. "noopt" */
223 if (strncmp(opt2, "no", 2) == 0 && strcmp(opt1, opt2 + 2) == 0)
224 return (1);
225 return (0);
226 }
227
228 /*
229 * If a mount option is specified several times,
230 * (with or without the "no" prefix) only keep
231 * the last occurence of it.
232 */
233 static void
234 vfs_sanitizeopts(struct vfsoptlist *opts)
235 {
236 struct vfsopt *opt, *opt2, *tmp;
237
238 TAILQ_FOREACH_REVERSE(opt, opts, vfsoptlist, link) {
239 opt2 = TAILQ_PREV(opt, vfsoptlist, link);
240 while (opt2 != NULL) {
241 if (vfs_equalopts(opt->name, opt2->name)) {
242 tmp = TAILQ_PREV(opt2, vfsoptlist, link);
243 vfs_freeopt(opts, opt2);
244 opt2 = tmp;
245 } else {
246 opt2 = TAILQ_PREV(opt2, vfsoptlist, link);
247 }
248 }
249 }
250 }
251
252 /*
253 * Build a linked list of mount options from a struct uio.
254 */
255 static int
256 vfs_buildopts(struct uio *auio, struct vfsoptlist **options)
257 {
258 struct vfsoptlist *opts;
259 struct vfsopt *opt;
260 size_t memused;
261 unsigned int i, iovcnt;
262 int error, namelen, optlen;
263
264 opts = malloc(sizeof(struct vfsoptlist), M_MOUNT, M_WAITOK);
265 TAILQ_INIT(opts);
266 memused = 0;
267 iovcnt = auio->uio_iovcnt;
268 for (i = 0; i < iovcnt; i += 2) {
269 opt = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK);
270 namelen = auio->uio_iov[i].iov_len;
271 optlen = auio->uio_iov[i + 1].iov_len;
272 opt->name = malloc(namelen, M_MOUNT, M_WAITOK);
273 opt->value = NULL;
274 opt->len = 0;
275
276 /*
277 * Do this early, so jumps to "bad" will free the current
278 * option.
279 */
280 TAILQ_INSERT_TAIL(opts, opt, link);
281 memused += sizeof(struct vfsopt) + optlen + namelen;
282
283 /*
284 * Avoid consuming too much memory, and attempts to overflow
285 * memused.
286 */
287 if (memused > VFS_MOUNTARG_SIZE_MAX ||
288 optlen > VFS_MOUNTARG_SIZE_MAX ||
289 namelen > VFS_MOUNTARG_SIZE_MAX) {
290 error = EINVAL;
291 goto bad;
292 }
293
294 if (auio->uio_segflg == UIO_SYSSPACE) {
295 bcopy(auio->uio_iov[i].iov_base, opt->name, namelen);
296 } else {
297 error = copyin(auio->uio_iov[i].iov_base, opt->name,
298 namelen);
299 if (error)
300 goto bad;
301 }
302 /* Ensure names are null-terminated strings. */
303 if (opt->name[namelen - 1] != '\0') {
304 error = EINVAL;
305 goto bad;
306 }
307 if (optlen != 0) {
308 opt->len = optlen;
309 opt->value = malloc(optlen, M_MOUNT, M_WAITOK);
310 if (auio->uio_segflg == UIO_SYSSPACE) {
311 bcopy(auio->uio_iov[i + 1].iov_base, opt->value,
312 optlen);
313 } else {
314 error = copyin(auio->uio_iov[i + 1].iov_base,
315 opt->value, optlen);
316 if (error)
317 goto bad;
318 }
319 }
320 }
321 vfs_sanitizeopts(opts);
322 *options = opts;
323 return (0);
324 bad:
325 vfs_freeopts(opts);
326 return (error);
327 }
328
329 /*
330 * Merge the old mount options with the new ones passed
331 * in the MNT_UPDATE case.
332 */
333 static void
334 vfs_mergeopts(struct vfsoptlist *toopts, struct vfsoptlist *opts)
335 {
336 struct vfsopt *opt, *opt2, *new;
337
338 TAILQ_FOREACH(opt, opts, link) {
339 /*
340 * Check that this option hasn't been redefined
341 * nor cancelled with a "no" mount option.
342 */
343 opt2 = TAILQ_FIRST(toopts);
344 while (opt2 != NULL) {
345 if (strcmp(opt2->name, opt->name) == 0)
346 goto next;
347 if (strncmp(opt2->name, "no", 2) == 0 &&
348 strcmp(opt2->name + 2, opt->name) == 0) {
349 vfs_freeopt(toopts, opt2);
350 goto next;
351 }
352 opt2 = TAILQ_NEXT(opt2, link);
353 }
354 /* We want this option, duplicate it. */
355 new = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK);
356 new->name = malloc(strlen(opt->name) + 1, M_MOUNT, M_WAITOK);
357 strcpy(new->name, opt->name);
358 if (opt->len != 0) {
359 new->value = malloc(opt->len, M_MOUNT, M_WAITOK);
360 bcopy(opt->value, new->value, opt->len);
361 } else {
362 new->value = NULL;
363 }
364 new->len = opt->len;
365 TAILQ_INSERT_TAIL(toopts, new, link);
366 next:
367 continue;
368 }
369 }
370
371 /*
372 * ---------------------------------------------------------------------
373 * Mount a filesystem
374 */
375 int
376 nmount(td, uap)
377 struct thread *td;
378 struct nmount_args /* {
379 struct iovec *iovp;
380 unsigned int iovcnt;
381 int flags;
382 } */ *uap;
383 {
384 struct uio *auio;
385 struct iovec *iov;
386 unsigned int i;
387 int error;
388 u_int iovcnt;
389
390 AUDIT_ARG(fflags, uap->flags);
391
392 /* Kick out MNT_ROOTFS early as it is legal internally */
393 if (uap->flags & MNT_ROOTFS)
394 return (EINVAL);
395
396 iovcnt = uap->iovcnt;
397 /*
398 * Check that we have an even number of iovec's
399 * and that we have at least two options.
400 */
401 if ((iovcnt & 1) || (iovcnt < 4))
402 return (EINVAL);
403
404 error = copyinuio(uap->iovp, iovcnt, &auio);
405 if (error)
406 return (error);
407 iov = auio->uio_iov;
408 for (i = 0; i < iovcnt; i++) {
409 if (iov->iov_len > MMAXOPTIONLEN) {
410 free(auio, M_IOV);
411 return (EINVAL);
412 }
413 iov++;
414 }
415 error = vfs_donmount(td, uap->flags, auio);
416 free(auio, M_IOV);
417 return (error);
418 }
419
420 /*
421 * ---------------------------------------------------------------------
422 * Various utility functions
423 */
424
425 void
426 vfs_ref(struct mount *mp)
427 {
428
429 MNT_ILOCK(mp);
430 MNT_REF(mp);
431 MNT_IUNLOCK(mp);
432 }
433
434 void
435 vfs_rel(struct mount *mp)
436 {
437
438 MNT_ILOCK(mp);
439 MNT_REL(mp);
440 MNT_IUNLOCK(mp);
441 }
442
443 static int
444 mount_init(void *mem, int size, int flags)
445 {
446 struct mount *mp;
447
448 mp = (struct mount *)mem;
449 mtx_init(&mp->mnt_mtx, "struct mount mtx", NULL, MTX_DEF);
450 lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0);
451 lockinit(&mp->mnt_explock, PVFS, "explock", 0, 0);
452 return (0);
453 }
454
455 static void
456 mount_fini(void *mem, int size)
457 {
458 struct mount *mp;
459
460 mp = (struct mount *)mem;
461 lockdestroy(&mp->mnt_explock);
462 lockdestroy(&mp->mnt_lock);
463 mtx_destroy(&mp->mnt_mtx);
464 }
465
466 /*
467 * Allocate and initialize the mount point struct.
468 */
469 static int
470 vfs_mount_alloc(struct vnode *vp, struct vfsconf *vfsp,
471 const char *fspath, struct thread *td, struct mount **mpp)
472 {
473 struct mount *mp;
474
475 mp = uma_zalloc(mount_zone, M_WAITOK);
476 bzero(&mp->mnt_startzero,
477 __rangeof(struct mount, mnt_startzero, mnt_endzero));
478 bzero(&mp->mnt_startzero2,
479 __rangeof(struct mount, mnt_startzero2, mnt_endzero2));
480 TAILQ_INIT(&mp->mnt_nvnodelist);
481 mp->mnt_nvnodelistsize = 0;
482 mp->mnt_ref = 0;
483 (void) vfs_busy(mp, LK_NOWAIT, 0, td);
484 mp->mnt_op = vfsp->vfc_vfsops;
485 mp->mnt_vfc = vfsp;
486 vfsp->vfc_refcount++; /* XXX Unlocked */
487 mp->mnt_stat.f_type = vfsp->vfc_typenum;
488 MNT_ILOCK(mp);
489 mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
490 MNT_IUNLOCK(mp);
491 mp->mnt_gen++;
492 strlcpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
493 mp->mnt_vnodecovered = vp;
494 mp->mnt_cred = crdup(td->td_ucred);
495 mp->mnt_stat.f_owner = td->td_ucred->cr_uid;
496 strlcpy(mp->mnt_stat.f_mntonname, fspath, MNAMELEN);
497 mp->mnt_iosize_max = DFLTPHYS;
498 #ifdef MAC
499 mac_init_mount(mp);
500 mac_create_mount(td->td_ucred, mp);
501 #endif
502 arc4rand(&mp->mnt_hashseed, sizeof mp->mnt_hashseed, 0);
503 *mpp = mp;
504 return (0);
505 }
506
507 /*
508 * Destroy the mount struct previously allocated by vfs_mount_alloc().
509 */
510 static void
511 vfs_mount_destroy(struct mount *mp)
512 {
513 int i;
514
515 MNT_ILOCK(mp);
516 for (i = 0; mp->mnt_ref && i < 3; i++)
517 msleep(mp, MNT_MTX(mp), PVFS, "mntref", hz);
518 /*
519 * This will always cause a 3 second delay in rebooting due to
520 * refs on the root mountpoint that never go away. Most of these
521 * are held by init which never exits.
522 */
523 if (i == 3 && (!rebooting || bootverbose))
524 printf("Mount point %s had %d dangling refs\n",
525 mp->mnt_stat.f_mntonname, mp->mnt_ref);
526 if (mp->mnt_holdcnt != 0) {
527 printf("Waiting for mount point to be unheld\n");
528 while (mp->mnt_holdcnt != 0) {
529 mp->mnt_holdcntwaiters++;
530 msleep(&mp->mnt_holdcnt, MNT_MTX(mp),
531 PZERO, "mntdestroy", 0);
532 mp->mnt_holdcntwaiters--;
533 }
534 printf("mount point unheld\n");
535 }
536 if (mp->mnt_writeopcount > 0) {
537 printf("Waiting for mount point write ops\n");
538 while (mp->mnt_writeopcount > 0) {
539 mp->mnt_kern_flag |= MNTK_SUSPEND;
540 msleep(&mp->mnt_writeopcount,
541 MNT_MTX(mp),
542 PZERO, "mntdestroy2", 0);
543 }
544 printf("mount point write ops completed\n");
545 }
546 if (mp->mnt_secondary_writes > 0) {
547 printf("Waiting for mount point secondary write ops\n");
548 while (mp->mnt_secondary_writes > 0) {
549 mp->mnt_kern_flag |= MNTK_SUSPEND;
550 msleep(&mp->mnt_secondary_writes,
551 MNT_MTX(mp),
552 PZERO, "mntdestroy3", 0);
553 }
554 printf("mount point secondary write ops completed\n");
555 }
556 MNT_IUNLOCK(mp);
557 mp->mnt_vfc->vfc_refcount--;
558 if (!TAILQ_EMPTY(&mp->mnt_nvnodelist)) {
559 struct vnode *vp;
560
561 TAILQ_FOREACH(vp, &mp->mnt_nvnodelist, v_nmntvnodes)
562 vprint("", vp);
563 panic("unmount: dangling vnode");
564 }
565 MNT_ILOCK(mp);
566 if (mp->mnt_kern_flag & MNTK_MWAIT)
567 wakeup(mp);
568 if (mp->mnt_writeopcount != 0)
569 panic("vfs_mount_destroy: nonzero writeopcount");
570 if (mp->mnt_secondary_writes != 0)
571 panic("vfs_mount_destroy: nonzero secondary_writes");
572 if (mp->mnt_nvnodelistsize != 0)
573 panic("vfs_mount_destroy: nonzero nvnodelistsize");
574 mp->mnt_writeopcount = -1000;
575 mp->mnt_nvnodelistsize = -1000;
576 mp->mnt_secondary_writes = -1000;
577 MNT_IUNLOCK(mp);
578 #ifdef MAC
579 mac_destroy_mount(mp);
580 #endif
581 if (mp->mnt_opt != NULL)
582 vfs_freeopts(mp->mnt_opt);
583 crfree(mp->mnt_cred);
584 uma_zfree(mount_zone, mp);
585 }
586
587 static int
588 vfs_donmount(struct thread *td, int fsflags, struct uio *fsoptions)
589 {
590 struct vfsoptlist *optlist;
591 struct vfsopt *opt, *noro_opt;
592 char *fstype, *fspath, *errmsg;
593 int error, fstypelen, fspathlen, errmsg_len, errmsg_pos;
594 int has_rw, has_noro;
595
596 errmsg = NULL;
597 errmsg_len = 0;
598 errmsg_pos = -1;
599 has_rw = 0;
600 has_noro = 0;
601
602 error = vfs_buildopts(fsoptions, &optlist);
603 if (error)
604 return (error);
605
606 if (vfs_getopt(optlist, "errmsg", (void **)&errmsg, &errmsg_len) == 0)
607 errmsg_pos = vfs_getopt_pos(optlist, "errmsg");
608
609 /*
610 * We need these two options before the others,
611 * and they are mandatory for any filesystem.
612 * Ensure they are NUL terminated as well.
613 */
614 fstypelen = 0;
615 error = vfs_getopt(optlist, "fstype", (void **)&fstype, &fstypelen);
616 if (error || fstype[fstypelen - 1] != '\0') {
617 error = EINVAL;
618 if (errmsg != NULL)
619 strncpy(errmsg, "Invalid fstype", errmsg_len);
620 goto bail;
621 }
622 fspathlen = 0;
623 error = vfs_getopt(optlist, "fspath", (void **)&fspath, &fspathlen);
624 if (error || fspath[fspathlen - 1] != '\0') {
625 error = EINVAL;
626 if (errmsg != NULL)
627 strncpy(errmsg, "Invalid fspath", errmsg_len);
628 goto bail;
629 }
630
631 /*
632 * We need to see if we have the "update" option
633 * before we call vfs_domount(), since vfs_domount() has special
634 * logic based on MNT_UPDATE. This is very important
635 * when we want to update the root filesystem.
636 */
637 TAILQ_FOREACH(opt, optlist, link) {
638 if (strcmp(opt->name, "update") == 0)
639 fsflags |= MNT_UPDATE;
640 else if (strcmp(opt->name, "async") == 0)
641 fsflags |= MNT_ASYNC;
642 else if (strcmp(opt->name, "force") == 0)
643 fsflags |= MNT_FORCE;
644 else if (strcmp(opt->name, "multilabel") == 0)
645 fsflags |= MNT_MULTILABEL;
646 else if (strcmp(opt->name, "noasync") == 0)
647 fsflags &= ~MNT_ASYNC;
648 else if (strcmp(opt->name, "noatime") == 0)
649 fsflags |= MNT_NOATIME;
650 else if (strcmp(opt->name, "noclusterr") == 0)
651 fsflags |= MNT_NOCLUSTERR;
652 else if (strcmp(opt->name, "noclusterw") == 0)
653 fsflags |= MNT_NOCLUSTERW;
654 else if (strcmp(opt->name, "noexec") == 0)
655 fsflags |= MNT_NOEXEC;
656 else if (strcmp(opt->name, "nosuid") == 0)
657 fsflags |= MNT_NOSUID;
658 else if (strcmp(opt->name, "nosymfollow") == 0)
659 fsflags |= MNT_NOSYMFOLLOW;
660 else if (strcmp(opt->name, "noro") == 0) {
661 fsflags &= ~MNT_RDONLY;
662 has_noro = 1;
663 }
664 else if (strcmp(opt->name, "rw") == 0) {
665 fsflags &= ~MNT_RDONLY;
666 has_rw = 1;
667 }
668 else if (strcmp(opt->name, "ro") == 0 ||
669 strcmp(opt->name, "rdonly") == 0)
670 fsflags |= MNT_RDONLY;
671 else if (strcmp(opt->name, "snapshot") == 0)
672 fsflags |= MNT_SNAPSHOT;
673 else if (strcmp(opt->name, "suiddir") == 0)
674 fsflags |= MNT_SUIDDIR;
675 else if (strcmp(opt->name, "sync") == 0)
676 fsflags |= MNT_SYNCHRONOUS;
677 else if (strcmp(opt->name, "union") == 0)
678 fsflags |= MNT_UNION;
679 }
680
681 /*
682 * If "rw" was specified as a mount option, and we
683 * are trying to update a mount-point from "ro" to "rw",
684 * we need a mount option "noro", since in vfs_mergeopts(),
685 * "noro" will cancel "ro", but "rw" will not do anything.
686 */
687 if (has_rw && !has_noro) {
688 noro_opt = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK);
689 noro_opt->name = strdup("noro", M_MOUNT);
690 noro_opt->value = NULL;
691 noro_opt->len = 0;
692 TAILQ_INSERT_TAIL(optlist, noro_opt, link);
693 }
694
695 /*
696 * Be ultra-paranoid about making sure the type and fspath
697 * variables will fit in our mp buffers, including the
698 * terminating NUL.
699 */
700 if (fstypelen >= MFSNAMELEN - 1 || fspathlen >= MNAMELEN - 1) {
701 error = ENAMETOOLONG;
702 goto bail;
703 }
704
705 mtx_lock(&Giant);
706 error = vfs_domount(td, fstype, fspath, fsflags, optlist);
707 mtx_unlock(&Giant);
708 bail:
709 /* copyout the errmsg */
710 if (errmsg_pos != -1 && ((2 * errmsg_pos + 1) < fsoptions->uio_iovcnt)
711 && errmsg_len > 0 && errmsg != NULL) {
712 if (fsoptions->uio_segflg == UIO_SYSSPACE) {
713 bcopy(errmsg,
714 fsoptions->uio_iov[2 * errmsg_pos + 1].iov_base,
715 fsoptions->uio_iov[2 * errmsg_pos + 1].iov_len);
716 } else {
717 copyout(errmsg,
718 fsoptions->uio_iov[2 * errmsg_pos + 1].iov_base,
719 fsoptions->uio_iov[2 * errmsg_pos + 1].iov_len);
720 }
721 }
722
723 if (error != 0)
724 vfs_freeopts(optlist);
725 return (error);
726 }
727
728 /*
729 * ---------------------------------------------------------------------
730 * Old mount API.
731 */
732 #ifndef _SYS_SYSPROTO_H_
733 struct mount_args {
734 char *type;
735 char *path;
736 int flags;
737 caddr_t data;
738 };
739 #endif
740 /* ARGSUSED */
741 int
742 mount(td, uap)
743 struct thread *td;
744 struct mount_args /* {
745 char *type;
746 char *path;
747 int flags;
748 caddr_t data;
749 } */ *uap;
750 {
751 char *fstype;
752 struct vfsconf *vfsp = NULL;
753 struct mntarg *ma = NULL;
754 int error;
755
756 AUDIT_ARG(fflags, uap->flags);
757
758 /* Kick out MNT_ROOTFS early as it is legal internally */
759 uap->flags &= ~MNT_ROOTFS;
760
761 if (uap->data == NULL)
762 return (EINVAL);
763
764 fstype = malloc(MFSNAMELEN, M_TEMP, M_WAITOK);
765 error = copyinstr(uap->type, fstype, MFSNAMELEN, NULL);
766 if (!error) {
767 AUDIT_ARG(text, fstype);
768 mtx_lock(&Giant); /* XXX ? */
769 vfsp = vfs_byname_kld(fstype, td, &error);
770 mtx_unlock(&Giant);
771 }
772 free(fstype, M_TEMP);
773 if (error)
774 return (error);
775 if (vfsp == NULL)
776 return (ENOENT);
777 if (vfsp->vfc_vfsops->vfs_cmount == NULL)
778 return (EOPNOTSUPP);
779
780 ma = mount_argsu(ma, "fstype", uap->type, MNAMELEN);
781 ma = mount_argsu(ma, "fspath", uap->path, MNAMELEN);
782 ma = mount_argb(ma, uap->flags & MNT_RDONLY, "noro");
783 ma = mount_argb(ma, !(uap->flags & MNT_NOSUID), "nosuid");
784 ma = mount_argb(ma, !(uap->flags & MNT_NOEXEC), "noexec");
785
786 error = vfsp->vfc_vfsops->vfs_cmount(ma, uap->data, uap->flags, td);
787 return (error);
788 }
789
790
791 /*
792 * vfs_domount(): actually attempt a filesystem mount.
793 */
794 static int
795 vfs_domount(
796 struct thread *td, /* Flags common to all filesystems. */
797 const char *fstype, /* Filesystem type. */
798 char *fspath, /* Mount path. */
799 int fsflags, /* Flags common to all filesystems. */
800 void *fsdata /* Options local to the filesystem. */
801 )
802 {
803 struct vnode *vp;
804 struct mount *mp;
805 struct vfsconf *vfsp;
806 struct export_args export;
807 int error, flag = 0;
808 struct vattr va;
809 struct nameidata nd;
810
811 mtx_assert(&Giant, MA_OWNED);
812 /*
813 * Be ultra-paranoid about making sure the type and fspath
814 * variables will fit in our mp buffers, including the
815 * terminating NUL.
816 */
817 if (strlen(fstype) >= MFSNAMELEN || strlen(fspath) >= MNAMELEN)
818 return (ENAMETOOLONG);
819
820 if (jailed(td->td_ucred))
821 return (EPERM);
822 if (usermount == 0) {
823 if ((error = suser(td)) != 0)
824 return (error);
825 }
826
827 /*
828 * Do not allow NFS export or MNT_SUIDDIR by unprivileged users.
829 */
830 if (fsflags & (MNT_EXPORTED | MNT_SUIDDIR)) {
831 if ((error = suser(td)) != 0)
832 return (error);
833 }
834 /*
835 * Silently enforce MNT_NOSUID and MNT_USER for
836 * unprivileged users.
837 */
838 if (suser(td) != 0)
839 fsflags |= MNT_NOSUID | MNT_USER;
840
841 /* Load KLDs before we lock the covered vnode to avoid reversals. */
842 vfsp = NULL;
843 if ((fsflags & MNT_UPDATE) == 0) {
844 /* Don't try to load KLDs if we're mounting the root. */
845 if (fsflags & MNT_ROOTFS)
846 vfsp = vfs_byname(fstype);
847 else
848 vfsp = vfs_byname_kld(fstype, td, &error);
849 if (vfsp == NULL)
850 return (ENODEV);
851 }
852 /*
853 * Get vnode to be covered
854 */
855 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_SYSSPACE,
856 fspath, td);
857 if ((error = namei(&nd)) != 0)
858 return (error);
859 NDFREE(&nd, NDF_ONLY_PNBUF);
860 vp = nd.ni_vp;
861 if (fsflags & MNT_UPDATE) {
862 if ((vp->v_vflag & VV_ROOT) == 0) {
863 vput(vp);
864 return (EINVAL);
865 }
866 mp = vp->v_mount;
867 MNT_ILOCK(mp);
868 flag = mp->mnt_flag;
869 /*
870 * We only allow the filesystem to be reloaded if it
871 * is currently mounted read-only.
872 */
873 if ((fsflags & MNT_RELOAD) &&
874 ((mp->mnt_flag & MNT_RDONLY) == 0)) {
875 MNT_IUNLOCK(mp);
876 vput(vp);
877 return (EOPNOTSUPP); /* Needs translation */
878 }
879 MNT_IUNLOCK(mp);
880 /*
881 * Only privileged root, or (if MNT_USER is set) the user that
882 * did the original mount is permitted to update it.
883 */
884 error = vfs_suser(mp, td);
885 if (error) {
886 vput(vp);
887 return (error);
888 }
889 if (vfs_busy(mp, LK_NOWAIT, 0, td)) {
890 vput(vp);
891 return (EBUSY);
892 }
893 VI_LOCK(vp);
894 if ((vp->v_iflag & VI_MOUNT) != 0 ||
895 vp->v_mountedhere != NULL) {
896 VI_UNLOCK(vp);
897 vfs_unbusy(mp, td);
898 vput(vp);
899 return (EBUSY);
900 }
901 vp->v_iflag |= VI_MOUNT;
902 VI_UNLOCK(vp);
903 MNT_ILOCK(mp);
904 mp->mnt_flag |= fsflags &
905 (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_SNAPSHOT | MNT_ROOTFS);
906 MNT_IUNLOCK(mp);
907 VOP_UNLOCK(vp, 0, td);
908 mp->mnt_optnew = fsdata;
909 vfs_mergeopts(mp->mnt_optnew, mp->mnt_opt);
910 } else {
911 /*
912 * If the user is not root, ensure that they own the directory
913 * onto which we are attempting to mount.
914 */
915 error = VOP_GETATTR(vp, &va, td->td_ucred, td);
916 if (error) {
917 vput(vp);
918 return (error);
919 }
920 if (va.va_uid != td->td_ucred->cr_uid) {
921 if ((error = suser(td)) != 0) {
922 vput(vp);
923 return (error);
924 }
925 }
926 error = vinvalbuf(vp, V_SAVE, td, 0, 0);
927 if (error != 0) {
928 vput(vp);
929 return (error);
930 }
931 if (vp->v_type != VDIR) {
932 vput(vp);
933 return (ENOTDIR);
934 }
935 VI_LOCK(vp);
936 if ((vp->v_iflag & VI_MOUNT) != 0 ||
937 vp->v_mountedhere != NULL) {
938 VI_UNLOCK(vp);
939 vput(vp);
940 return (EBUSY);
941 }
942 vp->v_iflag |= VI_MOUNT;
943 VI_UNLOCK(vp);
944
945 /*
946 * Allocate and initialize the filesystem.
947 */
948 error = vfs_mount_alloc(vp, vfsp, fspath, td, &mp);
949 if (error) {
950 vput(vp);
951 return (error);
952 }
953 VOP_UNLOCK(vp, 0, td);
954
955 /* XXXMAC: pass to vfs_mount_alloc? */
956 mp->mnt_optnew = fsdata;
957 }
958
959 /*
960 * Set the mount level flags.
961 */
962 MNT_ILOCK(mp);
963 mp->mnt_flag = (mp->mnt_flag & ~MNT_UPDATEMASK) |
964 (fsflags & (MNT_UPDATEMASK | MNT_FORCE | MNT_ROOTFS |
965 MNT_RDONLY));
966 MNT_IUNLOCK(mp);
967 /*
968 * Mount the filesystem.
969 * XXX The final recipients of VFS_MOUNT just overwrite the ndp they
970 * get. No freeing of cn_pnbuf.
971 */
972 error = VFS_MOUNT(mp, td);
973
974 /*
975 * Process the export option only if we are
976 * updating mount options.
977 */
978 if (!error && (fsflags & MNT_UPDATE)) {
979 if (vfs_copyopt(mp->mnt_optnew, "export", &export,
980 sizeof(export)) == 0)
981 error = vfs_export(mp, &export);
982 }
983
984 if (!error) {
985 if (mp->mnt_opt != NULL)
986 vfs_freeopts(mp->mnt_opt);
987 mp->mnt_opt = mp->mnt_optnew;
988 (void)VFS_STATFS(mp, &mp->mnt_stat, td);
989 }
990 /*
991 * Prevent external consumers of mount options from reading
992 * mnt_optnew.
993 */
994 mp->mnt_optnew = NULL;
995 if (mp->mnt_flag & MNT_UPDATE) {
996 MNT_ILOCK(mp);
997 if (error)
998 mp->mnt_flag = (mp->mnt_flag & MNT_QUOTA) |
999 (flag & ~MNT_QUOTA);
1000 else
1001 mp->mnt_flag &= ~(MNT_UPDATE | MNT_RELOAD |
1002 MNT_FORCE | MNT_SNAPSHOT);
1003 MNT_IUNLOCK(mp);
1004 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
1005 if (mp->mnt_syncer == NULL)
1006 error = vfs_allocate_syncvnode(mp);
1007 } else {
1008 if (mp->mnt_syncer != NULL)
1009 vrele(mp->mnt_syncer);
1010 mp->mnt_syncer = NULL;
1011 }
1012 vfs_unbusy(mp, td);
1013 VI_LOCK(vp);
1014 vp->v_iflag &= ~VI_MOUNT;
1015 VI_UNLOCK(vp);
1016 vrele(vp);
1017 return (error);
1018 }
1019 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1020 /*
1021 * Put the new filesystem on the mount list after root.
1022 */
1023 cache_purge(vp);
1024 if (!error) {
1025 struct vnode *newdp;
1026
1027 VI_LOCK(vp);
1028 vp->v_iflag &= ~VI_MOUNT;
1029 VI_UNLOCK(vp);
1030 vp->v_mountedhere = mp;
1031 mtx_lock(&mountlist_mtx);
1032 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
1033 mtx_unlock(&mountlist_mtx);
1034 vfs_event_signal(NULL, VQ_MOUNT, 0);
1035 if (VFS_ROOT(mp, LK_EXCLUSIVE, &newdp, td))
1036 panic("mount: lost mount");
1037 mountcheckdirs(vp, newdp);
1038 vput(newdp);
1039 VOP_UNLOCK(vp, 0, td);
1040 if ((mp->mnt_flag & MNT_RDONLY) == 0)
1041 error = vfs_allocate_syncvnode(mp);
1042 vfs_unbusy(mp, td);
1043 if (error)
1044 vrele(vp);
1045 } else {
1046 VI_LOCK(vp);
1047 vp->v_iflag &= ~VI_MOUNT;
1048 VI_UNLOCK(vp);
1049 vfs_unbusy(mp, td);
1050 vfs_mount_destroy(mp);
1051 vput(vp);
1052 }
1053 return (error);
1054 }
1055
1056 /*
1057 * ---------------------------------------------------------------------
1058 * Unmount a filesystem.
1059 *
1060 * Note: unmount takes a path to the vnode mounted on as argument,
1061 * not special file (as before).
1062 */
1063 #ifndef _SYS_SYSPROTO_H_
1064 struct unmount_args {
1065 char *path;
1066 int flags;
1067 };
1068 #endif
1069 /* ARGSUSED */
1070 int
1071 unmount(td, uap)
1072 struct thread *td;
1073 register struct unmount_args /* {
1074 char *path;
1075 int flags;
1076 } */ *uap;
1077 {
1078 struct mount *mp;
1079 char *pathbuf;
1080 int error, id0, id1;
1081
1082 if (jailed(td->td_ucred))
1083 return (EPERM);
1084 if (usermount == 0) {
1085 if ((error = suser(td)) != 0)
1086 return (error);
1087 }
1088
1089 pathbuf = malloc(MNAMELEN, M_TEMP, M_WAITOK);
1090 error = copyinstr(uap->path, pathbuf, MNAMELEN, NULL);
1091 if (error) {
1092 free(pathbuf, M_TEMP);
1093 return (error);
1094 }
1095 AUDIT_ARG(upath, td, pathbuf, ARG_UPATH1);
1096 if (uap->flags & MNT_BYFSID) {
1097 /* Decode the filesystem ID. */
1098 if (sscanf(pathbuf, "FSID:%d:%d", &id0, &id1) != 2) {
1099 free(pathbuf, M_TEMP);
1100 return (EINVAL);
1101 }
1102
1103 mtx_lock(&mountlist_mtx);
1104 TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) {
1105 if (mp->mnt_stat.f_fsid.val[0] == id0 &&
1106 mp->mnt_stat.f_fsid.val[1] == id1)
1107 break;
1108 }
1109 mtx_unlock(&mountlist_mtx);
1110 } else {
1111 mtx_lock(&mountlist_mtx);
1112 TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) {
1113 if (strcmp(mp->mnt_stat.f_mntonname, pathbuf) == 0)
1114 break;
1115 }
1116 mtx_unlock(&mountlist_mtx);
1117 }
1118 free(pathbuf, M_TEMP);
1119 if (mp == NULL) {
1120 /*
1121 * Previously we returned ENOENT for a nonexistent path and
1122 * EINVAL for a non-mountpoint. We cannot tell these apart
1123 * now, so in the !MNT_BYFSID case return the more likely
1124 * EINVAL for compatibility.
1125 */
1126 return ((uap->flags & MNT_BYFSID) ? ENOENT : EINVAL);
1127 }
1128
1129 /*
1130 * Don't allow unmounting the root filesystem.
1131 */
1132 if (mp->mnt_flag & MNT_ROOTFS)
1133 return (EINVAL);
1134 mtx_lock(&Giant);
1135 error = dounmount(mp, uap->flags, td);
1136 mtx_unlock(&Giant);
1137 return (error);
1138 }
1139
1140 /*
1141 * Do the actual filesystem unmount.
1142 */
1143 int
1144 dounmount(mp, flags, td)
1145 struct mount *mp;
1146 int flags;
1147 struct thread *td;
1148 {
1149 struct vnode *coveredvp, *fsrootvp;
1150 int error;
1151 int async_flag;
1152 int mnt_gen_r;
1153
1154 mtx_assert(&Giant, MA_OWNED);
1155
1156 if ((coveredvp = mp->mnt_vnodecovered) != NULL) {
1157 mnt_gen_r = mp->mnt_gen;
1158 VI_LOCK(coveredvp);
1159 vholdl(coveredvp);
1160 vn_lock(coveredvp, LK_EXCLUSIVE | LK_INTERLOCK | LK_RETRY, td);
1161 vdrop(coveredvp);
1162 /*
1163 * Check for mp being unmounted while waiting for the
1164 * covered vnode lock.
1165 */
1166 if (coveredvp->v_mountedhere != mp ||
1167 coveredvp->v_mountedhere->mnt_gen != mnt_gen_r) {
1168 VOP_UNLOCK(coveredvp, 0, td);
1169 return (EBUSY);
1170 }
1171 }
1172 /*
1173 * Only privileged root, or (if MNT_USER is set) the user that did the
1174 * original mount is permitted to unmount this filesystem.
1175 */
1176 error = vfs_suser(mp, td);
1177 if (error) {
1178 if (coveredvp)
1179 VOP_UNLOCK(coveredvp, 0, td);
1180 return (error);
1181 }
1182
1183 MNT_ILOCK(mp);
1184 if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
1185 MNT_IUNLOCK(mp);
1186 if (coveredvp)
1187 VOP_UNLOCK(coveredvp, 0, td);
1188 return (EBUSY);
1189 }
1190 mp->mnt_kern_flag |= MNTK_UNMOUNT;
1191 /* Allow filesystems to detect that a forced unmount is in progress. */
1192 if (flags & MNT_FORCE)
1193 mp->mnt_kern_flag |= MNTK_UNMOUNTF;
1194 error = lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK |
1195 ((flags & MNT_FORCE) ? 0 : LK_NOWAIT), MNT_MTX(mp), td);
1196 if (error) {
1197 MNT_ILOCK(mp);
1198 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
1199 if (mp->mnt_kern_flag & MNTK_MWAIT)
1200 wakeup(mp);
1201 MNT_IUNLOCK(mp);
1202 if (coveredvp)
1203 VOP_UNLOCK(coveredvp, 0, td);
1204 return (error);
1205 }
1206 vn_start_write(NULL, &mp, V_WAIT);
1207
1208 if (mp->mnt_flag & MNT_EXPUBLIC)
1209 vfs_setpublicfs(NULL, NULL, NULL);
1210
1211 vfs_msync(mp, MNT_WAIT);
1212 MNT_ILOCK(mp);
1213 async_flag = mp->mnt_flag & MNT_ASYNC;
1214 mp->mnt_flag &= ~MNT_ASYNC;
1215 MNT_IUNLOCK(mp);
1216 cache_purgevfs(mp); /* remove cache entries for this file sys */
1217 if (mp->mnt_syncer != NULL)
1218 vrele(mp->mnt_syncer);
1219 /*
1220 * For forced unmounts, move process cdir/rdir refs on the fs root
1221 * vnode to the covered vnode. For non-forced unmounts we want
1222 * such references to cause an EBUSY error.
1223 */
1224 if ((flags & MNT_FORCE) &&
1225 VFS_ROOT(mp, LK_EXCLUSIVE, &fsrootvp, td) == 0) {
1226 if (mp->mnt_vnodecovered != NULL)
1227 mountcheckdirs(fsrootvp, mp->mnt_vnodecovered);
1228 if (fsrootvp == rootvnode) {
1229 vrele(rootvnode);
1230 rootvnode = NULL;
1231 }
1232 vput(fsrootvp);
1233 }
1234 if (((mp->mnt_flag & MNT_RDONLY) ||
1235 (error = VFS_SYNC(mp, MNT_WAIT, td)) == 0) ||
1236 (flags & MNT_FORCE)) {
1237 error = VFS_UNMOUNT(mp, flags, td);
1238 }
1239 vn_finished_write(mp);
1240 if (error) {
1241 /* Undo cdir/rdir and rootvnode changes made above. */
1242 if ((flags & MNT_FORCE) &&
1243 VFS_ROOT(mp, LK_EXCLUSIVE, &fsrootvp, td) == 0) {
1244 if (mp->mnt_vnodecovered != NULL)
1245 mountcheckdirs(mp->mnt_vnodecovered, fsrootvp);
1246 if (rootvnode == NULL) {
1247 rootvnode = fsrootvp;
1248 vref(rootvnode);
1249 }
1250 vput(fsrootvp);
1251 }
1252 if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL)
1253 (void) vfs_allocate_syncvnode(mp);
1254 MNT_ILOCK(mp);
1255 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
1256 mp->mnt_flag |= async_flag;
1257 lockmgr(&mp->mnt_lock, LK_RELEASE, NULL, td);
1258 if (mp->mnt_kern_flag & MNTK_MWAIT)
1259 wakeup(mp);
1260 MNT_IUNLOCK(mp);
1261 if (coveredvp)
1262 VOP_UNLOCK(coveredvp, 0, td);
1263 return (error);
1264 }
1265 mtx_lock(&mountlist_mtx);
1266 TAILQ_REMOVE(&mountlist, mp, mnt_list);
1267 mtx_unlock(&mountlist_mtx);
1268 if (coveredvp != NULL) {
1269 coveredvp->v_mountedhere = NULL;
1270 vput(coveredvp);
1271 }
1272 vfs_event_signal(NULL, VQ_UNMOUNT, 0);
1273 lockmgr(&mp->mnt_lock, LK_RELEASE, NULL, td);
1274 vfs_mount_destroy(mp);
1275 return (0);
1276 }
1277
1278 /*
1279 * ---------------------------------------------------------------------
1280 * Mounting of root filesystem
1281 *
1282 */
1283
1284 struct root_hold_token {
1285 const char *who;
1286 LIST_ENTRY(root_hold_token) list;
1287 };
1288
1289 static LIST_HEAD(, root_hold_token) root_holds =
1290 LIST_HEAD_INITIALIZER(&root_holds);
1291
1292 struct root_hold_token *
1293 root_mount_hold(const char *identifier)
1294 {
1295 struct root_hold_token *h;
1296
1297 h = malloc(sizeof *h, M_DEVBUF, M_ZERO | M_WAITOK);
1298 h->who = identifier;
1299 mtx_lock(&mountlist_mtx);
1300 LIST_INSERT_HEAD(&root_holds, h, list);
1301 mtx_unlock(&mountlist_mtx);
1302 return (h);
1303 }
1304
1305 void
1306 root_mount_rel(struct root_hold_token *h)
1307 {
1308
1309 mtx_lock(&mountlist_mtx);
1310 LIST_REMOVE(h, list);
1311 wakeup(&root_holds);
1312 mtx_unlock(&mountlist_mtx);
1313 free(h, M_DEVBUF);
1314 }
1315
1316 static void
1317 root_mount_wait(void)
1318 {
1319 struct root_hold_token *h;
1320
1321 for (;;) {
1322 DROP_GIANT();
1323 g_waitidle();
1324 PICKUP_GIANT();
1325 mtx_lock(&mountlist_mtx);
1326 if (LIST_EMPTY(&root_holds)) {
1327 mtx_unlock(&mountlist_mtx);
1328 break;
1329 }
1330 printf("Root mount waiting for:");
1331 LIST_FOREACH(h, &root_holds, list)
1332 printf(" %s", h->who);
1333 printf("\n");
1334 msleep(&root_holds, &mountlist_mtx, PZERO | PDROP, "roothold",
1335 hz);
1336 }
1337 }
1338
1339 static void
1340 set_rootvnode(struct thread *td)
1341 {
1342 struct proc *p;
1343
1344 if (VFS_ROOT(TAILQ_FIRST(&mountlist), LK_EXCLUSIVE, &rootvnode, td))
1345 panic("Cannot find root vnode");
1346
1347 p = td->td_proc;
1348 FILEDESC_LOCK(p->p_fd);
1349
1350 if (p->p_fd->fd_cdir != NULL)
1351 vrele(p->p_fd->fd_cdir);
1352 p->p_fd->fd_cdir = rootvnode;
1353 VREF(rootvnode);
1354
1355 if (p->p_fd->fd_rdir != NULL)
1356 vrele(p->p_fd->fd_rdir);
1357 p->p_fd->fd_rdir = rootvnode;
1358 VREF(rootvnode);
1359
1360 FILEDESC_UNLOCK(p->p_fd);
1361
1362 VOP_UNLOCK(rootvnode, 0, td);
1363
1364 EVENTHANDLER_INVOKE(mountroot);
1365 }
1366
1367 /*
1368 * Mount /devfs as our root filesystem, but do not put it on the mountlist
1369 * yet. Create a /dev -> / symlink so that absolute pathnames will lookup.
1370 */
1371
1372 static void
1373 devfs_first(void)
1374 {
1375 struct thread *td = curthread;
1376 struct vfsoptlist *opts;
1377 struct vfsconf *vfsp;
1378 struct mount *mp = NULL;
1379 int error;
1380
1381 vfsp = vfs_byname("devfs");
1382 KASSERT(vfsp != NULL, ("Could not find devfs by name"));
1383 if (vfsp == NULL)
1384 return;
1385
1386 error = vfs_mount_alloc(NULLVP, vfsp, "/dev", td, &mp);
1387 KASSERT(error == 0, ("vfs_mount_alloc failed %d", error));
1388 if (error)
1389 return;
1390
1391 error = VFS_MOUNT(mp, curthread);
1392 KASSERT(error == 0, ("VFS_MOUNT(devfs) failed %d", error));
1393 if (error)
1394 return;
1395
1396 opts = malloc(sizeof(struct vfsoptlist), M_MOUNT, M_WAITOK);
1397 TAILQ_INIT(opts);
1398 mp->mnt_opt = opts;
1399
1400 mtx_lock(&mountlist_mtx);
1401 TAILQ_INSERT_HEAD(&mountlist, mp, mnt_list);
1402 mtx_unlock(&mountlist_mtx);
1403
1404 set_rootvnode(td);
1405
1406 error = kern_symlink(td, "/", "dev", UIO_SYSSPACE);
1407 if (error)
1408 printf("kern_symlink /dev -> / returns %d\n", error);
1409 }
1410
1411 /*
1412 * Surgically move our devfs to be mounted on /dev.
1413 */
1414
1415 static void
1416 devfs_fixup(struct thread *td)
1417 {
1418 struct nameidata nd;
1419 int error;
1420 struct vnode *vp, *dvp;
1421 struct mount *mp;
1422
1423 /* Remove our devfs mount from the mountlist and purge the cache */
1424 mtx_lock(&mountlist_mtx);
1425 mp = TAILQ_FIRST(&mountlist);
1426 TAILQ_REMOVE(&mountlist, mp, mnt_list);
1427 mtx_unlock(&mountlist_mtx);
1428 cache_purgevfs(mp);
1429
1430 VFS_ROOT(mp, LK_EXCLUSIVE, &dvp, td);
1431 VI_LOCK(dvp);
1432 dvp->v_iflag &= ~VI_MOUNT;
1433 dvp->v_mountedhere = NULL;
1434 VI_UNLOCK(dvp);
1435
1436 /* Set up the real rootvnode, and purge the cache */
1437 TAILQ_FIRST(&mountlist)->mnt_vnodecovered = NULL;
1438 set_rootvnode(td);
1439 cache_purgevfs(rootvnode->v_mount);
1440
1441 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, "/dev", td);
1442 error = namei(&nd);
1443 if (error) {
1444 printf("Lookup of /dev for devfs, error: %d\n", error);
1445 return;
1446 }
1447 NDFREE(&nd, NDF_ONLY_PNBUF);
1448 vp = nd.ni_vp;
1449 if (vp->v_type != VDIR) {
1450 vput(vp);
1451 }
1452 error = vinvalbuf(vp, V_SAVE, td, 0, 0);
1453 if (error) {
1454 vput(vp);
1455 }
1456 cache_purge(vp);
1457 mp->mnt_vnodecovered = vp;
1458 vp->v_mountedhere = mp;
1459 mtx_lock(&mountlist_mtx);
1460 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
1461 mtx_unlock(&mountlist_mtx);
1462 VOP_UNLOCK(vp, 0, td);
1463 vput(dvp);
1464 vfs_unbusy(mp, td);
1465
1466 /* Unlink the no longer needed /dev/dev -> / symlink */
1467 kern_unlink(td, "/dev/dev", UIO_SYSSPACE);
1468 }
1469
1470 /*
1471 * Report errors during filesystem mounting.
1472 */
1473 void
1474 vfs_mount_error(struct mount *mp, const char *fmt, ...)
1475 {
1476 struct vfsoptlist *moptlist = mp->mnt_optnew;
1477 va_list ap;
1478 int error, len;
1479 char *errmsg;
1480
1481 error = vfs_getopt(moptlist, "errmsg", (void **)&errmsg, &len);
1482 if (error || errmsg == NULL || len <= 0) {
1483 return;
1484 }
1485
1486 va_start(ap, fmt);
1487 vsnprintf(errmsg, (size_t)len, fmt, ap);
1488 va_end(ap);
1489 }
1490
1491 /*
1492 * Find and mount the root filesystem
1493 */
1494 void
1495 vfs_mountroot(void)
1496 {
1497 char *cp;
1498 int error, i, asked = 0;
1499
1500 root_mount_wait();
1501
1502 mount_zone = uma_zcreate("Mountpoints", sizeof(struct mount),
1503 NULL, NULL, mount_init, mount_fini,
1504 UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
1505 devfs_first();
1506
1507 /*
1508 * We are booted with instructions to prompt for the root filesystem.
1509 */
1510 if (boothowto & RB_ASKNAME) {
1511 if (!vfs_mountroot_ask())
1512 return;
1513 asked = 1;
1514 }
1515
1516 /*
1517 * The root filesystem information is compiled in, and we are
1518 * booted with instructions to use it.
1519 */
1520 if (ctrootdevname != NULL && (boothowto & RB_DFLTROOT)) {
1521 if (!vfs_mountroot_try(ctrootdevname))
1522 return;
1523 ctrootdevname = NULL;
1524 }
1525
1526 /*
1527 * We've been given the generic "use CDROM as root" flag. This is
1528 * necessary because one media may be used in many different
1529 * devices, so we need to search for them.
1530 */
1531 if (boothowto & RB_CDROM) {
1532 for (i = 0; cdrom_rootdevnames[i] != NULL; i++) {
1533 if (!vfs_mountroot_try(cdrom_rootdevnames[i]))
1534 return;
1535 }
1536 }
1537
1538 /*
1539 * Try to use the value read by the loader from /etc/fstab, or
1540 * supplied via some other means. This is the preferred
1541 * mechanism.
1542 */
1543 cp = getenv("vfs.root.mountfrom");
1544 if (cp != NULL) {
1545 error = vfs_mountroot_try(cp);
1546 freeenv(cp);
1547 if (!error)
1548 return;
1549 }
1550
1551 /*
1552 * Try values that may have been computed by code during boot
1553 */
1554 if (!vfs_mountroot_try(rootdevnames[0]))
1555 return;
1556 if (!vfs_mountroot_try(rootdevnames[1]))
1557 return;
1558
1559 /*
1560 * If we (still) have a compiled-in default, try it.
1561 */
1562 if (ctrootdevname != NULL)
1563 if (!vfs_mountroot_try(ctrootdevname))
1564 return;
1565 /*
1566 * Everything so far has failed, prompt on the console if we haven't
1567 * already tried that.
1568 */
1569 if (!asked)
1570 if (!vfs_mountroot_ask())
1571 return;
1572
1573 panic("Root mount failed, startup aborted.");
1574 }
1575
1576 /*
1577 * Mount (mountfrom) as the root filesystem.
1578 */
1579 static int
1580 vfs_mountroot_try(const char *mountfrom)
1581 {
1582 struct mount *mp;
1583 char *vfsname, *path;
1584 time_t timebase;
1585 int error;
1586 char patt[32];
1587
1588 vfsname = NULL;
1589 path = NULL;
1590 mp = NULL;
1591 error = EINVAL;
1592
1593 if (mountfrom == NULL)
1594 return (error); /* don't complain */
1595 printf("Trying to mount root from %s\n", mountfrom);
1596
1597 /* parse vfs name and path */
1598 vfsname = malloc(MFSNAMELEN, M_MOUNT, M_WAITOK);
1599 path = malloc(MNAMELEN, M_MOUNT, M_WAITOK);
1600 vfsname[0] = path[0] = 0;
1601 sprintf(patt, "%%%d[a-z0-9]:%%%ds", MFSNAMELEN, MNAMELEN);
1602 if (sscanf(mountfrom, patt, vfsname, path) < 1)
1603 goto out;
1604
1605 if (path[0] == '\0')
1606 strcpy(path, ROOTNAME);
1607
1608 error = kernel_vmount(
1609 MNT_RDONLY | MNT_ROOTFS,
1610 "fstype", vfsname,
1611 "fspath", "/",
1612 "from", path,
1613 NULL);
1614 if (error == 0) {
1615 /*
1616 * We mount devfs prior to mounting the / FS, so the first
1617 * entry will typically be devfs.
1618 */
1619 mp = TAILQ_FIRST(&mountlist);
1620 KASSERT(mp != NULL, ("%s: mountlist is empty", __func__));
1621
1622 /*
1623 * Iterate over all currently mounted file systems and use
1624 * the time stamp found to check and/or initialize the RTC.
1625 * Typically devfs has no time stamp and the only other FS
1626 * is the actual / FS.
1627 * Call inittodr() only once and pass it the largest of the
1628 * timestamps we encounter.
1629 */
1630 timebase = 0;
1631 do {
1632 if (mp->mnt_time > timebase)
1633 timebase = mp->mnt_time;
1634 mp = TAILQ_NEXT(mp, mnt_list);
1635 } while (mp != NULL);
1636 inittodr(timebase);
1637
1638 devfs_fixup(curthread);
1639 }
1640 out:
1641 free(path, M_MOUNT);
1642 free(vfsname, M_MOUNT);
1643 return (error);
1644 }
1645
1646 /*
1647 * ---------------------------------------------------------------------
1648 * Interactive root filesystem selection code.
1649 */
1650
1651 static int
1652 vfs_mountroot_ask(void)
1653 {
1654 char name[128];
1655
1656 for(;;) {
1657 printf("\nManual root filesystem specification:\n");
1658 printf(" <fstype>:<device> Mount <device> using filesystem <fstype>\n");
1659 #if defined(__i386__) || defined(__ia64__)
1660 printf(" eg. ufs:da0s1a\n");
1661 #else
1662 printf(" eg. ufs:/dev/da0a\n");
1663 #endif
1664 printf(" ? List valid disk boot devices\n");
1665 printf(" <empty line> Abort manual input\n");
1666 printf("\nmountroot> ");
1667 gets(name, sizeof(name), 1);
1668 if (name[0] == '\0')
1669 return (1);
1670 if (name[0] == '?') {
1671 printf("\nList of GEOM managed disk devices:\n ");
1672 g_dev_print();
1673 continue;
1674 }
1675 if (!vfs_mountroot_try(name))
1676 return (0);
1677 }
1678 }
1679
1680 /*
1681 * ---------------------------------------------------------------------
1682 * Functions for querying mount options/arguments from filesystems.
1683 */
1684
1685 /*
1686 * Check that no unknown options are given
1687 */
1688 int
1689 vfs_filteropt(struct vfsoptlist *opts, const char **legal)
1690 {
1691 struct vfsopt *opt;
1692 const char **t, *p;
1693
1694
1695 TAILQ_FOREACH(opt, opts, link) {
1696 p = opt->name;
1697 if (p[0] == 'n' && p[1] == 'o')
1698 p += 2;
1699 for(t = global_opts; *t != NULL; t++)
1700 if (!strcmp(*t, p))
1701 break;
1702 if (*t != NULL)
1703 continue;
1704 for(t = legal; *t != NULL; t++)
1705 if (!strcmp(*t, p))
1706 break;
1707 if (*t != NULL)
1708 continue;
1709 printf("mount option <%s> is unknown\n", p);
1710 return (EINVAL);
1711 }
1712 return (0);
1713 }
1714
1715 /*
1716 * Get a mount option by its name.
1717 *
1718 * Return 0 if the option was found, ENOENT otherwise.
1719 * If len is non-NULL it will be filled with the length
1720 * of the option. If buf is non-NULL, it will be filled
1721 * with the address of the option.
1722 */
1723 int
1724 vfs_getopt(opts, name, buf, len)
1725 struct vfsoptlist *opts;
1726 const char *name;
1727 void **buf;
1728 int *len;
1729 {
1730 struct vfsopt *opt;
1731
1732 KASSERT(opts != NULL, ("vfs_getopt: caller passed 'opts' as NULL"));
1733
1734 TAILQ_FOREACH(opt, opts, link) {
1735 if (strcmp(name, opt->name) == 0) {
1736 if (len != NULL)
1737 *len = opt->len;
1738 if (buf != NULL)
1739 *buf = opt->value;
1740 return (0);
1741 }
1742 }
1743 return (ENOENT);
1744 }
1745
1746 static int
1747 vfs_getopt_pos(struct vfsoptlist *opts, const char *name)
1748 {
1749 struct vfsopt *opt;
1750 int i;
1751
1752 if (opts == NULL)
1753 return (-1);
1754
1755 i = 0;
1756 TAILQ_FOREACH(opt, opts, link) {
1757 if (strcmp(name, opt->name) == 0)
1758 return (i);
1759 ++i;
1760 }
1761 return (-1);
1762 }
1763
1764 char *
1765 vfs_getopts(struct vfsoptlist *opts, const char *name, int *error)
1766 {
1767 struct vfsopt *opt;
1768
1769 *error = 0;
1770 TAILQ_FOREACH(opt, opts, link) {
1771 if (strcmp(name, opt->name) != 0)
1772 continue;
1773 if (((char *)opt->value)[opt->len - 1] != '\0') {
1774 *error = EINVAL;
1775 return (NULL);
1776 }
1777 return (opt->value);
1778 }
1779 return (NULL);
1780 }
1781
1782 int
1783 vfs_flagopt(struct vfsoptlist *opts, const char *name, u_int *w, u_int val)
1784 {
1785 struct vfsopt *opt;
1786
1787 TAILQ_FOREACH(opt, opts, link) {
1788 if (strcmp(name, opt->name) == 0) {
1789 if (w != NULL)
1790 *w |= val;
1791 return (1);
1792 }
1793 }
1794 if (w != NULL)
1795 *w &= ~val;
1796 return (0);
1797 }
1798
1799 int
1800 vfs_scanopt(struct vfsoptlist *opts, const char *name, const char *fmt, ...)
1801 {
1802 va_list ap;
1803 struct vfsopt *opt;
1804 int ret;
1805
1806 KASSERT(opts != NULL, ("vfs_getopt: caller passed 'opts' as NULL"));
1807
1808 TAILQ_FOREACH(opt, opts, link) {
1809 if (strcmp(name, opt->name) != 0)
1810 continue;
1811 if (((char *)opt->value)[opt->len - 1] != '\0')
1812 return (0);
1813 va_start(ap, fmt);
1814 ret = vsscanf(opt->value, fmt, ap);
1815 va_end(ap);
1816 return (ret);
1817 }
1818 return (0);
1819 }
1820
1821 /*
1822 * Find and copy a mount option.
1823 *
1824 * The size of the buffer has to be specified
1825 * in len, if it is not the same length as the
1826 * mount option, EINVAL is returned.
1827 * Returns ENOENT if the option is not found.
1828 */
1829 int
1830 vfs_copyopt(opts, name, dest, len)
1831 struct vfsoptlist *opts;
1832 const char *name;
1833 void *dest;
1834 int len;
1835 {
1836 struct vfsopt *opt;
1837
1838 KASSERT(opts != NULL, ("vfs_copyopt: caller passed 'opts' as NULL"));
1839
1840 TAILQ_FOREACH(opt, opts, link) {
1841 if (strcmp(name, opt->name) == 0) {
1842 if (len != opt->len)
1843 return (EINVAL);
1844 bcopy(opt->value, dest, opt->len);
1845 return (0);
1846 }
1847 }
1848 return (ENOENT);
1849 }
1850
1851 /*
1852 * This is a helper function for filesystems to traverse their
1853 * vnodes. See MNT_VNODE_FOREACH() in sys/mount.h
1854 */
1855
1856 struct vnode *
1857 __mnt_vnode_next(struct vnode **mvp, struct mount *mp)
1858 {
1859 struct vnode *vp;
1860
1861 mtx_assert(MNT_MTX(mp), MA_OWNED);
1862
1863 KASSERT((*mvp)->v_mount == mp, ("marker vnode mount list mismatch"));
1864 vp = TAILQ_NEXT(*mvp, v_nmntvnodes);
1865 while (vp != NULL && vp->v_type == VMARKER)
1866 vp = TAILQ_NEXT(vp, v_nmntvnodes);
1867
1868 /* Check if we are done */
1869 if (vp == NULL) {
1870 __mnt_vnode_markerfree(mvp, mp);
1871 return (NULL);
1872 }
1873 TAILQ_REMOVE(&mp->mnt_nvnodelist, *mvp, v_nmntvnodes);
1874 TAILQ_INSERT_AFTER(&mp->mnt_nvnodelist, vp, *mvp, v_nmntvnodes);
1875 return (vp);
1876 }
1877
1878 struct vnode *
1879 __mnt_vnode_first(struct vnode **mvp, struct mount *mp)
1880 {
1881 struct vnode *vp;
1882
1883 mtx_assert(MNT_MTX(mp), MA_OWNED);
1884
1885 vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
1886 while (vp != NULL && vp->v_type == VMARKER)
1887 vp = TAILQ_NEXT(vp, v_nmntvnodes);
1888
1889 /* Check if we are done */
1890 if (vp == NULL) {
1891 *mvp = NULL;
1892 return (NULL);
1893 }
1894 mp->mnt_holdcnt++;
1895 MNT_IUNLOCK(mp);
1896 *mvp = (struct vnode *) malloc(sizeof(struct vnode),
1897 M_VNODE_MARKER,
1898 M_WAITOK | M_ZERO);
1899 MNT_ILOCK(mp);
1900 (*mvp)->v_type = VMARKER;
1901
1902 vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
1903 while (vp != NULL && vp->v_type == VMARKER)
1904 vp = TAILQ_NEXT(vp, v_nmntvnodes);
1905
1906 /* Check if we are done */
1907 if (vp == NULL) {
1908 MNT_IUNLOCK(mp);
1909 free(*mvp, M_VNODE_MARKER);
1910 MNT_ILOCK(mp);
1911 *mvp = NULL;
1912 mp->mnt_holdcnt--;
1913 if (mp->mnt_holdcnt == 0 && mp->mnt_holdcntwaiters != 0)
1914 wakeup(&mp->mnt_holdcnt);
1915 return (NULL);
1916 }
1917 mp->mnt_markercnt++;
1918 (*mvp)->v_mount = mp;
1919 TAILQ_INSERT_AFTER(&mp->mnt_nvnodelist, vp, *mvp, v_nmntvnodes);
1920 return (vp);
1921 }
1922
1923
1924 void
1925 __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp)
1926 {
1927
1928 if (*mvp == NULL)
1929 return;
1930
1931 mtx_assert(MNT_MTX(mp), MA_OWNED);
1932
1933 KASSERT((*mvp)->v_mount == mp, ("marker vnode mount list mismatch"));
1934 TAILQ_REMOVE(&mp->mnt_nvnodelist, *mvp, v_nmntvnodes);
1935 MNT_IUNLOCK(mp);
1936 free(*mvp, M_VNODE_MARKER);
1937 MNT_ILOCK(mp);
1938 *mvp = NULL;
1939
1940 mp->mnt_markercnt--;
1941 mp->mnt_holdcnt--;
1942 if (mp->mnt_holdcnt == 0 && mp->mnt_holdcntwaiters != 0)
1943 wakeup(&mp->mnt_holdcnt);
1944 }
1945
1946
1947 int
1948 __vfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
1949 {
1950 int error;
1951
1952 error = mp->mnt_op->vfs_statfs(mp, &mp->mnt_stat, td);
1953 if (sbp != &mp->mnt_stat)
1954 *sbp = mp->mnt_stat;
1955 return (error);
1956 }
1957
1958 void
1959 vfs_mountedfrom(struct mount *mp, const char *from)
1960 {
1961
1962 bzero(mp->mnt_stat.f_mntfromname, sizeof mp->mnt_stat.f_mntfromname);
1963 strlcpy(mp->mnt_stat.f_mntfromname, from,
1964 sizeof mp->mnt_stat.f_mntfromname);
1965 }
1966
1967 /*
1968 * ---------------------------------------------------------------------
1969 * This is the api for building mount args and mounting filesystems from
1970 * inside the kernel.
1971 *
1972 * The API works by accumulation of individual args. First error is
1973 * latched.
1974 *
1975 * XXX: should be documented in new manpage kernel_mount(9)
1976 */
1977
1978 /* A memory allocation which must be freed when we are done */
1979 struct mntaarg {
1980 SLIST_ENTRY(mntaarg) next;
1981 };
1982
1983 /* The header for the mount arguments */
1984 struct mntarg {
1985 struct iovec *v;
1986 int len;
1987 int error;
1988 SLIST_HEAD(, mntaarg) list;
1989 };
1990
1991 /*
1992 * Add a boolean argument.
1993 *
1994 * flag is the boolean value.
1995 * name must start with "no".
1996 */
1997 struct mntarg *
1998 mount_argb(struct mntarg *ma, int flag, const char *name)
1999 {
2000
2001 KASSERT(name[0] == 'n' && name[1] == 'o',
2002 ("mount_argb(...,%s): name must start with 'no'", name));
2003
2004 return (mount_arg(ma, name + (flag ? 2 : 0), NULL, 0));
2005 }
2006
2007 /*
2008 * Add an argument printf style
2009 */
2010 struct mntarg *
2011 mount_argf(struct mntarg *ma, const char *name, const char *fmt, ...)
2012 {
2013 va_list ap;
2014 struct mntaarg *maa;
2015 struct sbuf *sb;
2016 int len;
2017
2018 if (ma == NULL) {
2019 ma = malloc(sizeof *ma, M_MOUNT, M_WAITOK | M_ZERO);
2020 SLIST_INIT(&ma->list);
2021 }
2022 if (ma->error)
2023 return (ma);
2024
2025 ma->v = realloc(ma->v, sizeof *ma->v * (ma->len + 2),
2026 M_MOUNT, M_WAITOK);
2027 ma->v[ma->len].iov_base = (void *)(uintptr_t)name;
2028 ma->v[ma->len].iov_len = strlen(name) + 1;
2029 ma->len++;
2030
2031 sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
2032 va_start(ap, fmt);
2033 sbuf_vprintf(sb, fmt, ap);
2034 va_end(ap);
2035 sbuf_finish(sb);
2036 len = sbuf_len(sb) + 1;
2037 maa = malloc(sizeof *maa + len, M_MOUNT, M_WAITOK | M_ZERO);
2038 SLIST_INSERT_HEAD(&ma->list, maa, next);
2039 bcopy(sbuf_data(sb), maa + 1, len);
2040 sbuf_delete(sb);
2041
2042 ma->v[ma->len].iov_base = maa + 1;
2043 ma->v[ma->len].iov_len = len;
2044 ma->len++;
2045
2046 return (ma);
2047 }
2048
2049 /*
2050 * Add an argument which is a userland string.
2051 */
2052 struct mntarg *
2053 mount_argsu(struct mntarg *ma, const char *name, const void *val, int len)
2054 {
2055 struct mntaarg *maa;
2056 char *tbuf;
2057
2058 if (val == NULL)
2059 return (ma);
2060 if (ma == NULL) {
2061 ma = malloc(sizeof *ma, M_MOUNT, M_WAITOK | M_ZERO);
2062 SLIST_INIT(&ma->list);
2063 }
2064 if (ma->error)
2065 return (ma);
2066 maa = malloc(sizeof *maa + len, M_MOUNT, M_WAITOK | M_ZERO);
2067 SLIST_INSERT_HEAD(&ma->list, maa, next);
2068 tbuf = (void *)(maa + 1);
2069 ma->error = copyinstr(val, tbuf, len, NULL);
2070 return (mount_arg(ma, name, tbuf, -1));
2071 }
2072
2073 /*
2074 * Plain argument.
2075 *
2076 * If length is -1, use printf.
2077 */
2078 struct mntarg *
2079 mount_arg(struct mntarg *ma, const char *name, const void *val, int len)
2080 {
2081
2082 if (ma == NULL) {
2083 ma = malloc(sizeof *ma, M_MOUNT, M_WAITOK | M_ZERO);
2084 SLIST_INIT(&ma->list);
2085 }
2086 if (ma->error)
2087 return (ma);
2088
2089 ma->v = realloc(ma->v, sizeof *ma->v * (ma->len + 2),
2090 M_MOUNT, M_WAITOK);
2091 ma->v[ma->len].iov_base = (void *)(uintptr_t)name;
2092 ma->v[ma->len].iov_len = strlen(name) + 1;
2093 ma->len++;
2094
2095 ma->v[ma->len].iov_base = (void *)(uintptr_t)val;
2096 if (len < 0)
2097 ma->v[ma->len].iov_len = strlen(val) + 1;
2098 else
2099 ma->v[ma->len].iov_len = len;
2100 ma->len++;
2101 return (ma);
2102 }
2103
2104 /*
2105 * Free a mntarg structure
2106 */
2107 static void
2108 free_mntarg(struct mntarg *ma)
2109 {
2110 struct mntaarg *maa;
2111
2112 while (!SLIST_EMPTY(&ma->list)) {
2113 maa = SLIST_FIRST(&ma->list);
2114 SLIST_REMOVE_HEAD(&ma->list, next);
2115 free(maa, M_MOUNT);
2116 }
2117 free(ma->v, M_MOUNT);
2118 free(ma, M_MOUNT);
2119 }
2120
2121 /*
2122 * Mount a filesystem
2123 */
2124 int
2125 kernel_mount(struct mntarg *ma, int flags)
2126 {
2127 struct uio auio;
2128 int error;
2129
2130 KASSERT(ma != NULL, ("kernel_mount NULL ma"));
2131 KASSERT(ma->v != NULL, ("kernel_mount NULL ma->v"));
2132 KASSERT(!(ma->len & 1), ("kernel_mount odd ma->len (%d)", ma->len));
2133
2134 auio.uio_iov = ma->v;
2135 auio.uio_iovcnt = ma->len;
2136 auio.uio_segflg = UIO_SYSSPACE;
2137
2138 error = ma->error;
2139 if (!error)
2140 error = vfs_donmount(curthread, flags, &auio);
2141 free_mntarg(ma);
2142 return (error);
2143 }
2144
2145 /*
2146 * A printflike function to mount a filesystem.
2147 */
2148 int
2149 kernel_vmount(int flags, ...)
2150 {
2151 struct mntarg *ma = NULL;
2152 va_list ap;
2153 const char *cp;
2154 const void *vp;
2155 int error;
2156
2157 va_start(ap, flags);
2158 for (;;) {
2159 cp = va_arg(ap, const char *);
2160 if (cp == NULL)
2161 break;
2162 vp = va_arg(ap, const void *);
2163 ma = mount_arg(ma, cp, vp, -1);
2164 }
2165 va_end(ap);
2166
2167 error = kernel_mount(ma, flags);
2168 return (error);
2169 }
Cache object: 5fcad4b855c006ec0f17a40a112f4973
|