/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2010 Apple Inc. All rights reserved.
*
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * 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. 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.
*
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * 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
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
*
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+/*
+ * 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 <mach/boolean.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/lock.h>
-#include <sys/proc.h>
+#include <sys/proc_internal.h>
+#include <sys/kauth.h>
#include <sys/buf.h>
#include <sys/uio.h>
-#include <sys/vnode.h>
+#include <sys/vnode_internal.h>
#include <sys/namei.h>
-#include <sys/ubc.h>
+#include <sys/ubc_internal.h>
+#include <sys/malloc.h>
+#include <sys/user.h>
+
+#include <default_pager/default_pager_types.h>
+
+#include <security/audit/audit.h>
+#include <bsm/audit_kevents.h>
#include <mach/mach_types.h>
-#include <vm/vm_map.h>
-#include <vm/vm_kern.h>
+#include <mach/host_priv.h>
+#include <mach/mach_traps.h>
+#include <mach/boolean.h>
+
+#include <kern/kern_types.h>
+#include <kern/locks.h>
#include <kern/host.h>
-#include <kern/parallel.h>
+#include <kern/task.h>
#include <kern/zalloc.h>
#include <kern/kalloc.h>
+#include <kern/assert.h>
+#include <kern/policy_internal.h>
+
#include <libkern/libkern.h>
-#include <sys/malloc.h>
+#include <vm/vm_pageout.h>
+#include <vm/vm_map.h>
+#include <vm/vm_kern.h>
#include <vm/vnode_pager.h>
+#include <vm/vm_protos.h>
+#if CONFIG_MACF
+#include <security/mac_framework.h>
+#endif
+
+#include <pexpert/pexpert.h>
+
/*
- * temporary support for delayed instantiation
- * of default_pager
+ * Routine: macx_backing_store_recovery
+ * Function:
+ * Syscall interface to set a tasks privilege
+ * level so that it is not subject to
+ * macx_backing_store_suspend
*/
-int default_pager_init_flag = 0;
+int
+macx_backing_store_recovery(
+ __unused struct macx_backing_store_recovery_args *args)
+{
+ assert(FALSE);
-struct bs_map bs_port_table[MAX_BACKING_STORE] = {
- {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
- {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}};
+ return ENOTSUP;
+}
-/* ###################################################### */
+/*
+ * Routine: macx_backing_store_suspend
+ * Function:
+ * Syscall interface to stop new demand for
+ * backing store when backing store is low
+ */
+int
+macx_backing_store_suspend(
+ __unused struct macx_backing_store_suspend_args *args)
+{
+ assert(FALSE);
-#include <kern/assert.h>
+ return ENOTSUP;
+}
+
+
+extern boolean_t compressor_store_stop_compaction;
/*
- * Routine: macx_swapon
+ * Routine: macx_backing_store_compaction
* Function:
- * Syscall interface to add a file to backing store
+ * Turn compaction of swap space on or off. This is
+ * used during shutdown/restart so that the kernel
+ * doesn't waste time compacting swap files that are
+ * about to be deleted anyway. Compaction is always
+ * on by default when the system comes up and is turned
+ * off when a shutdown/restart is requested. It is
+ * re-enabled if the shutdown/restart is aborted for any reason.
+ *
+ * This routine assumes macx_lock has been locked by macx_triggers ->
+ * mach_macx_triggers -> macx_backing_store_compaction
*/
+
int
-macx_swapon(
- char *filename,
- int flags,
- long size,
- long priority)
+macx_backing_store_compaction(int flags)
{
- struct vnode *vp = 0;
- struct nameidata nd, *ndp;
- struct proc *p = current_proc();
- pager_file_t pf;
- register int error;
- kern_return_t kr;
- mach_port_t backing_store;
- memory_object_default_t default_pager;
- int i;
- boolean_t funnel_state;
-
- struct vattr vattr;
-
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- ndp = &nd;
-
- if ((error = suser(p->p_ucred, &p->p_acflag)))
- goto swapon_bailout;
-
- unix_master();
-
- if(default_pager_init_flag == 0) {
- start_def_pager(NULL);
- default_pager_init_flag = 1;
- }
+ int error;
- /*
- * Get a vnode for the paging area.
- */
- NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
- filename, p);
+ if ((error = suser(kauth_cred_get(), 0)))
+ return error;
- if ((error = namei(ndp)))
- goto swapon_bailout;
- vp = ndp->ni_vp;
+ if (flags & SWAP_COMPACT_DISABLE) {
+ compressor_store_stop_compaction = TRUE;
- if (vp->v_type != VREG) {
- error = EINVAL;
- VOP_UNLOCK(vp, 0, p);
- goto swapon_bailout;
- }
- UBCINFOCHECK("macx_swapon", vp);
+ kprintf("compressor_store_stop_compaction = TRUE\n");
- if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) {
- VOP_UNLOCK(vp, 0, p);
- goto swapon_bailout;
- }
+ } else if (flags & SWAP_COMPACT_ENABLE) {
+ compressor_store_stop_compaction = FALSE;
- if (vattr.va_size < (u_quad_t)size) {
- vattr_null(&vattr);
- vattr.va_size = (u_quad_t)size;
- error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
- if (error) {
- VOP_UNLOCK(vp, 0, p);
- goto swapon_bailout;
- }
+ kprintf("compressor_store_stop_compaction = FALSE\n");
}
- /* add new backing store to list */
- i = 0;
- while(bs_port_table[i].vp != 0) {
- if(i == MAX_BACKING_STORE)
- break;
- i++;
- }
- if(i == MAX_BACKING_STORE) {
- error = ENOMEM;
- VOP_UNLOCK(vp, 0, p);
- goto swapon_bailout;
- }
+ return 0;
+}
- /* remember the vnode. This vnode has namei() reference */
- bs_port_table[i].vp = vp;
-
- /*
- * Look to see if we are already paging to this file.
- */
- /* make certain the copy send of kernel call will work */
- default_pager = MEMORY_OBJECT_DEFAULT_NULL;
- kr = host_default_memory_manager(host_priv_self(), &default_pager, 0);
- if(kr != KERN_SUCCESS) {
- error = EAGAIN;
- VOP_UNLOCK(vp, 0, p);
- bs_port_table[i].vp = 0;
- goto swapon_bailout;
- }
+/*
+ * Routine: macx_triggers
+ * Function:
+ * Syscall interface to set the call backs for low and
+ * high water marks.
+ */
+int
+macx_triggers(
+ struct macx_triggers_args *args)
+{
+ int flags = args->flags;
- kr = default_pager_backing_store_create(default_pager,
- -1, /* default priority */
- 0, /* default cluster size */
- &backing_store);
- memory_object_default_deallocate(default_pager);
-
- if(kr != KERN_SUCCESS) {
- error = ENOMEM;
- VOP_UNLOCK(vp, 0, p);
- bs_port_table[i].vp = 0;
- goto swapon_bailout;
- }
+ if (flags & (SWAP_COMPACT_DISABLE | SWAP_COMPACT_ENABLE))
+ return (macx_backing_store_compaction(flags));
- /*
- * NOTE: we are able to supply PAGE_SIZE here instead of
- * an actual record size or block number because:
- * a: we do not support offsets from the beginning of the
- * file (allowing for non page size/record modulo offsets.
- * b: because allow paging will be done modulo page size
- */
-
- VOP_UNLOCK(vp, 0, p);
- kr = default_pager_add_file(backing_store, vp, PAGE_SIZE,
- ((int)vattr.va_size)/PAGE_SIZE);
- if(kr != KERN_SUCCESS) {
- bs_port_table[i].vp = 0;
- if(kr == KERN_INVALID_ARGUMENT)
- error = EINVAL;
- else
- error = ENOMEM;
- goto swapon_bailout;
- }
- bs_port_table[i].bs = (void *)backing_store;
- error = 0;
- if (!ubc_hold(vp))
- panic("macx_swapon: hold");
-
- /* Mark this vnode as being used for swapfile */
- SET(vp->v_flag, VSWAP);
-
- /*
- * take an extra reference on the vnode to keep
- * vnreclaim() away from this vnode.
- */
- VREF(vp);
-
- /* Hold on to the namei reference to the paging file vnode */
- vp = 0;
-
-swapon_bailout:
- if (vp) {
- vrele(vp);
- }
- unix_release();
- (void) thread_funnel_set(kernel_flock, FALSE);
- return(error);
+ assert(FALSE);
+
+ return ENOTSUP;
+}
+
+
+int
+macx_swapon(
+ __unused struct macx_swapon_args *args)
+{
+ assert(FALSE);
+
+ return ENOTSUP;
}
+
/*
* Routine: macx_swapoff
* Function:
*/
int
macx_swapoff(
- char *filename,
- int flags)
+ __unused struct macx_swapoff_args *args)
{
- kern_return_t kr;
- mach_port_t backing_store;
-
- struct vnode *vp = 0;
- struct nameidata nd, *ndp;
- struct proc *p = current_proc();
- int i;
- int error;
- boolean_t funnel_state;
-
- funnel_state = thread_funnel_set(kernel_flock, TRUE);
- backing_store = NULL;
- ndp = &nd;
-
- if ((error = suser(p->p_ucred, &p->p_acflag)))
- goto swapoff_bailout;
-
- unix_master();
-
- /*
- * Get the vnode for the paging area.
- */
- NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
- filename, p);
-
- if ((error = namei(ndp)))
- goto swapoff_bailout;
- vp = ndp->ni_vp;
-
- if (vp->v_type != VREG) {
- error = EINVAL;
- VOP_UNLOCK(vp, 0, p);
- goto swapoff_bailout;
- }
+ assert(FALSE);
- for(i = 0; i < MAX_BACKING_STORE; i++) {
- if(bs_port_table[i].vp == vp) {
- backing_store;
- break;
- }
- }
- if (i == MAX_BACKING_STORE) {
- error = EINVAL;
- VOP_UNLOCK(vp, 0, p);
- goto swapoff_bailout;
- }
- backing_store = (mach_port_t)bs_port_table[i].bs;
-
- VOP_UNLOCK(vp, 0, p);
- kr = default_pager_backing_store_delete(backing_store);
- switch (kr) {
- case KERN_SUCCESS:
- error = 0;
- bs_port_table[i].vp = 0;
- ubc_rele(vp);
- /* This vnode is no longer used for swapfile */
- CLR(vp->v_flag, VSWAP);
-
- /* get rid of macx_swapon() namei() reference */
- vrele(vp);
-
- /* get rid of macx_swapon() "extra" reference */
- vrele(vp);
- break;
- case KERN_FAILURE:
- error = EAGAIN;
- break;
- default:
- error = EAGAIN;
- break;
- }
+ return ENOTSUP;
+}
-swapoff_bailout:
- /* get rid of macx_swapoff() namei() reference */
- if (vp)
- vrele(vp);
+/*
+ * Routine: macx_swapinfo
+ * Function:
+ * Syscall interface to get general swap statistics
+ */
+extern uint64_t vm_swap_get_total_space(void);
+extern uint64_t vm_swap_get_free_space(void);
+extern boolean_t vm_swap_up;
- unix_release();
- (void) thread_funnel_set(kernel_flock, FALSE);
- return(error);
+int
+macx_swapinfo(
+ memory_object_size_t *total_p,
+ memory_object_size_t *avail_p,
+ vm_size_t *pagesize_p,
+ boolean_t *encrypted_p)
+{
+ if (VM_CONFIG_SWAP_IS_PRESENT) {
+
+ *total_p = vm_swap_get_total_space();
+ *avail_p = vm_swap_get_free_space();
+ *pagesize_p = (vm_size_t)PAGE_SIZE_64;
+ *encrypted_p = TRUE;
+
+ } else {
+
+ *total_p = 0;
+ *avail_p = 0;
+ *pagesize_p = 0;
+ *encrypted_p = FALSE;
+ }
+ return 0;
}