]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/vm/dp_backing_file.c
xnu-3789.51.2.tar.gz
[apple/xnu.git] / bsd / vm / dp_backing_file.c
index 359d95fd10612d1b4ca5ac367a411c20ebb88c5d..2684c29dd21fc47377722cc8a6cc01a766e79b00 100644 (file)
 /*
- * 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:
@@ -230,87 +188,42 @@ swapon_bailout:
  */
 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;
 }