X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/43866e378188c25dd1e2208016ab3cbeb086ae6c..143464d58d2bd6378e74eec636961ceb0d32fb91:/bsd/miscfs/devfs/devfs_vfsops.c?ds=sidebyside diff --git a/bsd/miscfs/devfs/devfs_vfsops.c b/bsd/miscfs/devfs/devfs_vfsops.c index 84cc758ae..b40778e88 100644 --- a/bsd/miscfs/devfs/devfs_vfsops.c +++ b/bsd/miscfs/devfs/devfs_vfsops.c @@ -1,16 +1,19 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2010 Apple Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ - * - * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER @@ -20,7 +23,7 @@ * Please see the License for the specific language governing rights and * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /*- * Copyright 1997,1998 Julian Elischer. All rights reserved. @@ -50,6 +53,12 @@ * devfs_vfsops.c * */ +/* + * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce + * support for mandatory and extensible security protections. This notice + * is included in support of clause 2.2 (b) of the Apple Public License, + * Version 2.0. + */ /* * HISTORY * Dieter Siegmund (dieter@apple.com) Wed Jul 14 13:37:59 PDT 1999 @@ -61,19 +70,33 @@ #include #include #include -#include +#include #include -#include +#include +#include #include +#include + +#if CONFIG_MACF +#include +#endif + #include "devfs.h" #include "devfsdefs.h" -static int devfs_statfs( struct mount *mp, struct statfs *sbp, struct proc *p); +#if FDESC +#include "fdesc.h" +#endif /* FDESC */ + -static struct vfsconf * devfs_vfsp = 0; -static int kernel_mount = 0; +static int devfs_statfs( struct mount *mp, struct vfsstatfs *sbp, vfs_context_t ctx); +static int devfs_vfs_getattr(mount_t mp, struct vfs_attr *fsap, vfs_context_t ctx); +#if !defined(SECURE_KERNEL) +extern int setup_kmem; +__private_extern__ void devfs_setup_kmem(void); +#endif /*- * Called from the generic VFS startups. @@ -84,30 +107,45 @@ static int kernel_mount = 0; * devices from devfs get sync'd. */ static int -devfs_init(struct vfsconf *vfsp) +devfs_init(__unused struct vfsconf *vfsp) { - devfs_vfsp = vfsp; /* remember this for devfs_kernel_mount below */ - if (devfs_sinit()) - return (EOPNOTSUPP); - printf("devfs enabled\n"); + return (ENOTSUP); devfs_make_node(makedev(0, 0), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0622, "console"); devfs_make_node(makedev(2, 0), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0666, "tty"); - devfs_make_node(makedev(3, 0), DEVFS_CHAR, - UID_ROOT, GID_KMEM, 0640, "mem"); - devfs_make_node(makedev(3, 1), DEVFS_CHAR, - UID_ROOT, GID_KMEM, 0640, "kmem"); +#if !defined(SECURE_KERNEL) + if (setup_kmem) { + devfs_setup_kmem(); + } +#endif devfs_make_node(makedev(3, 2), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0666, "null"); devfs_make_node(makedev(3, 3), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0666, "zero"); devfs_make_node(makedev(6, 0), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0600, "klog"); + +#if FDESC + devfs_fdesc_init(); +#endif + return 0; } +#if !defined(SECURE_KERNEL) +__private_extern__ void +devfs_setup_kmem(void) +{ + devfs_make_node(makedev(3, 0), DEVFS_CHAR, + UID_ROOT, GID_KMEM, 0640, "mem"); + devfs_make_node(makedev(3, 1), DEVFS_CHAR, + UID_ROOT, GID_KMEM, 0640, "kmem"); +} +#endif + + /*- * mp - pointer to 'mount' structure * path - addr in user space of mount point (ie /usr or whatever) @@ -123,12 +161,10 @@ devfs_init(struct vfsconf *vfsp) */ /*proto*/ int -devfs_mount(struct mount *mp, char *path, caddr_t data, - struct nameidata *ndp, struct proc *p) +devfs_mount(struct mount *mp, __unused vnode_t devvp, __unused user_addr_t data, vfs_context_t ctx) { struct devfsmount *devfs_mp_p; /* devfs specific mount info */ int error; - size_t size; /*- * If they just want to update, we don't need to do anything. @@ -138,6 +174,9 @@ devfs_mount(struct mount *mp, char *path, caddr_t data, return 0; } + /* Advisory locking should be handled at the VFS layer */ + vfs_setlocklocal(mp); + /*- * Well, it's not an update, it's a real mount request. * Time to get dirty. @@ -155,19 +194,20 @@ devfs_mount(struct mount *mp, char *path, caddr_t data, * Fill out some fields */ mp->mnt_data = (qaddr_t)devfs_mp_p; - mp->mnt_stat.f_type = mp->mnt_vfc->vfc_typenum; - mp->mnt_stat.f_fsid.val[0] = (int32_t)(void *)devfs_mp_p; - mp->mnt_stat.f_fsid.val[1] = mp->mnt_stat.f_type; + mp->mnt_vfsstat.f_fsid.val[0] = (int32_t)(uintptr_t)devfs_mp_p; + mp->mnt_vfsstat.f_fsid.val[1] = vfs_typenum(mp); mp->mnt_flag |= MNT_LOCAL; - DEVFS_LOCK(p); + DEVFS_LOCK(); error = dev_dup_plane(devfs_mp_p); - DEVFS_UNLOCK(p); + DEVFS_UNLOCK(); + if (error) { mp->mnt_data = (qaddr_t)0; FREE((caddr_t)devfs_mp_p, M_DEVFSMNT); return (error); - } + } else + DEVFS_INCR_MOUNTS(); /*- * Copy in the name of the directory the filesystem @@ -176,22 +216,16 @@ devfs_mount(struct mount *mp, char *path, caddr_t data, * to be tidy. */ - if (!kernel_mount) { - copyinstr(path, (caddr_t)mp->mnt_stat.f_mntonname, - sizeof(mp->mnt_stat.f_mntonname)-1, &size); - bzero(mp->mnt_stat.f_mntonname + size, - sizeof(mp->mnt_stat.f_mntonname) - size); - } - bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); - bcopy("devfs",mp->mnt_stat.f_mntfromname, 5); - DEVFS_INCR_MOUNTS(); - (void)devfs_statfs(mp, &mp->mnt_stat, p); + bzero(mp->mnt_vfsstat.f_mntfromname, MAXPATHLEN); + bcopy("devfs",mp->mnt_vfsstat.f_mntfromname, 5); + (void)devfs_statfs(mp, &mp->mnt_vfsstat, ctx); + return 0; } static int -devfs_start(struct mount *mp, int flags, struct proc *p) +devfs_start(__unused struct mount *mp, __unused int flags, __unused vfs_context_t ctx) { return 0; } @@ -200,7 +234,7 @@ devfs_start(struct mount *mp, int flags, struct proc *p) * Unmount the filesystem described by mp. */ static int -devfs_unmount( struct mount *mp, int mntflags, struct proc *p) +devfs_unmount( struct mount *mp, int mntflags, __unused vfs_context_t ctx) { struct devfsmount *devfs_mp_p = (struct devfsmount *)mp->mnt_data; int flags = 0; @@ -215,11 +249,13 @@ devfs_unmount( struct mount *mp, int mntflags, struct proc *p) if (error && !force) return error; - DEVFS_LOCK(p); + DEVFS_LOCK(); devfs_free_plane(devfs_mp_p); - DEVFS_UNLOCK(p); - FREE((caddr_t)devfs_mp_p, M_DEVFSMNT); + DEVFS_UNLOCK(); + DEVFS_DECR_MOUNTS(); + + FREE((caddr_t)devfs_mp_p, M_DEVFSMNT); mp->mnt_data = (qaddr_t)0; mp->mnt_flag &= ~MNT_LOCAL; @@ -228,32 +264,28 @@ devfs_unmount( struct mount *mp, int mntflags, struct proc *p) /* return the address of the root vnode in *vpp */ static int -devfs_root(struct mount *mp, struct vnode **vpp) +devfs_root(struct mount *mp, struct vnode **vpp, __unused vfs_context_t ctx) { struct devfsmount *devfs_mp_p = (struct devfsmount *)(mp->mnt_data); int error; - error = devfs_dntovn(devfs_mp_p->plane_root->de_dnp,vpp, - current_proc()); - return error; -} + DEVFS_LOCK(); + /* last parameter to devfs_dntovn() is ignored */ + error = devfs_dntovn(devfs_mp_p->plane_root->de_dnp, vpp, NULL); + DEVFS_UNLOCK(); -static int -devfs_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg, - struct proc *p) -{ - return EOPNOTSUPP; + return error; } static int -devfs_statfs( struct mount *mp, struct statfs *sbp, struct proc *p) +devfs_statfs( struct mount *mp, struct vfsstatfs *sbp, __unused vfs_context_t ctx) { struct devfsmount *devfs_mp_p = (struct devfsmount *)mp->mnt_data; /*- * Fill in the stat block. */ - sbp->f_type = mp->mnt_stat.f_type; + //sbp->f_type = mp->mnt_vfsstat.f_type; sbp->f_flags = 0; /* XXX */ sbp->f_bsize = 512; sbp->f_iosize = 512; @@ -266,34 +298,151 @@ devfs_statfs( struct mount *mp, struct statfs *sbp, struct proc *p) sbp->f_bavail = 0; sbp->f_files = devfs_stats.nodes; sbp->f_ffree = 0; - sbp->f_fsid.val[0] = (int32_t)(void *)devfs_mp_p; - sbp->f_fsid.val[1] = mp->mnt_stat.f_type; + sbp->f_fsid.val[0] = (int32_t)(uintptr_t)devfs_mp_p; + sbp->f_fsid.val[1] = vfs_typenum(mp); - /*- - * Copy the mounted on and mounted from names into - * the passed in stat block, if it is not the one - * in the mount structure. - */ - if (sbp != &mp->mnt_stat) { - bcopy((caddr_t)mp->mnt_stat.f_mntonname, - (caddr_t)&sbp->f_mntonname[0], MNAMELEN); - bcopy((caddr_t)mp->mnt_stat.f_mntfromname, - (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); + return 0; +} + +static int +devfs_vfs_getattr(__unused mount_t mp, struct vfs_attr *fsap, __unused vfs_context_t ctx) +{ + VFSATTR_RETURN(fsap, f_objcount, devfs_stats.nodes); + VFSATTR_RETURN(fsap, f_maxobjcount, devfs_stats.nodes); + VFSATTR_RETURN(fsap, f_bsize, 512); + VFSATTR_RETURN(fsap, f_iosize, 512); + if (VFSATTR_IS_ACTIVE(fsap, f_blocks) || VFSATTR_IS_ACTIVE(fsap, f_bused)) { + fsap->f_blocks = (devfs_stats.mounts * sizeof(struct devfsmount) + + devfs_stats.nodes * sizeof(devnode_t) + + devfs_stats.entries * sizeof(devdirent_t) + + devfs_stats.stringspace + ) / fsap->f_bsize; + fsap->f_bused = fsap->f_blocks; + VFSATTR_SET_SUPPORTED(fsap, f_blocks); + VFSATTR_SET_SUPPORTED(fsap, f_bused); } + VFSATTR_RETURN(fsap, f_bfree, 0); + VFSATTR_RETURN(fsap, f_bavail, 0); + VFSATTR_RETURN(fsap, f_files, devfs_stats.nodes); + VFSATTR_RETURN(fsap, f_ffree, 0); + VFSATTR_RETURN(fsap, f_fssubtype, 0); + + if (VFSATTR_IS_ACTIVE(fsap, f_capabilities)) { + fsap->f_capabilities.capabilities[VOL_CAPABILITIES_FORMAT] = + VOL_CAP_FMT_SYMBOLICLINKS | + VOL_CAP_FMT_HARDLINKS | + VOL_CAP_FMT_NO_ROOT_TIMES | + VOL_CAP_FMT_CASE_SENSITIVE | + VOL_CAP_FMT_CASE_PRESERVING | + VOL_CAP_FMT_FAST_STATFS | + VOL_CAP_FMT_2TB_FILESIZE | + VOL_CAP_FMT_HIDDEN_FILES; + fsap->f_capabilities.capabilities[VOL_CAPABILITIES_INTERFACES] = + VOL_CAP_INT_ATTRLIST ; + fsap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED1] = 0; + fsap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED2] = 0; + + fsap->f_capabilities.valid[VOL_CAPABILITIES_FORMAT] = + VOL_CAP_FMT_PERSISTENTOBJECTIDS | + VOL_CAP_FMT_SYMBOLICLINKS | + VOL_CAP_FMT_HARDLINKS | + VOL_CAP_FMT_JOURNAL | + VOL_CAP_FMT_JOURNAL_ACTIVE | + VOL_CAP_FMT_NO_ROOT_TIMES | + VOL_CAP_FMT_SPARSE_FILES | + VOL_CAP_FMT_ZERO_RUNS | + VOL_CAP_FMT_CASE_SENSITIVE | + VOL_CAP_FMT_CASE_PRESERVING | + VOL_CAP_FMT_FAST_STATFS | + VOL_CAP_FMT_2TB_FILESIZE | + VOL_CAP_FMT_OPENDENYMODES | + VOL_CAP_FMT_HIDDEN_FILES | + VOL_CAP_FMT_PATH_FROM_ID | + VOL_CAP_FMT_NO_VOLUME_SIZES; + fsap->f_capabilities.valid[VOL_CAPABILITIES_INTERFACES] = + VOL_CAP_INT_SEARCHFS | + VOL_CAP_INT_ATTRLIST | + VOL_CAP_INT_NFSEXPORT | + VOL_CAP_INT_READDIRATTR | + VOL_CAP_INT_EXCHANGEDATA | + VOL_CAP_INT_COPYFILE | + VOL_CAP_INT_ALLOCATE | + VOL_CAP_INT_VOL_RENAME | + VOL_CAP_INT_ADVLOCK | + VOL_CAP_INT_FLOCK | + VOL_CAP_INT_EXTENDED_SECURITY | + VOL_CAP_INT_USERACCESS | + VOL_CAP_INT_MANLOCK | + VOL_CAP_INT_EXTENDED_ATTR | + VOL_CAP_INT_NAMEDSTREAMS; + fsap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED1] = 0; + fsap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED2] = 0; + + VFSATTR_SET_SUPPORTED(fsap, f_capabilities); + } + + if (VFSATTR_IS_ACTIVE(fsap, f_attributes)) { + fsap->f_attributes.validattr.commonattr = + ATTR_CMN_NAME | ATTR_CMN_DEVID | ATTR_CMN_FSID | + ATTR_CMN_OBJTYPE | ATTR_CMN_OBJTAG | ATTR_CMN_OBJID | + ATTR_CMN_PAROBJID | + ATTR_CMN_MODTIME | ATTR_CMN_CHGTIME | ATTR_CMN_ACCTIME | + ATTR_CMN_OWNERID | ATTR_CMN_GRPID | ATTR_CMN_ACCESSMASK | + ATTR_CMN_FLAGS | ATTR_CMN_USERACCESS | ATTR_CMN_FILEID; + fsap->f_attributes.validattr.volattr = + ATTR_VOL_FSTYPE | ATTR_VOL_SIZE | ATTR_VOL_SPACEFREE | + ATTR_VOL_SPACEAVAIL | ATTR_VOL_MINALLOCATION | + ATTR_VOL_OBJCOUNT | ATTR_VOL_MAXOBJCOUNT | + ATTR_VOL_MOUNTPOINT | ATTR_VOL_MOUNTFLAGS | + ATTR_VOL_MOUNTEDDEVICE | ATTR_VOL_CAPABILITIES | + ATTR_VOL_ATTRIBUTES; + fsap->f_attributes.validattr.dirattr = + ATTR_DIR_LINKCOUNT | ATTR_DIR_MOUNTSTATUS; + fsap->f_attributes.validattr.fileattr = + ATTR_FILE_LINKCOUNT | ATTR_FILE_TOTALSIZE | + ATTR_FILE_IOBLOCKSIZE | ATTR_FILE_DEVTYPE | + ATTR_FILE_DATALENGTH; + fsap->f_attributes.validattr.forkattr = 0; + + fsap->f_attributes.nativeattr.commonattr = + ATTR_CMN_NAME | ATTR_CMN_DEVID | ATTR_CMN_FSID | + ATTR_CMN_OBJTYPE | ATTR_CMN_OBJTAG | ATTR_CMN_OBJID | + ATTR_CMN_PAROBJID | + ATTR_CMN_MODTIME | ATTR_CMN_CHGTIME | ATTR_CMN_ACCTIME | + ATTR_CMN_OWNERID | ATTR_CMN_GRPID | ATTR_CMN_ACCESSMASK | + ATTR_CMN_FLAGS | ATTR_CMN_USERACCESS | ATTR_CMN_FILEID; + fsap->f_attributes.nativeattr.volattr = + ATTR_VOL_FSTYPE | ATTR_VOL_SIZE | ATTR_VOL_SPACEFREE | + ATTR_VOL_SPACEAVAIL | ATTR_VOL_MINALLOCATION | + ATTR_VOL_OBJCOUNT | ATTR_VOL_MAXOBJCOUNT | + ATTR_VOL_MOUNTPOINT | ATTR_VOL_MOUNTFLAGS | + ATTR_VOL_MOUNTEDDEVICE | ATTR_VOL_CAPABILITIES | + ATTR_VOL_ATTRIBUTES; + fsap->f_attributes.nativeattr.dirattr = + ATTR_DIR_MOUNTSTATUS; + fsap->f_attributes.nativeattr.fileattr = + ATTR_FILE_LINKCOUNT | ATTR_FILE_TOTALSIZE | + ATTR_FILE_IOBLOCKSIZE | ATTR_FILE_DEVTYPE | + ATTR_FILE_DATALENGTH; + fsap->f_attributes.nativeattr.forkattr = 0; + + VFSATTR_SET_SUPPORTED(fsap, f_attributes); + } + return 0; } static int -devfs_sync(struct mount *mp, int waitfor,struct ucred *cred,struct proc *p) +devfs_sync(__unused struct mount *mp, __unused int waitfor, __unused vfs_context_t ctx) { return (0); } static int -devfs_vget(struct mount *mp, void * ino,struct vnode **vpp) +devfs_vget(__unused struct mount *mp, __unused ino64_t ino, __unused struct vnode **vpp, __unused vfs_context_t ctx) { - return EOPNOTSUPP; + return ENOTSUP; } /************************************************************* @@ -302,30 +451,24 @@ devfs_vget(struct mount *mp, void * ino,struct vnode **vpp) */ static int -devfs_fhtovp (struct mount *mp, struct fid *fhp, struct mbuf *nam, - struct vnode **vpp, int *exflagsp, struct ucred **credanonp) +devfs_fhtovp (__unused struct mount *mp, __unused int fhlen, __unused unsigned char *fhp, __unused struct vnode **vpp, __unused vfs_context_t ctx) { return (EINVAL); } static int -devfs_vptofh (struct vnode *vp, struct fid *fhp) +devfs_vptofh (__unused struct vnode *vp, __unused int *fhlenp, __unused unsigned char *fhp, __unused vfs_context_t ctx) { return (EINVAL); } static int -devfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) - int *name; - u_int namelen; - void *oldp; - size_t *oldlenp; - void *newp; - size_t newlen; - struct proc *p; +devfs_sysctl(__unused int *name, __unused u_int namelen, __unused user_addr_t oldp, + __unused size_t *oldlenp, __unused user_addr_t newp, + __unused size_t newlen, __unused vfs_context_t ctx) { - return (EOPNOTSUPP); + return (ENOTSUP); } #include @@ -340,83 +483,107 @@ devfs_kernel_mount(char * mntname) { struct mount *mp; int error; - struct proc *procp; struct nameidata nd; struct vnode * vp; + vfs_context_t ctx = vfs_context_kernel(); + struct vfstable *vfsp; - if (devfs_vfsp == NULL) { - printf("devfs_kernel_mount: devfs_vfsp is NULL\n"); - return (EINVAL); - } - procp = current_proc(); + /* Find our vfstable entry */ + for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) + if (!strncmp(vfsp->vfc_name, "devfs", sizeof(vfsp->vfc_name))) + break; + + if (!vfsp) { + panic("Could not find entry in vfsconf for devfs.\n"); + } /* * Get vnode to be covered */ - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, - mntname, procp); + NDINIT(&nd, LOOKUP, OP_MOUNT, FOLLOW | LOCKLEAF, UIO_SYSSPACE, + CAST_USER_ADDR_T(mntname), ctx); if ((error = namei(&nd))) { - printf("devfs_kernel_mount: failed to find directory '%s', %d", + printf("devfs_kernel_mount: failed to find directory '%s', %d\n", mntname, error); return (error); } + nameidone(&nd); vp = nd.ni_vp; - if ((error = vinvalbuf(vp, V_SAVE, procp->p_ucred, procp, 0, 0))) { - printf("devfs_kernel_mount: vinval failed: %d\n", error); - vput(vp); + + if ((error = VNOP_FSYNC(vp, MNT_WAIT, ctx))) { + printf("devfs_kernel_mount: vnop_fsync failed: %d\n", error); + vnode_put(vp); + return (error); + } + if ((error = buf_invalidateblks(vp, BUF_WRITE_DATA, 0, 0))) { + printf("devfs_kernel_mount: buf_invalidateblks failed: %d\n", error); + vnode_put(vp); return (error); } - if (vp->v_type != VDIR) { + if (vnode_isdir(vp) == 0) { printf("devfs_kernel_mount: '%s' is not a directory\n", mntname); - vput(vp); + vnode_put(vp); return (ENOTDIR); } - if (vp->v_mountedhere != NULL) { - vput(vp); + if ((vnode_mountedhere(vp))) { + vnode_put(vp); return (EBUSY); } /* * Allocate and initialize the filesystem. */ - mp = _MALLOC_ZONE((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); - bzero((char *)mp, (u_long)sizeof(struct mount)); - - /* Initialize the default IO constraints */ - mp->mnt_maxreadcnt = mp->mnt_maxwritecnt = MAXPHYS; - mp->mnt_segreadcnt = mp->mnt_segwritecnt = 32; - - lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0); - (void)vfs_busy(mp, LK_NOWAIT, 0, procp); - LIST_INIT(&mp->mnt_vnodelist); - mp->mnt_op = devfs_vfsp->vfc_vfsops; - mp->mnt_vfc = devfs_vfsp; - devfs_vfsp->vfc_refcount++; + MALLOC_ZONE(mp, struct mount *, sizeof(struct mount), + M_MOUNT, M_WAITOK); + bzero((char *)mp, sizeof(struct mount)); + + /* Initialize the default IO constraints */ + mp->mnt_maxreadcnt = mp->mnt_maxwritecnt = MAXPHYS; + mp->mnt_segreadcnt = mp->mnt_segwritecnt = 32; + mp->mnt_ioflags = 0; + mp->mnt_realrootvp = NULLVP; + mp->mnt_authcache_ttl = CACHED_LOOKUP_RIGHT_TTL; + + mount_lock_init(mp); + TAILQ_INIT(&mp->mnt_vnodelist); + TAILQ_INIT(&mp->mnt_workerqueue); + TAILQ_INIT(&mp->mnt_newvnodes); + + (void)vfs_busy(mp, LK_NOWAIT); + mp->mnt_op = &devfs_vfsops; + mp->mnt_vtable = vfsp; mp->mnt_flag = 0; - mp->mnt_flag |= devfs_vfsp->vfc_flags & MNT_VISFLAGMASK; - strncpy(mp->mnt_stat.f_fstypename, devfs_vfsp->vfc_name, MFSNAMELEN); + mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; + strlcpy(mp->mnt_vfsstat.f_fstypename, vfsp->vfc_name, MFSTYPENAMELEN); vp->v_mountedhere = mp; mp->mnt_vnodecovered = vp; - mp->mnt_stat.f_owner = procp->p_ucred->cr_uid; - (void) copystr(mntname, mp->mnt_stat.f_mntonname, MNAMELEN - 1, 0); + mp->mnt_vfsstat.f_owner = kauth_cred_getuid(kauth_cred_get()); + (void) copystr(mntname, mp->mnt_vfsstat.f_mntonname, MAXPATHLEN - 1, 0); +#if CONFIG_MACF + mac_mount_label_init(mp); + mac_mount_label_associate(ctx, mp); +#endif + + error = devfs_mount(mp, NULL, USER_ADDR_NULL, ctx); - kernel_mount = 1; - error = devfs_mount(mp, mntname, NULL, NULL, procp); - kernel_mount = 0; if (error) { - printf("devfs_kernel_mount: mount %s failed: %d", mntname, error); - mp->mnt_vfc->vfc_refcount--; - vfs_unbusy(mp, procp); - _FREE_ZONE(mp, sizeof (struct mount), M_MOUNT); - vput(vp); + printf("devfs_kernel_mount: mount %s failed: %d\n", mntname, error); + mp->mnt_vtable->vfc_refcount--; + + vfs_unbusy(mp); + + mount_lock_destroy(mp); +#if CONFIG_MACF + mac_mount_label_destroy(mp); +#endif + FREE_ZONE(mp, sizeof (struct mount), M_MOUNT); + vnode_put(vp); return (error); } - printf("devfs on %s\n", mntname); - simple_lock(&mountlist_slock); - CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); - simple_unlock(&mountlist_slock); - VOP_UNLOCK(vp, 0, procp); - vfs_unbusy(mp, procp); + vnode_ref(vp); + vnode_put(vp); + vfs_unbusy(mp); + mount_list_add(mp); return (0); } @@ -425,12 +592,14 @@ struct vfsops devfs_vfsops = { devfs_start, devfs_unmount, devfs_root, - devfs_quotactl, - devfs_statfs, + NULL, /* quotactl */ + devfs_vfs_getattr, devfs_sync, devfs_vget, devfs_fhtovp, devfs_vptofh, devfs_init, devfs_sysctl, + NULL, + {NULL} };