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.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
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.
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
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD$");
40 #include <sys/param.h>
42 #include <sys/fcntl.h>
44 #include <sys/kernel.h>
45 #include <sys/libkern.h>
46 #include <sys/malloc.h>
47 #include <sys/mount.h>
48 #include <sys/mutex.h>
49 #include <sys/namei.h>
52 #include <sys/filedesc.h>
53 #include <sys/reboot.h>
55 #include <sys/syscallsubr.h>
56 #include <sys/sysproto.h>
58 #include <sys/sysctl.h>
59 #include <sys/sysent.h>
60 #include <sys/systm.h>
61 #include <sys/vnode.h>
64 #include <geom/geom.h>
66 #include <machine/stdarg.h>
68 #include <security/audit/audit.h>
69 #include <security/mac/mac_framework.h>
71 #define VFS_MOUNTARG_SIZE_MAX (1024 * 64)
73 static int vfs_domount(struct thread
*td
, const char *fstype
, char *fspath
,
74 uint64_t fsflags
, struct vfsoptlist
**optlist
);
75 static void free_mntarg(struct mntarg
*ma
);
77 static int usermount
= 0;
78 SYSCTL_INT(_vfs
, OID_AUTO
, usermount
, CTLFLAG_RW
, &usermount
, 0,
79 "Unprivileged users may mount and unmount file systems");
81 MALLOC_DEFINE(M_MOUNT
, "mount", "vfs mount structure");
82 static uma_zone_t mount_zone
;
84 /* List of mounted filesystems. */
85 struct mntlist mountlist
= TAILQ_HEAD_INITIALIZER(mountlist
);
87 /* For any iteration/modification of mountlist */
88 struct mtx mountlist_mtx
;
89 MTX_SYSINIT(mountlist
, &mountlist_mtx
, "mountlist", MTX_DEF
);
92 * Global opts, taken by all filesystems
94 static const char *global_opts
[] = {
106 mount_init(void *mem
, int size
, int flags
)
110 mp
= (struct mount
*)mem
;
111 mtx_init(&mp
->mnt_mtx
, "struct mount mtx", NULL
, MTX_DEF
);
112 lockinit(&mp
->mnt_explock
, PVFS
, "explock", 0, 0);
117 mount_fini(void *mem
, int size
)
121 mp
= (struct mount
*)mem
;
122 lockdestroy(&mp
->mnt_explock
);
123 mtx_destroy(&mp
->mnt_mtx
);
127 vfs_mount_init(void *dummy __unused
)
130 mount_zone
= uma_zcreate("Mountpoints", sizeof(struct mount
), NULL
,
131 NULL
, mount_init
, mount_fini
, UMA_ALIGN_PTR
, UMA_ZONE_NOFREE
);
133 SYSINIT(vfs_mount
, SI_SUB_VFS
, SI_ORDER_ANY
, vfs_mount_init
, NULL
);
136 * ---------------------------------------------------------------------
137 * Functions for building and sanitizing the mount options
140 /* Remove one mount option. */
142 vfs_freeopt(struct vfsoptlist
*opts
, struct vfsopt
*opt
)
145 TAILQ_REMOVE(opts
, opt
, link
);
146 free(opt
->name
, M_MOUNT
);
147 if (opt
->value
!= NULL
)
148 free(opt
->value
, M_MOUNT
);
152 /* Release all resources related to the mount options. */
154 vfs_freeopts(struct vfsoptlist
*opts
)
158 while (!TAILQ_EMPTY(opts
)) {
159 opt
= TAILQ_FIRST(opts
);
160 vfs_freeopt(opts
, opt
);
166 vfs_deleteopt(struct vfsoptlist
*opts
, const char *name
)
168 struct vfsopt
*opt
, *temp
;
172 TAILQ_FOREACH_SAFE(opt
, opts
, link
, temp
) {
173 if (strcmp(opt
->name
, name
) == 0)
174 vfs_freeopt(opts
, opt
);
179 vfs_isopt_ro(const char *opt
)
182 if (strcmp(opt
, "ro") == 0 || strcmp(opt
, "rdonly") == 0 ||
183 strcmp(opt
, "norw") == 0)
189 vfs_isopt_rw(const char *opt
)
192 if (strcmp(opt
, "rw") == 0 || strcmp(opt
, "noro") == 0)
198 * Check if options are equal (with or without the "no" prefix).
201 vfs_equalopts(const char *opt1
, const char *opt2
)
205 /* "opt" vs. "opt" or "noopt" vs. "noopt" */
206 if (strcmp(opt1
, opt2
) == 0)
208 /* "noopt" vs. "opt" */
209 if (strncmp(opt1
, "no", 2) == 0 && strcmp(opt1
+ 2, opt2
) == 0)
211 /* "opt" vs. "noopt" */
212 if (strncmp(opt2
, "no", 2) == 0 && strcmp(opt1
, opt2
+ 2) == 0)
214 while ((p
= strchr(opt1
, '.')) != NULL
&&
215 !strncmp(opt1
, opt2
, ++p
- opt1
)) {
218 /* "foo.noopt" vs. "foo.opt" */
219 if (strncmp(opt1
, "no", 2) == 0 && strcmp(opt1
+ 2, opt2
) == 0)
221 /* "foo.opt" vs. "foo.noopt" */
222 if (strncmp(opt2
, "no", 2) == 0 && strcmp(opt1
, opt2
+ 2) == 0)
225 /* "ro" / "rdonly" / "norw" / "rw" / "noro" */
226 if ((vfs_isopt_ro(opt1
) || vfs_isopt_rw(opt1
)) &&
227 (vfs_isopt_ro(opt2
) || vfs_isopt_rw(opt2
)))
233 * If a mount option is specified several times,
234 * (with or without the "no" prefix) only keep
235 * the last occurrence of it.
238 vfs_sanitizeopts(struct vfsoptlist
*opts
)
240 struct vfsopt
*opt
, *opt2
, *tmp
;
242 TAILQ_FOREACH_REVERSE(opt
, opts
, vfsoptlist
, link
) {
243 opt2
= TAILQ_PREV(opt
, vfsoptlist
, link
);
244 while (opt2
!= NULL
) {
245 if (vfs_equalopts(opt
->name
, opt2
->name
)) {
246 tmp
= TAILQ_PREV(opt2
, vfsoptlist
, link
);
247 vfs_freeopt(opts
, opt2
);
250 opt2
= TAILQ_PREV(opt2
, vfsoptlist
, link
);
257 * Build a linked list of mount options from a struct uio.
260 vfs_buildopts(struct uio
*auio
, struct vfsoptlist
**options
)
262 struct vfsoptlist
*opts
;
264 size_t memused
, namelen
, optlen
;
265 unsigned int i
, iovcnt
;
268 opts
= malloc(sizeof(struct vfsoptlist
), M_MOUNT
, M_WAITOK
);
271 iovcnt
= auio
->uio_iovcnt
;
272 for (i
= 0; i
< iovcnt
; i
+= 2) {
273 namelen
= auio
->uio_iov
[i
].iov_len
;
274 optlen
= auio
->uio_iov
[i
+ 1].iov_len
;
275 memused
+= sizeof(struct vfsopt
) + optlen
+ namelen
;
277 * Avoid consuming too much memory, and attempts to overflow
280 if (memused
> VFS_MOUNTARG_SIZE_MAX
||
281 optlen
> VFS_MOUNTARG_SIZE_MAX
||
282 namelen
> VFS_MOUNTARG_SIZE_MAX
) {
287 opt
= malloc(sizeof(struct vfsopt
), M_MOUNT
, M_WAITOK
);
288 opt
->name
= malloc(namelen
, M_MOUNT
, M_WAITOK
);
295 * Do this early, so jumps to "bad" will free the current
298 TAILQ_INSERT_TAIL(opts
, opt
, link
);
300 if (auio
->uio_segflg
== UIO_SYSSPACE
) {
301 bcopy(auio
->uio_iov
[i
].iov_base
, opt
->name
, namelen
);
303 error
= copyin(auio
->uio_iov
[i
].iov_base
, opt
->name
,
308 /* Ensure names are null-terminated strings. */
309 if (namelen
== 0 || opt
->name
[namelen
- 1] != '\0') {
315 opt
->value
= malloc(optlen
, M_MOUNT
, M_WAITOK
);
316 if (auio
->uio_segflg
== UIO_SYSSPACE
) {
317 bcopy(auio
->uio_iov
[i
+ 1].iov_base
, opt
->value
,
320 error
= copyin(auio
->uio_iov
[i
+ 1].iov_base
,
327 vfs_sanitizeopts(opts
);
336 * Merge the old mount options with the new ones passed
337 * in the MNT_UPDATE case.
339 * XXX: This function will keep a "nofoo" option in the new
340 * options. E.g, if the option's canonical name is "foo",
341 * "nofoo" ends up in the mount point's active options.
344 vfs_mergeopts(struct vfsoptlist
*toopts
, struct vfsoptlist
*oldopts
)
346 struct vfsopt
*opt
, *new;
348 TAILQ_FOREACH(opt
, oldopts
, link
) {
349 new = malloc(sizeof(struct vfsopt
), M_MOUNT
, M_WAITOK
);
350 new->name
= strdup(opt
->name
, M_MOUNT
);
352 new->value
= malloc(opt
->len
, M_MOUNT
, M_WAITOK
);
353 bcopy(opt
->value
, new->value
, opt
->len
);
357 new->seen
= opt
->seen
;
358 TAILQ_INSERT_HEAD(toopts
, new, link
);
360 vfs_sanitizeopts(toopts
);
364 * Mount a filesystem.
369 struct nmount_args
/* {
381 * Mount flags are now 64-bits. On 32-bit archtectures only
382 * 32-bits are passed in, but from here on everything handles
383 * 64-bit flags correctly.
387 AUDIT_ARG_FFLAGS(flags
);
388 CTR4(KTR_VFS
, "%s: iovp %p with iovcnt %d and flags %d", __func__
,
389 uap
->iovp
, uap
->iovcnt
, flags
);
392 * Filter out MNT_ROOTFS. We do not want clients of nmount() in
393 * userspace to set this flag, but we must filter it out if we want
394 * MNT_UPDATE on the root file system to work.
395 * MNT_ROOTFS should only be set by the kernel when mounting its
398 flags
&= ~MNT_ROOTFS
;
400 iovcnt
= uap
->iovcnt
;
402 * Check that we have an even number of iovec's
403 * and that we have at least two options.
405 if ((iovcnt
& 1) || (iovcnt
< 4)) {
406 CTR2(KTR_VFS
, "%s: failed for invalid iovcnt %d", __func__
,
411 error
= copyinuio(uap
->iovp
, iovcnt
, &auio
);
413 CTR2(KTR_VFS
, "%s: failed for invalid uio op with %d errno",
417 error
= vfs_donmount(td
, flags
, auio
);
424 * ---------------------------------------------------------------------
425 * Various utility functions
429 vfs_ref(struct mount
*mp
)
432 CTR2(KTR_VFS
, "%s: mp %p", __func__
, mp
);
439 vfs_rel(struct mount
*mp
)
442 CTR2(KTR_VFS
, "%s: mp %p", __func__
, mp
);
449 * Allocate and initialize the mount point struct.
452 vfs_mount_alloc(struct vnode
*vp
, struct vfsconf
*vfsp
, const char *fspath
,
457 mp
= uma_zalloc(mount_zone
, M_WAITOK
);
458 bzero(&mp
->mnt_startzero
,
459 __rangeof(struct mount
, mnt_startzero
, mnt_endzero
));
460 TAILQ_INIT(&mp
->mnt_nvnodelist
);
461 mp
->mnt_nvnodelistsize
= 0;
462 TAILQ_INIT(&mp
->mnt_activevnodelist
);
463 mp
->mnt_activevnodelistsize
= 0;
465 (void) vfs_busy(mp
, MBF_NOWAIT
);
466 atomic_add_acq_int(&vfsp
->vfc_refcount
, 1);
467 mp
->mnt_op
= vfsp
->vfc_vfsops
;
469 mp
->mnt_stat
.f_type
= vfsp
->vfc_typenum
;
471 strlcpy(mp
->mnt_stat
.f_fstypename
, vfsp
->vfc_name
, MFSNAMELEN
);
472 mp
->mnt_vnodecovered
= vp
;
473 mp
->mnt_cred
= crdup(cred
);
474 mp
->mnt_stat
.f_owner
= cred
->cr_uid
;
475 strlcpy(mp
->mnt_stat
.f_mntonname
, fspath
, MNAMELEN
);
476 mp
->mnt_iosize_max
= DFLTPHYS
;
479 mac_mount_create(cred
, mp
);
481 arc4rand(&mp
->mnt_hashseed
, sizeof mp
->mnt_hashseed
, 0);
482 TAILQ_INIT(&mp
->mnt_uppers
);
487 * Destroy the mount struct previously allocated by vfs_mount_alloc().
490 vfs_mount_destroy(struct mount
*mp
)
494 mp
->mnt_kern_flag
|= MNTK_REFEXPIRE
;
495 if (mp
->mnt_kern_flag
& MNTK_MWAIT
) {
496 mp
->mnt_kern_flag
&= ~MNTK_MWAIT
;
500 msleep(mp
, MNT_MTX(mp
), PVFS
, "mntref", 0);
501 KASSERT(mp
->mnt_ref
== 0,
502 ("%s: invalid refcount in the drain path @ %s:%d", __func__
,
503 __FILE__
, __LINE__
));
504 if (mp
->mnt_writeopcount
!= 0)
505 panic("vfs_mount_destroy: nonzero writeopcount");
506 if (mp
->mnt_secondary_writes
!= 0)
507 panic("vfs_mount_destroy: nonzero secondary_writes");
508 atomic_subtract_rel_int(&mp
->mnt_vfc
->vfc_refcount
, 1);
509 if (!TAILQ_EMPTY(&mp
->mnt_nvnodelist
)) {
512 TAILQ_FOREACH(vp
, &mp
->mnt_nvnodelist
, v_nmntvnodes
)
514 panic("unmount: dangling vnode");
516 KASSERT(TAILQ_EMPTY(&mp
->mnt_uppers
), ("mnt_uppers"));
517 if (mp
->mnt_nvnodelistsize
!= 0)
518 panic("vfs_mount_destroy: nonzero nvnodelistsize");
519 if (mp
->mnt_activevnodelistsize
!= 0)
520 panic("vfs_mount_destroy: nonzero activevnodelistsize");
521 if (mp
->mnt_lockref
!= 0)
522 panic("vfs_mount_destroy: nonzero lock refcount");
525 mac_mount_destroy(mp
);
527 if (mp
->mnt_opt
!= NULL
)
528 vfs_freeopts(mp
->mnt_opt
);
529 crfree(mp
->mnt_cred
);
530 uma_zfree(mount_zone
, mp
);
534 vfs_donmount(struct thread
*td
, uint64_t fsflags
, struct uio
*fsoptions
)
536 struct vfsoptlist
*optlist
;
537 struct vfsopt
*opt
, *tmp_opt
;
538 char *fstype
, *fspath
, *errmsg
;
539 int error
, fstypelen
, fspathlen
, errmsg_len
, errmsg_pos
;
541 errmsg
= fspath
= NULL
;
542 errmsg_len
= fspathlen
= 0;
545 error
= vfs_buildopts(fsoptions
, &optlist
);
549 if (vfs_getopt(optlist
, "errmsg", (void **)&errmsg
, &errmsg_len
) == 0)
550 errmsg_pos
= vfs_getopt_pos(optlist
, "errmsg");
553 * We need these two options before the others,
554 * and they are mandatory for any filesystem.
555 * Ensure they are NUL terminated as well.
558 error
= vfs_getopt(optlist
, "fstype", (void **)&fstype
, &fstypelen
);
559 if (error
|| fstype
[fstypelen
- 1] != '\0') {
562 strncpy(errmsg
, "Invalid fstype", errmsg_len
);
566 error
= vfs_getopt(optlist
, "fspath", (void **)&fspath
, &fspathlen
);
567 if (error
|| fspath
[fspathlen
- 1] != '\0') {
570 strncpy(errmsg
, "Invalid fspath", errmsg_len
);
575 * We need to see if we have the "update" option
576 * before we call vfs_domount(), since vfs_domount() has special
577 * logic based on MNT_UPDATE. This is very important
578 * when we want to update the root filesystem.
580 TAILQ_FOREACH_SAFE(opt
, optlist
, link
, tmp_opt
) {
581 if (strcmp(opt
->name
, "update") == 0) {
582 fsflags
|= MNT_UPDATE
;
583 vfs_freeopt(optlist
, opt
);
585 else if (strcmp(opt
->name
, "async") == 0)
586 fsflags
|= MNT_ASYNC
;
587 else if (strcmp(opt
->name
, "force") == 0) {
588 fsflags
|= MNT_FORCE
;
589 vfs_freeopt(optlist
, opt
);
591 else if (strcmp(opt
->name
, "reload") == 0) {
592 fsflags
|= MNT_RELOAD
;
593 vfs_freeopt(optlist
, opt
);
595 else if (strcmp(opt
->name
, "multilabel") == 0)
596 fsflags
|= MNT_MULTILABEL
;
597 else if (strcmp(opt
->name
, "noasync") == 0)
598 fsflags
&= ~MNT_ASYNC
;
599 else if (strcmp(opt
->name
, "noatime") == 0)
600 fsflags
|= MNT_NOATIME
;
601 else if (strcmp(opt
->name
, "atime") == 0) {
602 free(opt
->name
, M_MOUNT
);
603 opt
->name
= strdup("nonoatime", M_MOUNT
);
605 else if (strcmp(opt
->name
, "noclusterr") == 0)
606 fsflags
|= MNT_NOCLUSTERR
;
607 else if (strcmp(opt
->name
, "clusterr") == 0) {
608 free(opt
->name
, M_MOUNT
);
609 opt
->name
= strdup("nonoclusterr", M_MOUNT
);
611 else if (strcmp(opt
->name
, "noclusterw") == 0)
612 fsflags
|= MNT_NOCLUSTERW
;
613 else if (strcmp(opt
->name
, "clusterw") == 0) {
614 free(opt
->name
, M_MOUNT
);
615 opt
->name
= strdup("nonoclusterw", M_MOUNT
);
617 else if (strcmp(opt
->name
, "noexec") == 0)
618 fsflags
|= MNT_NOEXEC
;
619 else if (strcmp(opt
->name
, "exec") == 0) {
620 free(opt
->name
, M_MOUNT
);
621 opt
->name
= strdup("nonoexec", M_MOUNT
);
623 else if (strcmp(opt
->name
, "nosuid") == 0)
624 fsflags
|= MNT_NOSUID
;
625 else if (strcmp(opt
->name
, "suid") == 0) {
626 free(opt
->name
, M_MOUNT
);
627 opt
->name
= strdup("nonosuid", M_MOUNT
);
629 else if (strcmp(opt
->name
, "nosymfollow") == 0)
630 fsflags
|= MNT_NOSYMFOLLOW
;
631 else if (strcmp(opt
->name
, "symfollow") == 0) {
632 free(opt
->name
, M_MOUNT
);
633 opt
->name
= strdup("nonosymfollow", M_MOUNT
);
635 else if (strcmp(opt
->name
, "noro") == 0)
636 fsflags
&= ~MNT_RDONLY
;
637 else if (strcmp(opt
->name
, "rw") == 0)
638 fsflags
&= ~MNT_RDONLY
;
639 else if (strcmp(opt
->name
, "ro") == 0)
640 fsflags
|= MNT_RDONLY
;
641 else if (strcmp(opt
->name
, "rdonly") == 0) {
642 free(opt
->name
, M_MOUNT
);
643 opt
->name
= strdup("ro", M_MOUNT
);
644 fsflags
|= MNT_RDONLY
;
646 else if (strcmp(opt
->name
, "suiddir") == 0)
647 fsflags
|= MNT_SUIDDIR
;
648 else if (strcmp(opt
->name
, "sync") == 0)
649 fsflags
|= MNT_SYNCHRONOUS
;
650 else if (strcmp(opt
->name
, "union") == 0)
651 fsflags
|= MNT_UNION
;
652 else if (strcmp(opt
->name
, "automounted") == 0) {
653 fsflags
|= MNT_AUTOMOUNTED
;
654 vfs_freeopt(optlist
, opt
);
659 * Be ultra-paranoid about making sure the type and fspath
660 * variables will fit in our mp buffers, including the
663 if (fstypelen
> MFSNAMELEN
|| fspathlen
> MNAMELEN
) {
664 error
= ENAMETOOLONG
;
668 error
= vfs_domount(td
, fstype
, fspath
, fsflags
, &optlist
);
670 /* copyout the errmsg */
671 if (errmsg_pos
!= -1 && ((2 * errmsg_pos
+ 1) < fsoptions
->uio_iovcnt
)
672 && errmsg_len
> 0 && errmsg
!= NULL
) {
673 if (fsoptions
->uio_segflg
== UIO_SYSSPACE
) {
675 fsoptions
->uio_iov
[2 * errmsg_pos
+ 1].iov_base
,
676 fsoptions
->uio_iov
[2 * errmsg_pos
+ 1].iov_len
);
679 fsoptions
->uio_iov
[2 * errmsg_pos
+ 1].iov_base
,
680 fsoptions
->uio_iov
[2 * errmsg_pos
+ 1].iov_len
);
685 vfs_freeopts(optlist
);
692 #ifndef _SYS_SYSPROTO_H_
704 struct mount_args
/* {
712 struct vfsconf
*vfsp
= NULL
;
713 struct mntarg
*ma
= NULL
;
718 * Mount flags are now 64-bits. On 32-bit architectures only
719 * 32-bits are passed in, but from here on everything handles
720 * 64-bit flags correctly.
724 AUDIT_ARG_FFLAGS(flags
);
727 * Filter out MNT_ROOTFS. We do not want clients of mount() in
728 * userspace to set this flag, but we must filter it out if we want
729 * MNT_UPDATE on the root file system to work.
730 * MNT_ROOTFS should only be set by the kernel when mounting its
733 flags
&= ~MNT_ROOTFS
;
735 fstype
= malloc(MFSNAMELEN
, M_TEMP
, M_WAITOK
);
736 error
= copyinstr(uap
->type
, fstype
, MFSNAMELEN
, NULL
);
738 free(fstype
, M_TEMP
);
742 AUDIT_ARG_TEXT(fstype
);
743 vfsp
= vfs_byname_kld(fstype
, td
, &error
);
744 free(fstype
, M_TEMP
);
747 if (vfsp
->vfc_vfsops
->vfs_cmount
== NULL
)
750 ma
= mount_argsu(ma
, "fstype", uap
->type
, MFSNAMELEN
);
751 ma
= mount_argsu(ma
, "fspath", uap
->path
, MNAMELEN
);
752 ma
= mount_argb(ma
, flags
& MNT_RDONLY
, "noro");
753 ma
= mount_argb(ma
, !(flags
& MNT_NOSUID
), "nosuid");
754 ma
= mount_argb(ma
, !(flags
& MNT_NOEXEC
), "noexec");
756 error
= vfsp
->vfc_vfsops
->vfs_cmount(ma
, uap
->data
, flags
);
761 * vfs_domount_first(): first file system mount (not update)
765 struct thread
*td
, /* Calling thread. */
766 struct vfsconf
*vfsp
, /* File system type. */
767 char *fspath
, /* Mount path. */
768 struct vnode
*vp
, /* Vnode to be covered. */
769 uint64_t fsflags
, /* Flags common to all filesystems. */
770 struct vfsoptlist
**optlist
/* Options local to the filesystem. */
778 ASSERT_VOP_ELOCKED(vp
, __func__
);
779 KASSERT((fsflags
& MNT_UPDATE
) == 0, ("MNT_UPDATE shouldn't be here"));
782 * If the user is not root, ensure that they own the directory
783 * onto which we are attempting to mount.
785 error
= VOP_GETATTR(vp
, &va
, td
->td_ucred
);
786 if (error
== 0 && va
.va_uid
!= td
->td_ucred
->cr_uid
)
787 error
= priv_check_cred(td
->td_ucred
, PRIV_VFS_ADMIN
, 0);
789 error
= vinvalbuf(vp
, V_SAVE
, 0, 0);
790 if (error
== 0 && vp
->v_type
!= VDIR
)
794 if ((vp
->v_iflag
& VI_MOUNT
) == 0 && vp
->v_mountedhere
== NULL
)
795 vp
->v_iflag
|= VI_MOUNT
;
806 /* Allocate and initialize the filesystem. */
807 mp
= vfs_mount_alloc(vp
, vfsp
, fspath
, td
->td_ucred
);
808 /* XXXMAC: pass to vfs_mount_alloc? */
809 mp
->mnt_optnew
= *optlist
;
810 /* Set the mount level flags. */
811 mp
->mnt_flag
= (fsflags
& (MNT_UPDATEMASK
| MNT_ROOTFS
| MNT_RDONLY
));
814 * Mount the filesystem.
815 * XXX The final recipients of VFS_MOUNT just overwrite the ndp they
816 * get. No freeing of cn_pnbuf.
818 error
= VFS_MOUNT(mp
);
821 vfs_mount_destroy(mp
);
823 vp
->v_iflag
&= ~VI_MOUNT
;
829 if (mp
->mnt_opt
!= NULL
)
830 vfs_freeopts(mp
->mnt_opt
);
831 mp
->mnt_opt
= mp
->mnt_optnew
;
833 (void)VFS_STATFS(mp
, &mp
->mnt_stat
);
836 * Prevent external consumers of mount options from reading mnt_optnew.
838 mp
->mnt_optnew
= NULL
;
841 if ((mp
->mnt_flag
& MNT_ASYNC
) != 0 &&
842 (mp
->mnt_kern_flag
& MNTK_NOASYNC
) == 0)
843 mp
->mnt_kern_flag
|= MNTK_ASYNC
;
845 mp
->mnt_kern_flag
&= ~MNTK_ASYNC
;
848 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
851 vp
->v_iflag
&= ~VI_MOUNT
;
853 vp
->v_mountedhere
= mp
;
854 /* Place the new filesystem at the end of the mount list. */
855 mtx_lock(&mountlist_mtx
);
856 TAILQ_INSERT_TAIL(&mountlist
, mp
, mnt_list
);
857 mtx_unlock(&mountlist_mtx
);
858 vfs_event_signal(NULL
, VQ_MOUNT
, 0);
859 if (VFS_ROOT(mp
, LK_EXCLUSIVE
, &newdp
))
860 panic("mount: lost mount");
862 EVENTHANDLER_INVOKE(vfs_mounted
, mp
, newdp
, td
);
863 VOP_UNLOCK(newdp
, 0);
864 mountcheckdirs(vp
, newdp
);
866 if ((mp
->mnt_flag
& MNT_RDONLY
) == 0)
867 vfs_allocate_syncvnode(mp
);
873 * vfs_domount_update(): update of mounted file system
877 struct thread
*td
, /* Calling thread. */
878 struct vnode
*vp
, /* Mount point vnode. */
879 uint64_t fsflags
, /* Flags common to all filesystems. */
880 struct vfsoptlist
**optlist
/* Options local to the filesystem. */
883 struct oexport_args oexport
;
884 struct export_args export
;
886 int error
, export_error
;
889 ASSERT_VOP_ELOCKED(vp
, __func__
);
890 KASSERT((fsflags
& MNT_UPDATE
) != 0, ("MNT_UPDATE should be here"));
893 if ((vp
->v_vflag
& VV_ROOT
) == 0) {
894 if (vfs_copyopt(*optlist
, "export", &export
, sizeof(export
))
904 * We only allow the filesystem to be reloaded if it
905 * is currently mounted read-only.
908 if ((fsflags
& MNT_RELOAD
) != 0 && (flag
& MNT_RDONLY
) == 0) {
910 return (EOPNOTSUPP
); /* Needs translation */
913 * Only privileged root, or (if MNT_USER is set) the user that
914 * did the original mount is permitted to update it.
916 error
= vfs_suser(mp
, td
);
921 if (vfs_busy(mp
, MBF_NOWAIT
)) {
926 if ((vp
->v_iflag
& VI_MOUNT
) != 0 || vp
->v_mountedhere
!= NULL
) {
932 vp
->v_iflag
|= VI_MOUNT
;
937 mp
->mnt_flag
&= ~MNT_UPDATEMASK
;
938 mp
->mnt_flag
|= fsflags
& (MNT_RELOAD
| MNT_FORCE
| MNT_UPDATE
|
939 MNT_SNAPSHOT
| MNT_ROOTFS
| MNT_UPDATEMASK
| MNT_RDONLY
);
940 if ((mp
->mnt_flag
& MNT_ASYNC
) == 0)
941 mp
->mnt_kern_flag
&= ~MNTK_ASYNC
;
943 mp
->mnt_optnew
= *optlist
;
944 vfs_mergeopts(mp
->mnt_optnew
, mp
->mnt_opt
);
947 * Mount the filesystem.
948 * XXX The final recipients of VFS_MOUNT just overwrite the ndp they
949 * get. No freeing of cn_pnbuf.
951 error
= VFS_MOUNT(mp
);
955 /* Process the export option. */
956 if (vfs_copyopt(mp
->mnt_optnew
, "export", &export
,
957 sizeof(export
)) == 0) {
958 export_error
= vfs_export(mp
, &export
);
959 } else if (vfs_copyopt(mp
->mnt_optnew
, "export", &oexport
,
960 sizeof(oexport
)) == 0) {
961 export
.ex_flags
= oexport
.ex_flags
;
962 export
.ex_root
= oexport
.ex_root
;
963 export
.ex_anon
= oexport
.ex_anon
;
964 export
.ex_addr
= oexport
.ex_addr
;
965 export
.ex_addrlen
= oexport
.ex_addrlen
;
966 export
.ex_mask
= oexport
.ex_mask
;
967 export
.ex_masklen
= oexport
.ex_masklen
;
968 export
.ex_indexfile
= oexport
.ex_indexfile
;
969 export
.ex_numsecflavors
= 0;
970 export_error
= vfs_export(mp
, &export
);
976 mp
->mnt_flag
&= ~(MNT_UPDATE
| MNT_RELOAD
| MNT_FORCE
|
980 * If we fail, restore old mount flags. MNT_QUOTA is special,
981 * because it is not part of MNT_UPDATEMASK, but it could have
982 * changed in the meantime if quotactl(2) was called.
983 * All in all we want current value of MNT_QUOTA, not the old
986 mp
->mnt_flag
= (mp
->mnt_flag
& MNT_QUOTA
) | (flag
& ~MNT_QUOTA
);
988 if ((mp
->mnt_flag
& MNT_ASYNC
) != 0 &&
989 (mp
->mnt_kern_flag
& MNTK_NOASYNC
) == 0)
990 mp
->mnt_kern_flag
|= MNTK_ASYNC
;
992 mp
->mnt_kern_flag
&= ~MNTK_ASYNC
;
998 if (mp
->mnt_opt
!= NULL
)
999 vfs_freeopts(mp
->mnt_opt
);
1000 mp
->mnt_opt
= mp
->mnt_optnew
;
1002 (void)VFS_STATFS(mp
, &mp
->mnt_stat
);
1004 * Prevent external consumers of mount options from reading
1007 mp
->mnt_optnew
= NULL
;
1009 if ((mp
->mnt_flag
& MNT_RDONLY
) == 0)
1010 vfs_allocate_syncvnode(mp
);
1012 vfs_deallocate_syncvnode(mp
);
1016 vp
->v_iflag
&= ~VI_MOUNT
;
1019 return (error
!= 0 ? error
: export_error
);
1023 * vfs_domount(): actually attempt a filesystem mount.
1027 struct thread
*td
, /* Calling thread. */
1028 const char *fstype
, /* Filesystem type. */
1029 char *fspath
, /* Mount path. */
1030 uint64_t fsflags
, /* Flags common to all filesystems. */
1031 struct vfsoptlist
**optlist
/* Options local to the filesystem. */
1034 struct vfsconf
*vfsp
;
1035 struct nameidata nd
;
1041 * Be ultra-paranoid about making sure the type and fspath
1042 * variables will fit in our mp buffers, including the
1045 if (strlen(fstype
) >= MFSNAMELEN
|| strlen(fspath
) >= MNAMELEN
)
1046 return (ENAMETOOLONG
);
1048 if (jailed(td
->td_ucred
) || usermount
== 0) {
1049 if ((error
= priv_check(td
, PRIV_VFS_MOUNT
)) != 0)
1054 * Do not allow NFS export or MNT_SUIDDIR by unprivileged users.
1056 if (fsflags
& MNT_EXPORTED
) {
1057 error
= priv_check(td
, PRIV_VFS_MOUNT_EXPORTED
);
1061 if (fsflags
& MNT_SUIDDIR
) {
1062 error
= priv_check(td
, PRIV_VFS_MOUNT_SUIDDIR
);
1067 * Silently enforce MNT_NOSUID and MNT_USER for unprivileged users.
1069 if ((fsflags
& (MNT_NOSUID
| MNT_USER
)) != (MNT_NOSUID
| MNT_USER
)) {
1070 if (priv_check(td
, PRIV_VFS_MOUNT_NONUSER
) != 0)
1071 fsflags
|= MNT_NOSUID
| MNT_USER
;
1074 /* Load KLDs before we lock the covered vnode to avoid reversals. */
1076 if ((fsflags
& MNT_UPDATE
) == 0) {
1077 /* Don't try to load KLDs if we're mounting the root. */
1078 if (fsflags
& MNT_ROOTFS
)
1079 vfsp
= vfs_byname(fstype
);
1081 vfsp
= vfs_byname_kld(fstype
, td
, &error
);
1084 if (jailed(td
->td_ucred
) && !(vfsp
->vfc_flags
& VFCF_JAIL
))
1089 * Get vnode to be covered or mount point's vnode in case of MNT_UPDATE.
1091 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
| AUDITVNODE1
,
1092 UIO_SYSSPACE
, fspath
, td
);
1096 NDFREE(&nd
, NDF_ONLY_PNBUF
);
1098 if ((fsflags
& MNT_UPDATE
) == 0) {
1099 pathbuf
= malloc(MNAMELEN
, M_TEMP
, M_WAITOK
);
1100 strcpy(pathbuf
, fspath
);
1101 error
= vn_path_to_global_path(td
, vp
, pathbuf
, MNAMELEN
);
1102 /* debug.disablefullpath == 1 results in ENODEV */
1103 if (error
== 0 || error
== ENODEV
) {
1104 error
= vfs_domount_first(td
, vfsp
, pathbuf
, vp
,
1107 free(pathbuf
, M_TEMP
);
1109 error
= vfs_domount_update(td
, vp
, fsflags
, optlist
);
1115 * Unmount a filesystem.
1117 * Note: unmount takes a path to the vnode mounted on as argument, not
1118 * special file (as before).
1120 #ifndef _SYS_SYSPROTO_H_
1121 struct unmount_args
{
1128 sys_unmount(struct thread
*td
, struct unmount_args
*uap
)
1130 struct nameidata nd
;
1133 int error
, id0
, id1
;
1135 AUDIT_ARG_VALUE(uap
->flags
);
1136 if (jailed(td
->td_ucred
) || usermount
== 0) {
1137 error
= priv_check(td
, PRIV_VFS_UNMOUNT
);
1142 pathbuf
= malloc(MNAMELEN
, M_TEMP
, M_WAITOK
);
1143 error
= copyinstr(uap
->path
, pathbuf
, MNAMELEN
, NULL
);
1145 free(pathbuf
, M_TEMP
);
1148 if (uap
->flags
& MNT_BYFSID
) {
1149 AUDIT_ARG_TEXT(pathbuf
);
1150 /* Decode the filesystem ID. */
1151 if (sscanf(pathbuf
, "FSID:%d:%d", &id0
, &id1
) != 2) {
1152 free(pathbuf
, M_TEMP
);
1156 mtx_lock(&mountlist_mtx
);
1157 TAILQ_FOREACH_REVERSE(mp
, &mountlist
, mntlist
, mnt_list
) {
1158 if (mp
->mnt_stat
.f_fsid
.val
[0] == id0
&&
1159 mp
->mnt_stat
.f_fsid
.val
[1] == id1
) {
1164 mtx_unlock(&mountlist_mtx
);
1167 * Try to find global path for path argument.
1169 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
| AUDITVNODE1
,
1170 UIO_SYSSPACE
, pathbuf
, td
);
1171 if (namei(&nd
) == 0) {
1172 NDFREE(&nd
, NDF_ONLY_PNBUF
);
1173 error
= vn_path_to_global_path(td
, nd
.ni_vp
, pathbuf
,
1175 if (error
== 0 || error
== ENODEV
)
1178 mtx_lock(&mountlist_mtx
);
1179 TAILQ_FOREACH_REVERSE(mp
, &mountlist
, mntlist
, mnt_list
) {
1180 if (strcmp(mp
->mnt_stat
.f_mntonname
, pathbuf
) == 0) {
1185 mtx_unlock(&mountlist_mtx
);
1187 free(pathbuf
, M_TEMP
);
1190 * Previously we returned ENOENT for a nonexistent path and
1191 * EINVAL for a non-mountpoint. We cannot tell these apart
1192 * now, so in the !MNT_BYFSID case return the more likely
1193 * EINVAL for compatibility.
1195 return ((uap
->flags
& MNT_BYFSID
) ? ENOENT
: EINVAL
);
1199 * Don't allow unmounting the root filesystem.
1201 if (mp
->mnt_flag
& MNT_ROOTFS
) {
1205 error
= dounmount(mp
, uap
->flags
, td
);
1210 * Do the actual filesystem unmount.
1213 dounmount(struct mount
*mp
, int flags
, struct thread
*td
)
1215 struct vnode
*coveredvp
, *fsrootvp
;
1217 uint64_t async_flag
;
1220 if ((coveredvp
= mp
->mnt_vnodecovered
) != NULL
) {
1221 mnt_gen_r
= mp
->mnt_gen
;
1224 vn_lock(coveredvp
, LK_EXCLUSIVE
| LK_INTERLOCK
| LK_RETRY
);
1227 * Check for mp being unmounted while waiting for the
1228 * covered vnode lock.
1230 if (coveredvp
->v_mountedhere
!= mp
||
1231 coveredvp
->v_mountedhere
->mnt_gen
!= mnt_gen_r
) {
1232 VOP_UNLOCK(coveredvp
, 0);
1238 * Only privileged root, or (if MNT_USER is set) the user that did the
1239 * original mount is permitted to unmount this filesystem.
1241 error
= vfs_suser(mp
, td
);
1244 VOP_UNLOCK(coveredvp
, 0);
1249 vn_start_write(NULL
, &mp
, V_WAIT
| V_MNTREF
);
1251 if ((mp
->mnt_kern_flag
& MNTK_UNMOUNT
) != 0 ||
1252 !TAILQ_EMPTY(&mp
->mnt_uppers
)) {
1255 VOP_UNLOCK(coveredvp
, 0);
1256 vn_finished_write(mp
);
1259 mp
->mnt_kern_flag
|= MNTK_UNMOUNT
| MNTK_NOINSMNTQ
;
1260 /* Allow filesystems to detect that a forced unmount is in progress. */
1261 if (flags
& MNT_FORCE
) {
1262 mp
->mnt_kern_flag
|= MNTK_UNMOUNTF
;
1265 * Must be done after setting MNTK_UNMOUNTF and before
1266 * waiting for mnt_lockref to become 0.
1272 if (mp
->mnt_lockref
) {
1273 mp
->mnt_kern_flag
|= MNTK_DRAINING
;
1274 error
= msleep(&mp
->mnt_lockref
, MNT_MTX(mp
), PVFS
,
1278 KASSERT(mp
->mnt_lockref
== 0,
1279 ("%s: invalid lock refcount in the drain path @ %s:%d",
1280 __func__
, __FILE__
, __LINE__
));
1282 ("%s: invalid return value for msleep in the drain path @ %s:%d",
1283 __func__
, __FILE__
, __LINE__
));
1285 if (mp
->mnt_flag
& MNT_EXPUBLIC
)
1286 vfs_setpublicfs(NULL
, NULL
, NULL
);
1288 vfs_msync(mp
, MNT_WAIT
);
1290 async_flag
= mp
->mnt_flag
& MNT_ASYNC
;
1291 mp
->mnt_flag
&= ~MNT_ASYNC
;
1292 mp
->mnt_kern_flag
&= ~MNTK_ASYNC
;
1294 cache_purgevfs(mp
); /* remove cache entries for this file sys */
1295 vfs_deallocate_syncvnode(mp
);
1297 * For forced unmounts, move process cdir/rdir refs on the fs root
1298 * vnode to the covered vnode. For non-forced unmounts we want
1299 * such references to cause an EBUSY error.
1301 if ((flags
& MNT_FORCE
) &&
1302 VFS_ROOT(mp
, LK_EXCLUSIVE
, &fsrootvp
) == 0) {
1303 if (mp
->mnt_vnodecovered
!= NULL
)
1304 mountcheckdirs(fsrootvp
, mp
->mnt_vnodecovered
);
1305 if (fsrootvp
== rootvnode
) {
1311 if ((mp
->mnt_flag
& MNT_RDONLY
) != 0 || (flags
& MNT_FORCE
) != 0 ||
1312 (error
= VFS_SYNC(mp
, MNT_WAIT
)) == 0)
1313 error
= VFS_UNMOUNT(mp
, flags
);
1314 vn_finished_write(mp
);
1316 * If we failed to flush the dirty blocks for this mount point,
1317 * undo all the cdir/rdir and rootvnode changes we made above.
1318 * Unless we failed to do so because the device is reporting that
1319 * it doesn't exist anymore.
1321 if (error
&& error
!= ENXIO
) {
1322 if ((flags
& MNT_FORCE
) &&
1323 VFS_ROOT(mp
, LK_EXCLUSIVE
, &fsrootvp
) == 0) {
1324 if (mp
->mnt_vnodecovered
!= NULL
)
1325 mountcheckdirs(mp
->mnt_vnodecovered
, fsrootvp
);
1326 if (rootvnode
== NULL
) {
1327 rootvnode
= fsrootvp
;
1333 mp
->mnt_kern_flag
&= ~MNTK_NOINSMNTQ
;
1334 if ((mp
->mnt_flag
& MNT_RDONLY
) == 0) {
1336 vfs_allocate_syncvnode(mp
);
1339 mp
->mnt_kern_flag
&= ~(MNTK_UNMOUNT
| MNTK_UNMOUNTF
);
1340 mp
->mnt_flag
|= async_flag
;
1341 if ((mp
->mnt_flag
& MNT_ASYNC
) != 0 &&
1342 (mp
->mnt_kern_flag
& MNTK_NOASYNC
) == 0)
1343 mp
->mnt_kern_flag
|= MNTK_ASYNC
;
1344 if (mp
->mnt_kern_flag
& MNTK_MWAIT
) {
1345 mp
->mnt_kern_flag
&= ~MNTK_MWAIT
;
1350 VOP_UNLOCK(coveredvp
, 0);
1353 mtx_lock(&mountlist_mtx
);
1354 TAILQ_REMOVE(&mountlist
, mp
, mnt_list
);
1355 mtx_unlock(&mountlist_mtx
);
1356 EVENTHANDLER_INVOKE(vfs_unmounted
, mp
, td
);
1357 if (coveredvp
!= NULL
) {
1358 coveredvp
->v_mountedhere
= NULL
;
1361 vfs_event_signal(NULL
, VQ_UNMOUNT
, 0);
1362 if (mp
== rootdevmp
)
1364 vfs_mount_destroy(mp
);
1369 * Report errors during filesystem mounting.
1372 vfs_mount_error(struct mount
*mp
, const char *fmt
, ...)
1374 struct vfsoptlist
*moptlist
= mp
->mnt_optnew
;
1379 error
= vfs_getopt(moptlist
, "errmsg", (void **)&errmsg
, &len
);
1380 if (error
|| errmsg
== NULL
|| len
<= 0)
1384 vsnprintf(errmsg
, (size_t)len
, fmt
, ap
);
1389 vfs_opterror(struct vfsoptlist
*opts
, const char *fmt
, ...)
1395 error
= vfs_getopt(opts
, "errmsg", (void **)&errmsg
, &len
);
1396 if (error
|| errmsg
== NULL
|| len
<= 0)
1400 vsnprintf(errmsg
, (size_t)len
, fmt
, ap
);
1405 * ---------------------------------------------------------------------
1406 * Functions for querying mount options/arguments from filesystems.
1410 * Check that no unknown options are given
1413 vfs_filteropt(struct vfsoptlist
*opts
, const char **legal
)
1417 const char **t
, *p
, *q
;
1420 TAILQ_FOREACH(opt
, opts
, link
) {
1423 if (p
[0] == 'n' && p
[1] == 'o')
1425 for(t
= global_opts
; *t
!= NULL
; t
++) {
1426 if (strcmp(*t
, p
) == 0)
1429 if (strcmp(*t
, q
) == 0)
1435 for(t
= legal
; *t
!= NULL
; t
++) {
1436 if (strcmp(*t
, p
) == 0)
1439 if (strcmp(*t
, q
) == 0)
1445 snprintf(errmsg
, sizeof(errmsg
),
1446 "mount option <%s> is unknown", p
);
1450 TAILQ_FOREACH(opt
, opts
, link
) {
1451 if (strcmp(opt
->name
, "errmsg") == 0) {
1452 strncpy((char *)opt
->value
, errmsg
, opt
->len
);
1457 printf("%s\n", errmsg
);
1463 * Get a mount option by its name.
1465 * Return 0 if the option was found, ENOENT otherwise.
1466 * If len is non-NULL it will be filled with the length
1467 * of the option. If buf is non-NULL, it will be filled
1468 * with the address of the option.
1471 vfs_getopt(opts
, name
, buf
, len
)
1472 struct vfsoptlist
*opts
;
1479 KASSERT(opts
!= NULL
, ("vfs_getopt: caller passed 'opts' as NULL"));
1481 TAILQ_FOREACH(opt
, opts
, link
) {
1482 if (strcmp(name
, opt
->name
) == 0) {
1495 vfs_getopt_pos(struct vfsoptlist
*opts
, const char *name
)
1502 TAILQ_FOREACH(opt
, opts
, link
) {
1503 if (strcmp(name
, opt
->name
) == 0) {
1512 vfs_getopt_size(struct vfsoptlist
*opts
, const char *name
, off_t
*value
)
1514 char *opt_value
, *vtp
;
1518 error
= vfs_getopt(opts
, name
, (void **)&opt_value
, &opt_len
);
1521 if (opt_len
== 0 || opt_value
== NULL
)
1523 if (opt_value
[0] == '\0' || opt_value
[opt_len
- 1] != '\0')
1525 iv
= strtoq(opt_value
, &vtp
, 0);
1526 if (vtp
== opt_value
|| (vtp
[0] != '\0' && vtp
[1] != '\0'))
1554 vfs_getopts(struct vfsoptlist
*opts
, const char *name
, int *error
)
1559 TAILQ_FOREACH(opt
, opts
, link
) {
1560 if (strcmp(name
, opt
->name
) != 0)
1563 if (opt
->len
== 0 ||
1564 ((char *)opt
->value
)[opt
->len
- 1] != '\0') {
1568 return (opt
->value
);
1575 vfs_flagopt(struct vfsoptlist
*opts
, const char *name
, uint64_t *w
,
1580 TAILQ_FOREACH(opt
, opts
, link
) {
1581 if (strcmp(name
, opt
->name
) == 0) {
1594 vfs_scanopt(struct vfsoptlist
*opts
, const char *name
, const char *fmt
, ...)
1600 KASSERT(opts
!= NULL
, ("vfs_getopt: caller passed 'opts' as NULL"));
1602 TAILQ_FOREACH(opt
, opts
, link
) {
1603 if (strcmp(name
, opt
->name
) != 0)
1606 if (opt
->len
== 0 || opt
->value
== NULL
)
1608 if (((char *)opt
->value
)[opt
->len
- 1] != '\0')
1611 ret
= vsscanf(opt
->value
, fmt
, ap
);
1619 vfs_setopt(struct vfsoptlist
*opts
, const char *name
, void *value
, int len
)
1623 TAILQ_FOREACH(opt
, opts
, link
) {
1624 if (strcmp(name
, opt
->name
) != 0)
1627 if (opt
->value
== NULL
)
1630 if (opt
->len
!= len
)
1632 bcopy(value
, opt
->value
, len
);
1640 vfs_setopt_part(struct vfsoptlist
*opts
, const char *name
, void *value
, int len
)
1644 TAILQ_FOREACH(opt
, opts
, link
) {
1645 if (strcmp(name
, opt
->name
) != 0)
1648 if (opt
->value
== NULL
)
1654 bcopy(value
, opt
->value
, len
);
1662 vfs_setopts(struct vfsoptlist
*opts
, const char *name
, const char *value
)
1666 TAILQ_FOREACH(opt
, opts
, link
) {
1667 if (strcmp(name
, opt
->name
) != 0)
1670 if (opt
->value
== NULL
)
1671 opt
->len
= strlen(value
) + 1;
1672 else if (strlcpy(opt
->value
, value
, opt
->len
) >= opt
->len
)
1680 * Find and copy a mount option.
1682 * The size of the buffer has to be specified
1683 * in len, if it is not the same length as the
1684 * mount option, EINVAL is returned.
1685 * Returns ENOENT if the option is not found.
1688 vfs_copyopt(opts
, name
, dest
, len
)
1689 struct vfsoptlist
*opts
;
1696 KASSERT(opts
!= NULL
, ("vfs_copyopt: caller passed 'opts' as NULL"));
1698 TAILQ_FOREACH(opt
, opts
, link
) {
1699 if (strcmp(name
, opt
->name
) == 0) {
1701 if (len
!= opt
->len
)
1703 bcopy(opt
->value
, dest
, opt
->len
);
1711 __vfs_statfs(struct mount
*mp
, struct statfs
*sbp
)
1715 error
= mp
->mnt_op
->vfs_statfs(mp
, &mp
->mnt_stat
);
1716 if (sbp
!= &mp
->mnt_stat
)
1717 *sbp
= mp
->mnt_stat
;
1722 vfs_mountedfrom(struct mount
*mp
, const char *from
)
1725 bzero(mp
->mnt_stat
.f_mntfromname
, sizeof mp
->mnt_stat
.f_mntfromname
);
1726 strlcpy(mp
->mnt_stat
.f_mntfromname
, from
,
1727 sizeof mp
->mnt_stat
.f_mntfromname
);
1731 * ---------------------------------------------------------------------
1732 * This is the api for building mount args and mounting filesystems from
1733 * inside the kernel.
1735 * The API works by accumulation of individual args. First error is
1738 * XXX: should be documented in new manpage kernel_mount(9)
1741 /* A memory allocation which must be freed when we are done */
1743 SLIST_ENTRY(mntaarg
) next
;
1746 /* The header for the mount arguments */
1751 SLIST_HEAD(, mntaarg
) list
;
1755 * Add a boolean argument.
1757 * flag is the boolean value.
1758 * name must start with "no".
1761 mount_argb(struct mntarg
*ma
, int flag
, const char *name
)
1764 KASSERT(name
[0] == 'n' && name
[1] == 'o',
1765 ("mount_argb(...,%s): name must start with 'no'", name
));
1767 return (mount_arg(ma
, name
+ (flag
? 2 : 0), NULL
, 0));
1771 * Add an argument printf style
1774 mount_argf(struct mntarg
*ma
, const char *name
, const char *fmt
, ...)
1777 struct mntaarg
*maa
;
1782 ma
= malloc(sizeof *ma
, M_MOUNT
, M_WAITOK
| M_ZERO
);
1783 SLIST_INIT(&ma
->list
);
1788 ma
->v
= realloc(ma
->v
, sizeof *ma
->v
* (ma
->len
+ 2),
1790 ma
->v
[ma
->len
].iov_base
= (void *)(uintptr_t)name
;
1791 ma
->v
[ma
->len
].iov_len
= strlen(name
) + 1;
1794 sb
= sbuf_new_auto();
1796 sbuf_vprintf(sb
, fmt
, ap
);
1799 len
= sbuf_len(sb
) + 1;
1800 maa
= malloc(sizeof *maa
+ len
, M_MOUNT
, M_WAITOK
| M_ZERO
);
1801 SLIST_INSERT_HEAD(&ma
->list
, maa
, next
);
1802 bcopy(sbuf_data(sb
), maa
+ 1, len
);
1805 ma
->v
[ma
->len
].iov_base
= maa
+ 1;
1806 ma
->v
[ma
->len
].iov_len
= len
;
1813 * Add an argument which is a userland string.
1816 mount_argsu(struct mntarg
*ma
, const char *name
, const void *val
, int len
)
1818 struct mntaarg
*maa
;
1824 ma
= malloc(sizeof *ma
, M_MOUNT
, M_WAITOK
| M_ZERO
);
1825 SLIST_INIT(&ma
->list
);
1829 maa
= malloc(sizeof *maa
+ len
, M_MOUNT
, M_WAITOK
| M_ZERO
);
1830 SLIST_INSERT_HEAD(&ma
->list
, maa
, next
);
1831 tbuf
= (void *)(maa
+ 1);
1832 ma
->error
= copyinstr(val
, tbuf
, len
, NULL
);
1833 return (mount_arg(ma
, name
, tbuf
, -1));
1839 * If length is -1, treat value as a C string.
1842 mount_arg(struct mntarg
*ma
, const char *name
, const void *val
, int len
)
1846 ma
= malloc(sizeof *ma
, M_MOUNT
, M_WAITOK
| M_ZERO
);
1847 SLIST_INIT(&ma
->list
);
1852 ma
->v
= realloc(ma
->v
, sizeof *ma
->v
* (ma
->len
+ 2),
1854 ma
->v
[ma
->len
].iov_base
= (void *)(uintptr_t)name
;
1855 ma
->v
[ma
->len
].iov_len
= strlen(name
) + 1;
1858 ma
->v
[ma
->len
].iov_base
= (void *)(uintptr_t)val
;
1860 ma
->v
[ma
->len
].iov_len
= strlen(val
) + 1;
1862 ma
->v
[ma
->len
].iov_len
= len
;
1868 * Free a mntarg structure
1871 free_mntarg(struct mntarg
*ma
)
1873 struct mntaarg
*maa
;
1875 while (!SLIST_EMPTY(&ma
->list
)) {
1876 maa
= SLIST_FIRST(&ma
->list
);
1877 SLIST_REMOVE_HEAD(&ma
->list
, next
);
1880 free(ma
->v
, M_MOUNT
);
1885 * Mount a filesystem
1888 kernel_mount(struct mntarg
*ma
, uint64_t flags
)
1893 KASSERT(ma
!= NULL
, ("kernel_mount NULL ma"));
1894 KASSERT(ma
->v
!= NULL
, ("kernel_mount NULL ma->v"));
1895 KASSERT(!(ma
->len
& 1), ("kernel_mount odd ma->len (%d)", ma
->len
));
1897 auio
.uio_iov
= ma
->v
;
1898 auio
.uio_iovcnt
= ma
->len
;
1899 auio
.uio_segflg
= UIO_SYSSPACE
;
1903 error
= vfs_donmount(curthread
, flags
, &auio
);
1909 * A printflike function to mount a filesystem.
1912 kernel_vmount(int flags
, ...)
1914 struct mntarg
*ma
= NULL
;
1920 va_start(ap
, flags
);
1922 cp
= va_arg(ap
, const char *);
1925 vp
= va_arg(ap
, const void *);
1926 ma
= mount_arg(ma
, cp
, vp
, (vp
!= NULL
? -1 : 0));
1930 error
= kernel_mount(ma
, flags
);
1935 vfs_oexport_conv(const struct oexport_args
*oexp
, struct export_args
*exp
)
1938 bcopy(oexp
, exp
, sizeof(*oexp
));
1939 exp
->ex_numsecflavors
= 0;