37 #include <sys/cdefs.h>
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);
79 "Unprivileged users may mount and unmount file systems");
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);
121 mp = (
struct mount *)mem;
130 mount_zone = uma_zcreate(
"Mountpoints",
sizeof(
struct mount), NULL,
145 TAILQ_REMOVE(opts, opt, link);
146 free(opt->name, M_MOUNT);
147 if (opt->value != NULL)
148 free(opt->value, M_MOUNT);
158 while (!TAILQ_EMPTY(opts)) {
159 opt = TAILQ_FIRST(opts);
168 struct vfsopt *opt, *temp;
172 TAILQ_FOREACH_SAFE(opt, opts, link, temp) {
173 if (strcmp(opt->name, name) == 0)
182 if (strcmp(opt,
"ro") == 0 || strcmp(opt,
"rdonly") == 0 ||
183 strcmp(opt,
"norw") == 0)
192 if (strcmp(opt,
"rw") == 0 || strcmp(opt,
"noro") == 0)
206 if (strcmp(opt1, opt2) == 0)
209 if (strncmp(opt1,
"no", 2) == 0 && strcmp(opt1 + 2, opt2) == 0)
212 if (strncmp(opt2,
"no", 2) == 0 && strcmp(opt1, opt2 + 2) == 0)
214 while ((p = strchr(opt1,
'.')) != NULL &&
215 !strncmp(opt1, opt2, ++p - opt1)) {
219 if (strncmp(opt1,
"no", 2) == 0 && strcmp(opt1 + 2, opt2) == 0)
222 if (strncmp(opt2,
"no", 2) == 0 && strcmp(opt1, opt2 + 2) == 0)
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) {
246 tmp = TAILQ_PREV(opt2, vfsoptlist, link);
250 opt2 = TAILQ_PREV(opt2, vfsoptlist, link);
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;
287 opt =
malloc(
sizeof(
struct vfsopt), M_MOUNT, M_WAITOK);
288 opt->name =
malloc(namelen, M_MOUNT, M_WAITOK);
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,
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,
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);
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);
398 flags &= ~MNT_ROOTFS;
400 iovcnt = uap->iovcnt;
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",
432 CTR2(KTR_VFS,
"%s: mp %p", __func__, mp);
442 CTR2(KTR_VFS,
"%s: mp %p", __func__, mp);
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;
466 mp->mnt_op = vfsp->vfc_vfsops;
468 vfsp->vfc_refcount++;
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);
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 mp->mnt_vfc->vfc_refcount--;
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)
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;
549 if (
vfs_getopt(optlist,
"errmsg", (
void **)&errmsg, &errmsg_len) == 0)
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);
580 TAILQ_FOREACH_SAFE(opt, optlist, link, tmp_opt) {
581 if (strcmp(opt->name,
"update") == 0) {
582 fsflags |= MNT_UPDATE;
585 else if (strcmp(opt->name,
"async") == 0)
586 fsflags |= MNT_ASYNC;
587 else if (strcmp(opt->name,
"force") == 0) {
588 fsflags |= MNT_FORCE;
591 else if (strcmp(opt->name,
"reload") == 0) {
592 fsflags |= MNT_RELOAD;
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;
659 if (fstypelen >= MFSNAMELEN - 1 || fspathlen >= MNAMELEN - 1) {
660 error = ENAMETOOLONG;
664 error =
vfs_domount(td, fstype, fspath, fsflags, &optlist);
667 if (errmsg_pos != -1 && ((2 * errmsg_pos + 1) < fsoptions->uio_iovcnt)
668 && errmsg_len > 0 && errmsg != NULL) {
669 if (fsoptions->uio_segflg == UIO_SYSSPACE) {
671 fsoptions->uio_iov[2 * errmsg_pos + 1].iov_base,
672 fsoptions->uio_iov[2 * errmsg_pos + 1].iov_len);
675 fsoptions->uio_iov[2 * errmsg_pos + 1].iov_base,
676 fsoptions->uio_iov[2 * errmsg_pos + 1].iov_len);
688 #ifndef _SYS_SYSPROTO_H_
720 AUDIT_ARG_FFLAGS(flags);
729 flags &= ~MNT_ROOTFS;
731 fstype =
malloc(MFSNAMELEN, M_TEMP, M_WAITOK);
732 error = copyinstr(uap->
type, fstype, MFSNAMELEN, NULL);
734 free(fstype, M_TEMP);
738 AUDIT_ARG_TEXT(fstype);
741 free(fstype, M_TEMP);
746 if (vfsp->vfc_vfsops->vfs_cmount == NULL) {
753 ma =
mount_argb(ma, flags & MNT_RDONLY,
"noro");
754 ma =
mount_argb(ma, !(flags & MNT_NOSUID),
"nosuid");
755 ma =
mount_argb(ma, !(flags & MNT_NOEXEC),
"noexec");
757 error = vfsp->vfc_vfsops->vfs_cmount(ma, uap->
data, flags);
772 struct vfsoptlist **optlist
780 mtx_assert(&
Giant, MA_OWNED);
781 ASSERT_VOP_ELOCKED(vp, __func__);
782 KASSERT((fsflags & MNT_UPDATE) == 0, (
"MNT_UPDATE shouldn't be here"));
788 error = VOP_GETATTR(vp, &va, td->td_ucred);
789 if (error == 0 && va.va_uid != td->td_ucred->cr_uid)
793 if (error == 0 && vp->v_type != VDIR)
797 if ((vp->v_iflag & VI_MOUNT) == 0 && vp->v_mountedhere == NULL)
798 vp->v_iflag |= VI_MOUNT;
812 mp->mnt_optnew = *optlist;
814 mp->mnt_flag = (fsflags & (MNT_UPDATEMASK | MNT_ROOTFS | MNT_RDONLY));
821 error = VFS_MOUNT(mp);
826 vp->v_iflag &= ~VI_MOUNT;
832 if (mp->mnt_opt != NULL)
834 mp->mnt_opt = mp->mnt_optnew;
836 (void)VFS_STATFS(mp, &mp->mnt_stat);
841 mp->mnt_optnew = NULL;
844 if ((mp->mnt_flag & MNT_ASYNC) != 0 &&
845 (mp->mnt_kern_flag & MNTK_NOASYNC) == 0)
846 mp->mnt_kern_flag |= MNTK_ASYNC;
848 mp->mnt_kern_flag &= ~MNTK_ASYNC;
851 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
854 vp->v_iflag &= ~VI_MOUNT;
856 vp->v_mountedhere = mp;
859 TAILQ_INSERT_TAIL(&
mountlist, mp, mnt_list);
862 if (VFS_ROOT(mp, LK_EXCLUSIVE, &newdp))
863 panic(
"mount: lost mount");
864 VOP_UNLOCK(newdp, 0);
868 if ((mp->mnt_flag & MNT_RDONLY) == 0)
882 struct vfsoptlist **optlist
885 struct oexport_args oexport;
886 struct export_args export;
888 int error, export_error;
891 mtx_assert(&
Giant, MA_OWNED);
892 ASSERT_VOP_ELOCKED(vp, __func__);
893 KASSERT((fsflags & MNT_UPDATE) != 0, (
"MNT_UPDATE should be here"));
895 if ((vp->v_vflag & VV_ROOT) == 0) {
905 if ((fsflags & MNT_RELOAD) != 0 && (flag & MNT_RDONLY) == 0) {
923 if ((vp->v_iflag & VI_MOUNT) != 0 || vp->v_mountedhere != NULL) {
929 vp->v_iflag |= VI_MOUNT;
934 mp->mnt_flag &= ~MNT_UPDATEMASK;
935 mp->mnt_flag |= fsflags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE |
936 MNT_SNAPSHOT | MNT_ROOTFS | MNT_UPDATEMASK | MNT_RDONLY);
937 if ((mp->mnt_flag & MNT_ASYNC) == 0)
938 mp->mnt_kern_flag &= ~MNTK_ASYNC;
940 mp->mnt_optnew = *optlist;
948 error = VFS_MOUNT(mp);
954 sizeof(export)) == 0) {
956 }
else if (
vfs_copyopt(mp->mnt_optnew,
"export", &oexport,
957 sizeof(oexport)) == 0) {
958 export.ex_flags = oexport.ex_flags;
959 export.ex_root = oexport.ex_root;
960 export.ex_anon = oexport.ex_anon;
961 export.ex_addr = oexport.ex_addr;
962 export.ex_addrlen = oexport.ex_addrlen;
963 export.ex_mask = oexport.ex_mask;
964 export.ex_masklen = oexport.ex_masklen;
965 export.ex_indexfile = oexport.ex_indexfile;
966 export.ex_numsecflavors = 0;
973 mp->mnt_flag &= ~(MNT_UPDATE | MNT_RELOAD | MNT_FORCE |
983 mp->mnt_flag = (mp->mnt_flag & MNT_QUOTA) | (flag & ~MNT_QUOTA);
985 if ((mp->mnt_flag & MNT_ASYNC) != 0 &&
986 (mp->mnt_kern_flag & MNTK_NOASYNC) == 0)
987 mp->mnt_kern_flag |= MNTK_ASYNC;
989 mp->mnt_kern_flag &= ~MNTK_ASYNC;
995 if (mp->mnt_opt != NULL)
997 mp->mnt_opt = mp->mnt_optnew;
999 (void)VFS_STATFS(mp, &mp->mnt_stat);
1004 mp->mnt_optnew = NULL;
1006 if ((mp->mnt_flag & MNT_RDONLY) == 0)
1013 vp->v_iflag &= ~VI_MOUNT;
1016 return (error != 0 ? error : export_error);
1028 struct vfsoptlist **optlist
1032 struct nameidata nd;
1042 if (strlen(fstype) >= MFSNAMELEN || strlen(fspath) >= MNAMELEN)
1043 return (ENAMETOOLONG);
1046 if ((error =
priv_check(td, PRIV_VFS_MOUNT)) != 0)
1053 if (fsflags & MNT_EXPORTED) {
1054 error =
priv_check(td, PRIV_VFS_MOUNT_EXPORTED);
1058 if (fsflags & MNT_SUIDDIR) {
1059 error =
priv_check(td, PRIV_VFS_MOUNT_SUIDDIR);
1066 if ((fsflags & (MNT_NOSUID | MNT_USER)) != (MNT_NOSUID | MNT_USER)) {
1067 if (
priv_check(td, PRIV_VFS_MOUNT_NONUSER) != 0)
1068 fsflags |= MNT_NOSUID | MNT_USER;
1073 if ((fsflags & MNT_UPDATE) == 0) {
1075 if (fsflags & MNT_ROOTFS)
1081 if (
jailed(td->td_ucred) && !(vfsp->vfc_flags & VFCF_JAIL))
1088 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
1089 UIO_SYSSPACE, fspath, td);
1093 if (!NDHASGIANT(&nd))
1095 NDFREE(&nd, NDF_ONLY_PNBUF);
1097 if ((fsflags & MNT_UPDATE) == 0) {
1098 pathbuf =
malloc(MNAMELEN, M_TEMP, M_WAITOK);
1099 strcpy(pathbuf, fspath);
1102 if (error == 0 || error == ENODEV) {
1106 free(pathbuf, M_TEMP);
1111 ASSERT_VI_UNLOCKED(vp, __func__);
1112 ASSERT_VOP_UNLOCKED(vp, __func__);
1123 #ifndef _SYS_SYSPROTO_H_
1138 struct nameidata nd;
1141 int error, id0, id1, vfslocked;
1143 AUDIT_ARG_VALUE(uap->flags);
1150 pathbuf =
malloc(MNAMELEN, M_TEMP, M_WAITOK);
1151 error = copyinstr(uap->path, pathbuf, MNAMELEN, NULL);
1153 free(pathbuf, M_TEMP);
1157 if (uap->flags & MNT_BYFSID) {
1158 AUDIT_ARG_TEXT(pathbuf);
1160 if (
sscanf(pathbuf,
"FSID:%d:%d", &id0, &id1) != 2) {
1162 free(pathbuf, M_TEMP);
1167 TAILQ_FOREACH_REVERSE(mp, &
mountlist, mntlist, mnt_list) {
1168 if (mp->mnt_stat.f_fsid.val[0] == id0 &&
1169 mp->mnt_stat.f_fsid.val[1] == id1)
1178 FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
1179 UIO_SYSSPACE, pathbuf, td);
1180 if (
namei(&nd) == 0) {
1181 vfslocked = NDHASGIANT(&nd);
1182 NDFREE(&nd, NDF_ONLY_PNBUF);
1185 if (error == 0 || error == ENODEV)
1187 VFS_UNLOCK_GIANT(vfslocked);
1190 TAILQ_FOREACH_REVERSE(mp, &
mountlist, mntlist, mnt_list) {
1191 if (strcmp(mp->mnt_stat.f_mntonname, pathbuf) == 0)
1196 free(pathbuf, M_TEMP);
1205 return ((uap->flags & MNT_BYFSID) ? ENOENT : EINVAL);
1211 if (mp->mnt_flag & MNT_ROOTFS) {
1229 struct vnode *coveredvp, *fsrootvp;
1231 uint64_t async_flag;
1234 mtx_assert(&
Giant, MA_OWNED);
1236 if ((coveredvp = mp->mnt_vnodecovered) != NULL) {
1237 mnt_gen_r = mp->mnt_gen;
1240 vn_lock(coveredvp, LK_EXCLUSIVE | LK_INTERLOCK | LK_RETRY);
1246 if (coveredvp->v_mountedhere != mp ||
1247 coveredvp->v_mountedhere->mnt_gen != mnt_gen_r) {
1248 VOP_UNLOCK(coveredvp, 0);
1259 VOP_UNLOCK(coveredvp, 0);
1265 if ((mp->mnt_kern_flag & MNTK_UNMOUNT) != 0 ||
1266 !TAILQ_EMPTY(&mp->mnt_uppers)) {
1269 VOP_UNLOCK(coveredvp, 0);
1273 mp->mnt_kern_flag |= MNTK_UNMOUNT | MNTK_NOINSMNTQ;
1275 if (flags & MNT_FORCE)
1276 mp->mnt_kern_flag |= MNTK_UNMOUNTF;
1278 if (mp->mnt_lockref) {
1279 mp->mnt_kern_flag |= MNTK_DRAINING;
1280 error = msleep(&mp->mnt_lockref, MNT_MTX(mp), PVFS,
1284 KASSERT(mp->mnt_lockref == 0,
1285 (
"%s: invalid lock refcount in the drain path @ %s:%d",
1286 __func__, __FILE__, __LINE__));
1288 (
"%s: invalid return value for msleep in the drain path @ %s:%d",
1289 __func__, __FILE__, __LINE__));
1291 if (mp->mnt_flag & MNT_EXPUBLIC)
1296 async_flag = mp->mnt_flag & MNT_ASYNC;
1297 mp->mnt_flag &= ~MNT_ASYNC;
1298 mp->mnt_kern_flag &= ~MNTK_ASYNC;
1307 if ((flags & MNT_FORCE) &&
1308 VFS_ROOT(mp, LK_EXCLUSIVE, &fsrootvp) == 0) {
1309 if (mp->mnt_vnodecovered != NULL)
1317 if (((mp->mnt_flag & MNT_RDONLY) ||
1318 (error = VFS_SYNC(mp, MNT_WAIT)) == 0) || (flags & MNT_FORCE) != 0)
1319 error = VFS_UNMOUNT(mp, flags);
1327 if (error && error != ENXIO) {
1328 if ((flags & MNT_FORCE) &&
1329 VFS_ROOT(mp, LK_EXCLUSIVE, &fsrootvp) == 0) {
1330 if (mp->mnt_vnodecovered != NULL)
1339 mp->mnt_kern_flag &= ~MNTK_NOINSMNTQ;
1340 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
1345 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
1346 mp->mnt_flag |= async_flag;
1347 if ((mp->mnt_flag & MNT_ASYNC) != 0 &&
1348 (mp->mnt_kern_flag & MNTK_NOASYNC) == 0)
1349 mp->mnt_kern_flag |= MNTK_ASYNC;
1350 if (mp->mnt_kern_flag & MNTK_MWAIT) {
1351 mp->mnt_kern_flag &= ~MNTK_MWAIT;
1356 VOP_UNLOCK(coveredvp, 0);
1362 if (coveredvp != NULL) {
1363 coveredvp->v_mountedhere = NULL;
1377 struct vfsoptlist *moptlist = mp->mnt_optnew;
1382 error =
vfs_getopt(moptlist,
"errmsg", (
void **)&errmsg, &len);
1383 if (error || errmsg == NULL || len <= 0)
1387 vsnprintf(errmsg, (
size_t)len, fmt, ap);
1398 error =
vfs_getopt(opts,
"errmsg", (
void **)&errmsg, &len);
1399 if (error || errmsg == NULL || len <= 0)
1403 vsnprintf(errmsg, (
size_t)len, fmt, ap);
1420 const char **t, *p, *q;
1423 TAILQ_FOREACH(opt, opts, link) {
1426 if (p[0] ==
'n' && p[1] ==
'o')
1429 if (strcmp(*t, p) == 0)
1432 if (strcmp(*t, q) == 0)
1438 for(t = legal; *t != NULL; t++) {
1439 if (strcmp(*t, p) == 0)
1442 if (strcmp(*t, q) == 0)
1449 "mount option <%s> is unknown", p);
1453 TAILQ_FOREACH(opt, opts, link) {
1454 if (strcmp(opt->name,
"errmsg") == 0) {
1455 strncpy((
char *)opt->value, errmsg, opt->len);
1475 struct vfsoptlist *opts;
1482 KASSERT(opts != NULL, (
"vfs_getopt: caller passed 'opts' as NULL"));
1484 TAILQ_FOREACH(opt, opts, link) {
1485 if (strcmp(name, opt->name) == 0) {
1505 TAILQ_FOREACH(opt, opts, link) {
1506 if (strcmp(name, opt->name) == 0) {
1520 TAILQ_FOREACH(opt, opts, link) {
1521 if (strcmp(name, opt->name) != 0)
1524 if (opt->len == 0 ||
1525 ((
char *)opt->value)[opt->len - 1] !=
'\0') {
1529 return (opt->value);
1541 TAILQ_FOREACH(opt, opts, link) {
1542 if (strcmp(name, opt->name) == 0) {
1561 KASSERT(opts != NULL, (
"vfs_getopt: caller passed 'opts' as NULL"));
1563 TAILQ_FOREACH(opt, opts, link) {
1564 if (strcmp(name, opt->name) != 0)
1567 if (opt->len == 0 || opt->value == NULL)
1569 if (((
char *)opt->value)[opt->len - 1] !=
'\0')
1572 ret =
vsscanf(opt->value, fmt, ap);
1584 TAILQ_FOREACH(opt, opts, link) {
1585 if (strcmp(name, opt->name) != 0)
1588 if (opt->value == NULL)
1591 if (opt->len != len)
1593 bcopy(value, opt->value, len);
1605 TAILQ_FOREACH(opt, opts, link) {
1606 if (strcmp(name, opt->name) != 0)
1609 if (opt->value == NULL)
1615 bcopy(value, opt->value, len);
1627 TAILQ_FOREACH(opt, opts, link) {
1628 if (strcmp(name, opt->name) != 0)
1631 if (opt->value == NULL)
1632 opt->len = strlen(value) + 1;
1633 else if (strlcpy(opt->value, value, opt->len) >= opt->len)
1650 struct vfsoptlist *opts;
1657 KASSERT(opts != NULL, (
"vfs_copyopt: caller passed 'opts' as NULL"));
1659 TAILQ_FOREACH(opt, opts, link) {
1660 if (strcmp(name, opt->name) == 0) {
1662 if (len != opt->len)
1664 bcopy(opt->value, dest, opt->len);
1685 mtx_assert(MNT_MTX(mp), MA_OWNED);
1687 KASSERT((*mvp)->v_mount == mp, (
"marker vnode mount list mismatch"));
1693 vp = TAILQ_NEXT(*mvp, v_nmntvnodes);
1694 while (vp != NULL && vp->v_type == VMARKER)
1695 vp = TAILQ_NEXT(vp, v_nmntvnodes);
1702 TAILQ_REMOVE(&mp->mnt_nvnodelist, *mvp, v_nmntvnodes);
1703 TAILQ_INSERT_AFTER(&mp->mnt_nvnodelist, vp, *mvp, v_nmntvnodes);
1712 mtx_assert(MNT_MTX(mp), MA_OWNED);
1714 vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
1715 while (vp != NULL && vp->v_type == VMARKER)
1716 vp = TAILQ_NEXT(vp, v_nmntvnodes);
1725 *mvp = (
struct vnode *)
malloc(
sizeof(
struct vnode),
1729 (*mvp)->v_type = VMARKER;
1731 vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
1732 while (vp != NULL && vp->v_type == VMARKER)
1733 vp = TAILQ_NEXT(vp, v_nmntvnodes);
1738 free(*mvp, M_VNODE_MARKER);
1744 (*mvp)->v_mount = mp;
1745 TAILQ_INSERT_AFTER(&mp->mnt_nvnodelist, vp, *mvp, v_nmntvnodes);
1757 mtx_assert(MNT_MTX(mp), MA_OWNED);
1759 KASSERT((*mvp)->v_mount == mp, (
"marker vnode mount list mismatch"));
1760 TAILQ_REMOVE(&mp->mnt_nvnodelist, *mvp, v_nmntvnodes);
1762 free(*mvp, M_VNODE_MARKER);
1773 error = mp->mnt_op->vfs_statfs(mp, &mp->mnt_stat);
1774 if (sbp != &mp->mnt_stat)
1775 *sbp = mp->mnt_stat;
1783 bzero(mp->mnt_stat.f_mntfromname,
sizeof mp->mnt_stat.f_mntfromname);
1784 strlcpy(mp->mnt_stat.f_mntfromname, from,
1785 sizeof mp->mnt_stat.f_mntfromname);
1822 KASSERT(name[0] ==
'n' && name[1] ==
'o',
1823 (
"mount_argb(...,%s): name must start with 'no'", name));
1825 return (
mount_arg(ma, name + (flag ? 2 : 0), NULL, 0));
1840 ma =
malloc(
sizeof *ma, M_MOUNT, M_WAITOK | M_ZERO);
1841 SLIST_INIT(&ma->list);
1848 ma->
v[ma->
len].iov_base = (
void *)(uintptr_t)
name;
1849 ma->
v[ma->
len].iov_len = strlen(name) + 1;
1852 sb = sbuf_new_auto();
1858 maa =
malloc(
sizeof *maa + len, M_MOUNT, M_WAITOK | M_ZERO);
1859 SLIST_INSERT_HEAD(&ma->list, maa, next);
1863 ma->
v[ma->
len].iov_base = maa + 1;
1882 ma =
malloc(
sizeof *ma, M_MOUNT, M_WAITOK | M_ZERO);
1883 SLIST_INIT(&ma->list);
1887 maa =
malloc(
sizeof *maa + len, M_MOUNT, M_WAITOK | M_ZERO);
1888 SLIST_INSERT_HEAD(&ma->list, maa, next);
1889 tbuf = (
void *)(maa + 1);
1890 ma->
error = copyinstr(val, tbuf, len, NULL);
1904 ma =
malloc(
sizeof *ma, M_MOUNT, M_WAITOK | M_ZERO);
1905 SLIST_INIT(&ma->list);
1912 ma->
v[ma->
len].iov_base = (
void *)(uintptr_t)
name;
1913 ma->
v[ma->
len].iov_len = strlen(name) + 1;
1916 ma->
v[ma->
len].iov_base = (
void *)(uintptr_t)val;
1918 ma->
v[ma->
len].iov_len = strlen(val) + 1;
1933 while (!SLIST_EMPTY(&ma->list)) {
1934 maa = SLIST_FIRST(&ma->list);
1935 SLIST_REMOVE_HEAD(&ma->list, next);
1938 free(ma->
v, M_MOUNT);
1951 KASSERT(ma != NULL, (
"kernel_mount NULL ma"));
1952 KASSERT(ma->
v != NULL, (
"kernel_mount NULL ma->v"));
1953 KASSERT(!(ma->
len & 1), (
"kernel_mount odd ma->len (%d)", ma->
len));
1955 auio.uio_iov = ma->
v;
1956 auio.uio_iovcnt = ma->
len;
1957 auio.uio_segflg = UIO_SYSSPACE;
1972 struct mntarg *ma = NULL;
1978 va_start(ap, flags);
1980 cp = va_arg(ap,
const char *);
1983 vp = va_arg(ap,
const void *);
1984 ma =
mount_arg(ma, cp, vp, (vp != NULL ? -1 : 0));
1996 bcopy(oexp, exp,
sizeof(*oexp));
1997 exp->ex_numsecflavors = 0;
void lockdestroy(struct lock *lk)
void vfs_event_signal(fsid_t *fsid, uint32_t event, intptr_t data __unused)
struct mntarg * mount_argb(struct mntarg *ma, int flag, const char *name)
int vfs_suser(struct mount *mp, struct thread *td)
void vfs_deleteopt(struct vfsoptlist *opts, const char *name)
void vfs_allocate_syncvnode(struct mount *mp)
static void mount_fini(void *mem, int size)
int vinvalbuf(struct vnode *vp, int flags, int slpflag, int slptimeo)
void * realloc(void *addr, unsigned long size, struct malloc_type *mtp, int flags)
MTX_SYSINIT(mountlist,&mountlist_mtx,"mountlist", MTX_DEF)
void NDFREE(struct nameidata *ndp, const u_int flags)
int vfs_setopts(struct vfsoptlist *opts, const char *name, const char *value)
int snprintf(char *str, size_t size, const char *format,...)
void vfs_deallocate_syncvnode(struct mount *mp)
int priv_check_cred(struct ucred *cred, int priv, int flags)
ssize_t sbuf_len(struct sbuf *s)
void vfs_freeopts(struct vfsoptlist *opts)
int __vfs_statfs(struct mount *mp, struct statfs *sbp)
#define VFS_MOUNTARG_SIZE_MAX
static void vfs_mount_init(void *dummy __unused)
SYSINIT(vfs_mount, SI_SUB_VFS, SI_ORDER_ANY, vfs_mount_init, NULL)
int sys_mount(struct thread *td, struct mount_args *uap)
int vfs_flagopt(struct vfsoptlist *opts, const char *name, uint64_t *w, uint64_t val)
void vfs_rel(struct mount *mp)
void vfs_opterror(struct vfsoptlist *opts, const char *fmt,...)
void mountcheckdirs(struct vnode *olddp, struct vnode *newdp)
int vfs_export(struct mount *mp, struct export_args *argp)
void * malloc(unsigned long size, struct malloc_type *mtp, int flags)
void cache_purge(struct vnode *vp)
int vn_path_to_global_path(struct thread *td, struct vnode *vp, char *path, u_int pathlen)
int vfs_getopt(struct vfsoptlist *opts, const char *name, void **buf, int *len)
static int vfs_domount(struct thread *td, const char *fstype, char *fspath, uint64_t fsflags, struct vfsoptlist **optlist)
void panic(const char *fmt,...)
void vn_finished_write(struct mount *mp)
int vfs_copyopt(struct vfsoptlist *opts, const char *name, void *dest, int len)
int kernel_vmount(int flags,...)
int vfs_setopt(struct vfsoptlist *opts, const char *name, void *value, int len)
int dounmount(struct mount *mp, int flags, struct thread *td)
static int vfs_equalopts(const char *opt1, const char *opt2)
MALLOC_DECLARE(M_VNODE_MARKER)
void vfs_mount_error(struct mount *mp, const char *fmt,...)
struct vfsconf * vfs_byname_kld(const char *fstype, struct thread *td, int *error)
int sys_nmount(struct thread *td, struct nmount_args *uap)
static void free_mntarg(struct mntarg *ma)
static void vfs_freeopt(struct vfsoptlist *opts, struct vfsopt *opt)
SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW,&usermount, 0,"Unprivileged users may mount and unmount file systems")
int sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
void __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp)
struct vfsconfhead vfsconf
int vsnprintf(char *str, size_t size, const char *format, va_list ap)
void vdrop(struct vnode *vp)
int vfs_setpublicfs(struct mount *mp, struct netexport *nep, struct export_args *argp)
int priv_check(struct thread *td, int priv)
int vfs_getopt_pos(struct vfsoptlist *opts, const char *name)
void vref(struct vnode *vp)
static int vfs_domount_first(struct thread *td, struct vfsconf *vfsp, char *fspath, struct vnode *vp, uint64_t fsflags, struct vfsoptlist **optlist)
struct vfsconf * vfs_byname(const char *name)
void vput(struct vnode *vp)
struct mount * vfs_mount_alloc(struct vnode *vp, struct vfsconf *vfsp, const char *fspath, struct ucred *cred)
static int vfs_isopt_ro(const char *opt)
void vfs_ref(struct mount *mp)
int sys_unmount(struct thread *td, struct unmount_args *uap)
int jailed(struct ucred *cred)
void cache_purgevfs(struct mount *mp)
int vfs_filteropt(struct vfsoptlist *opts, const char **legal)
void vfs_unbusy(struct mount *mp)
static void vfs_mergeopts(struct vfsoptlist *toopts, struct vfsoptlist *oldopts)
MALLOC_DEFINE(M_MOUNT,"mount","vfs mount structure")
int namei(struct nameidata *ndp)
void vfs_mountedfrom(struct mount *mp, const char *from)
static int vfs_isopt_rw(const char *opt)
void crfree(struct ucred *cr)
struct mntarg * mount_arg(struct mntarg *ma, const char *name, const void *val, int len)
char * vfs_getopts(struct vfsoptlist *opts, const char *name, int *error)
void vholdl(struct vnode *vp)
static void vfs_sanitizeopts(struct vfsoptlist *opts)
int vfs_setopt_part(struct vfsoptlist *opts, const char *name, void *value, int len)
int vfs_buildopts(struct uio *auio, struct vfsoptlist **options)
static uma_zone_t mount_zone
int kernel_mount(struct mntarg *ma, uint64_t flags)
void free(void *addr, struct malloc_type *mtp)
struct ucred * crdup(struct ucred *cr)
int printf(const char *fmt,...)
int vfs_busy(struct mount *mp, int flags)
static int vfs_domount_update(struct thread *td, struct vnode *vp, uint64_t fsflags, struct vfsoptlist **optlist)
static const char * global_opts[]
void sbuf_delete(struct sbuf *s)
void kern_yield(int prio)
struct mntarg * mount_argsu(struct mntarg *ma, const char *name, const void *val, int len)
int copyinuio(struct iovec *iovp, u_int iovcnt, struct uio **uiop)
struct mntarg * mount_argf(struct mntarg *ma, const char *name, const char *fmt,...)
void vfs_oexport_conv(const struct oexport_args *oexp, struct export_args *exp)
void mtx_init(struct mtx *m, const char *name, const char *type, int opts)
void vrele(struct vnode *vp)
int vn_start_write(struct vnode *vp, struct mount **mpp, int flags)
char * sbuf_data(struct sbuf *s)
int sscanf(const char *ibuf, const char *fmt,...)
int sbuf_finish(struct sbuf *s)
struct vnode * __mnt_vnode_next(struct vnode **mvp, struct mount *mp)
void vfs_mount_destroy(struct mount *mp)
static int mount_init(void *mem, int size, int flags)
int vsscanf(const char *inp, char const *fmt0, va_list ap)
SLIST_HEAD(et_eventtimers_list, eventtimer)
struct vnode * __mnt_vnode_first(struct vnode **mvp, struct mount *mp)
void mtx_destroy(struct mtx *m)
int vfs_donmount(struct thread *td, uint64_t fsflags, struct uio *fsoptions)
void vfs_msync(struct mount *mp, int flags)
int vfs_scanopt(struct vfsoptlist *opts, const char *name, const char *fmt,...)
void lockinit(struct lock *lk, int pri, const char *wmesg, int timo, int flags)