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