X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/55e303ae13a4cf49d70f2294092726f2fffb9ef2..39236c6e673c41db228275375ab7fdb0f837b292:/bsd/vfs/vfs_init.c diff --git a/bsd/vfs/vfs_init.c b/bsd/vfs/vfs_init.c index 8f59fb010..f9dfc09e5 100644 --- a/bsd/vfs/vfs_init.c +++ b/bsd/vfs/vfs_init.c @@ -1,16 +1,19 @@ /* - * Copyright (c) 2000-2002 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 (c) 1995 NeXT Computer, Inc. All Rights Reserved */ /* @@ -62,20 +65,33 @@ * * @(#)vfs_init.c 8.5 (Berkeley) 5/11/95 */ +/* + * 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. + */ #include -#include +#include #include #include -#include +#include #include #include #include -#include #include #include +#include /* journal_init() */ +#if CONFIG_MACF +#include +#include +#endif +#if QUOTA +#include +#endif /* * Sigh, such primitive tools are these... @@ -86,7 +102,8 @@ #define DODEBUG(A) #endif -extern uid_t console_user; +__private_extern__ void vntblinit(void); + extern struct vnodeopv_desc *vfs_opv_descs[]; /* a list of lists of vnodeops defns */ extern struct vnodeop_desc *vfs_op_descs[]; @@ -99,17 +116,17 @@ extern struct vnodeop_desc *vfs_op_descs[]; */ int vfs_opv_numops; -typedef (*PFI)(); /* the standard Pointer to a Function returning an Int */ +typedef int (*PFIvp)(void *); /* * A miscellaneous routine. * A generic "default" routine that just returns an error. */ int -vn_default_error() +vn_default_error(void) { - return (EOPNOTSUPP); + return (ENOTSUP); } /* @@ -129,7 +146,7 @@ vn_default_error() * that is a(whole)nother story.) This is a feature. */ void -vfs_opv_init() +vfs_opv_init(void) { int i, j, k; int (***opv_desc_vector_p)(void *); @@ -146,9 +163,9 @@ vfs_opv_init() * Also handle backwards compatibility. */ if (*opv_desc_vector_p == NULL) { - MALLOC(*opv_desc_vector_p, PFI*, - vfs_opv_numops*sizeof(PFI), M_TEMP, M_WAITOK); - bzero (*opv_desc_vector_p, vfs_opv_numops*sizeof(PFI)); + MALLOC(*opv_desc_vector_p, PFIvp*, + vfs_opv_numops*sizeof(PFIvp), M_TEMP, M_WAITOK); + bzero (*opv_desc_vector_p, vfs_opv_numops*sizeof(PFIvp)); DODEBUG(printf("vector at %x allocated\n", opv_desc_vector_p)); } @@ -175,7 +192,7 @@ vfs_opv_init() */ if (opve_descp->opve_op->vdesc_offset == 0 && opve_descp->opve_op->vdesc_offset != - VOFFSET(vop_default)) { + VOFFSET(vnop_default)) { printf("operation %s not listed in %s.\n", opve_descp->opve_op->vdesc_name, "vfs_op_descs"); @@ -198,13 +215,13 @@ vfs_opv_init() /* * Force every operations vector to have a default routine. */ - if (opv_desc_vector[VOFFSET(vop_default)]==NULL) { + if (opv_desc_vector[VOFFSET(vnop_default)]==NULL) { panic("vfs_opv_init: operation vector without default routine."); } for (k = 0; kvfs_vfsops is encountered. */ - vattr_null(&va_null); numused_vfsslots = maxtypenum = 0; - for (vfsp = vfsconf, i = 0; i < maxvfsconf; i++, vfsp++) { + for (vfsp = vfsconf, i = 0; i < maxvfsslots; i++, vfsp++) { + struct vfsconf vfsc; if (vfsp->vfc_vfsops == (struct vfsops *)0) break; if (i) vfsconf[i-1].vfc_next = vfsp; if (maxtypenum <= vfsp->vfc_typenum) maxtypenum = vfsp->vfc_typenum + 1; - (*vfsp->vfc_vfsops->vfs_init)(vfsp); + + bzero(&vfsc, sizeof(struct vfsconf)); + vfsc.vfc_reserved1 = 0; + bcopy(vfsp->vfc_name, vfsc.vfc_name, sizeof(vfsc.vfc_name)); + vfsc.vfc_typenum = vfsp->vfc_typenum; + vfsc.vfc_refcount = vfsp->vfc_refcount; + vfsc.vfc_flags = vfsp->vfc_flags; + vfsc.vfc_reserved2 = 0; + vfsc.vfc_reserved3 = 0; + + (*vfsp->vfc_vfsops->vfs_init)(&vfsc); + numused_vfsslots++; } /* next vfc_typenum to be used */ maxvfsconf = maxtypenum; + + /* + * Initialize the vnop authorization scope. + */ + vnode_authorize_init(); + + /* + * Initialiize the quota system. + */ +#if QUOTA + dqinit(); +#endif + + /* + * create a mount point for dead vnodes + */ + 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_maxsegreadsize = mp->mnt_maxreadcnt; + mp->mnt_maxsegwritesize = mp->mnt_maxwritecnt; + mp->mnt_devblocksize = DEV_BSIZE; + mp->mnt_alignmentmask = PAGE_MASK; + mp->mnt_ioqueue_depth = MNT_DEFAULT_IOQUEUE_DEPTH; + mp->mnt_ioscale = 1; + mp->mnt_ioflags = 0; + mp->mnt_realrootvp = NULLVP; + mp->mnt_authcache_ttl = CACHED_LOOKUP_RIGHT_TTL; + + TAILQ_INIT(&mp->mnt_vnodelist); + TAILQ_INIT(&mp->mnt_workerqueue); + TAILQ_INIT(&mp->mnt_newvnodes); + mp->mnt_flag = MNT_LOCAL; + mp->mnt_lflag = MNT_LDEAD; + mount_lock_init(mp); + +#if CONFIG_MACF + mac_mount_label_init(mp); + mac_mount_label_associate(vfs_context_kernel(), mp); +#endif + dead_mountp = mp; +} + +void +vnode_list_lock(void) +{ + lck_spin_lock(vnode_list_spin_lock); +} + +void +vnode_list_unlock(void) +{ + lck_spin_unlock(vnode_list_spin_lock); +} + +void +mount_list_lock(void) +{ + lck_mtx_lock(mnt_list_mtx_lock); +} + +void +mount_list_unlock(void) +{ + lck_mtx_unlock(mnt_list_mtx_lock); +} + +void +mount_lock_init(mount_t mp) +{ + lck_mtx_init(&mp->mnt_mlock, mnt_lck_grp, mnt_lck_attr); + lck_mtx_init(&mp->mnt_renamelock, mnt_lck_grp, mnt_lck_attr); + lck_rw_init(&mp->mnt_rwlock, mnt_lck_grp, mnt_lck_attr); } +void +mount_lock_destroy(mount_t mp) +{ + lck_mtx_destroy(&mp->mnt_mlock, mnt_lck_grp); + lck_mtx_destroy(&mp->mnt_renamelock, mnt_lck_grp); + lck_rw_destroy(&mp->mnt_rwlock, mnt_lck_grp); +} + + /* - * Name: vfsconf_add + * Name: vfstable_add * * Description: Add a filesystem to the vfsconf list at the first * unused slot. If no slots are available, return an @@ -308,28 +529,34 @@ vfsinit() * * Warning: This code assumes that vfsconf[0] is non-empty. */ -int -vfsconf_add(struct vfsconf *nvfsp) +struct vfstable * +vfstable_add(struct vfstable *nvfsp) { int slot; - struct vfsconf *slotp; + struct vfstable *slotp, *allocated = NULL; - if (nvfsp == NULL) /* overkill */ - return (-1); - /* * Find the next empty slot; we recognize an empty slot by a * NULL-valued ->vfc_vfsops, so if we delete a VFS, we must * ensure we set the entry back to NULL. */ +findslot: + mount_list_lock(); for (slot = 0; slot < maxvfsslots; slot++) { if (vfsconf[slot].vfc_vfsops == NULL) break; } if (slot == maxvfsslots) { - /* out of static slots; allocate one instead */ - MALLOC(slotp, struct vfsconf *, sizeof(struct vfsconf), - M_TEMP, M_WAITOK); + if (allocated == NULL) { + mount_list_unlock(); + /* out of static slots; allocate one instead */ + MALLOC(allocated, struct vfstable *, sizeof(struct vfstable), + M_TEMP, M_WAITOK); + goto findslot; + } else { + slotp = allocated; + allocated = NULL; + } } else { slotp = &vfsconf[slot]; } @@ -341,7 +568,7 @@ vfsconf_add(struct vfsconf *nvfsp) * Note; Takes advantage of the fact that 'slot' was left * with the value of 'maxvfslots' in the allocation case. */ - bcopy(nvfsp, slotp, sizeof(struct vfsconf)); + bcopy(nvfsp, slotp, sizeof(struct vfstable)); if (slot != 0) { slotp->vfc_next = vfsconf[slot - 1].vfc_next; vfsconf[slot - 1].vfc_next = slotp; @@ -350,22 +577,17 @@ vfsconf_add(struct vfsconf *nvfsp) } numused_vfsslots++; - /* - * Call through the ->vfs_init(); use slotp instead of nvfsp, - * so that if the FS cares where it's instance record is, it - * can find it later. - * - * XXX All code that calls ->vfs_init treats it as if it - * XXX returns a "void', and can never fail. - */ - if (nvfsp->vfc_vfsops->vfs_init) - (*nvfsp->vfc_vfsops->vfs_init)(slotp); + mount_list_unlock(); - return(0); + if (allocated != NULL) { + FREE(allocated, M_TEMP); + } + + return(slotp); } /* - * Name: vfsconf_del + * Name: vfstable_del * * Description: Remove a filesystem from the vfsconf list by name. * If no such filesystem exists, return an error. @@ -378,25 +600,27 @@ vfsconf_add(struct vfsconf *nvfsp) * Notes: Hopefully all filesystems have unique names. */ int -vfsconf_del(char * fs_name) +vfstable_del(struct vfstable * vtbl) { - struct vfsconf **vcpp; - struct vfsconf *vcdelp; + struct vfstable **vcpp; + struct vfstable *vcdelp; + +#if DEBUG + lck_mtx_assert(mnt_list_mtx_lock, LCK_MTX_ASSERT_OWNED); +#endif /* DEBUG */ /* - * Traverse the list looking for fs_name; if found, *vcpp + * Traverse the list looking for vtbl; if found, *vcpp * will contain the address of the pointer to the entry to * be removed. */ for( vcpp = &vfsconf; *vcpp; vcpp = &(*vcpp)->vfc_next) { - if (strcmp( (*vcpp)->vfc_name, fs_name) == 0) + if (*vcpp == vtbl) break; } - if (*vcpp == NULL) { - /* XXX need real error code for entry not found */ - return(-1); - } + if (*vcpp == NULL) + return(ESRCH); /* vtbl not on vfsconf list */ /* Unlink entry */ vcdelp = *vcpp; @@ -409,7 +633,7 @@ vfsconf_del(char * fs_name) */ if (vcdelp >= vfsconf && vcdelp < (vfsconf + maxvfsslots)) { /* Y */ /* Mark as empty for vfscon_add() */ - bzero(vcdelp, sizeof(struct vfsconf)); + bzero(vcdelp, sizeof(struct vfstable)); numused_vfsslots--; } else { /* N */ /* @@ -418,8 +642,27 @@ vfsconf_del(char * fs_name) * vfsconf onto our list, but it may not be persistent * because of the previous (copying) implementation. */ - FREE(vcdelp, M_TEMP); + mount_list_unlock(); + FREE(vcdelp, M_TEMP); + mount_list_lock(); } +#if DEBUG + lck_mtx_assert(mnt_list_mtx_lock, LCK_MTX_ASSERT_OWNED); +#endif /* DEBUG */ + return(0); } + +void +SPECHASH_LOCK(void) +{ + lck_mtx_lock(spechash_mtx_lock); +} + +void +SPECHASH_UNLOCK(void) +{ + lck_mtx_unlock(spechash_mtx_lock); +} +