]> 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 edf716daa8f48064a07c9bfa619ac847869468a7..2684c29dd21fc47377722cc8a6cc01a766e79b00 100644 (file)
@@ -1,31 +1,35 @@
 /*
- * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2010 Apple Inc. All rights reserved.
  *
- * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
+ * @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.  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 
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
- * Please see the License for the specific language governing rights and 
+ * 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.
+ * 
+ * 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, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
  * limitations under the License.
- *
- * @APPLE_LICENSE_OSREFERENCE_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 <sys/param.h>
 #include <sys/namei.h>
 #include <sys/ubc_internal.h>
 #include <sys/malloc.h>
+#include <sys/user.h>
 
 #include <default_pager/default_pager_types.h>
-#include <default_pager/default_pager_object.h>
 
-#include <bsm/audit_kernel.h>
+#include <security/audit/audit.h>
 #include <bsm/audit_kevents.h>
 
 #include <mach/mach_types.h>
 #include <mach/boolean.h>
 
 #include <kern/kern_types.h>
+#include <kern/locks.h>
 #include <kern/host.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 <vm/vm_kern.h>
 #include <vm/vnode_pager.h>
 #include <vm/vm_protos.h>
+#if CONFIG_MACF
+#include <security/mac_framework.h>
+#endif
 
-extern thread_t current_act(void);
-
-/*
- * temporary support for delayed instantiation
- * of default_pager
- */
-int default_pager_init_flag = 0;
-
-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}};
-
-/* ###################################################### */
+#include <pexpert/pexpert.h>
 
 
 /*
@@ -98,29 +87,11 @@ struct bs_map               bs_port_table[MAX_BACKING_STORE] = {
  */
 int
 macx_backing_store_recovery(
-       struct macx_backing_store_recovery_args *args)
+       __unused struct macx_backing_store_recovery_args *args)
 {
-       int             pid = args->pid;
-       int             error;
-       struct proc     *p =  current_proc();
-       boolean_t       funnel_state;
-
-       funnel_state = thread_funnel_set(kernel_flock, TRUE);
-       if ((error = suser(kauth_cred_get(), 0)))
-               goto backing_store_recovery_return;
-
-       /* for now restrict backing_store_recovery */
-       /* usage to only present task */
-       if(pid != proc_selfpid()) {
-               error = EINVAL;
-               goto backing_store_recovery_return;
-       }
-
-       task_backing_store_privileged(p->task);
+       assert(FALSE);
 
-backing_store_recovery_return:
-       (void) thread_funnel_set(kernel_flock, FALSE);
-       return(error);
+       return ENOTSUP;
 }
 
 /*
@@ -132,168 +103,84 @@ backing_store_recovery_return:
 
 int
 macx_backing_store_suspend(
-       struct macx_backing_store_suspend_args *args)
+       __unused struct macx_backing_store_suspend_args *args)
 {
-       boolean_t       suspend = args->suspend;
-       int             error;
-       boolean_t       funnel_state;
+       assert(FALSE);
 
-       funnel_state = thread_funnel_set(kernel_flock, TRUE);
-       if ((error = suser(kauth_cred_get(), 0)))
-               goto backing_store_suspend_return;
+       return ENOTSUP;
+}
 
-       vm_backing_store_disable(suspend);
 
-backing_store_suspend_return:
-       (void) thread_funnel_set(kernel_flock, FALSE);
-       return(error);
-}
+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(
-       struct macx_swapon_args *args)
+macx_backing_store_compaction(int flags)
 {
-       int                     size = args->size;
-       vnode_t                 vp = (vnode_t)NULL; 
-       struct nameidata        nd, *ndp;
-       struct proc             *p =  current_proc();
-       register int            error;
-       kern_return_t           kr;
-       mach_port_t             backing_store;
-       memory_object_default_t default_pager;
-       int                     i;
-       boolean_t               funnel_state;
-       off_t                   file_size;
-       struct vfs_context      context;
-
-       context.vc_proc = p;
-       context.vc_ucred = kauth_cred_get();
-
-       AUDIT_MACH_SYSCALL_ENTER(AUE_SWAPON);
-       AUDIT_ARG(value, args->priority);
-
-       funnel_state = thread_funnel_set(kernel_flock, TRUE);
-       ndp = &nd;
+       int error;
 
        if ((error = suser(kauth_cred_get(), 0)))
-               goto swapon_bailout;
+               return error;
 
-       if(default_pager_init_flag == 0) {
-               start_def_pager(NULL);
-               default_pager_init_flag = 1;
-       }
+       if (flags & SWAP_COMPACT_DISABLE) {
+               compressor_store_stop_compaction = TRUE;
 
-       /*
-        * Get a vnode for the paging area.
-        */
-       NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNPATH1,
-              ((IS_64BIT_PROCESS(p)) ? UIO_USERSPACE64 : UIO_USERSPACE32),
-              CAST_USER_ADDR_T(args->filename), &context);
-
-       if ((error = namei(ndp)))
-               goto swapon_bailout;
-       nameidone(ndp);
-       vp = ndp->ni_vp;
-
-       if (vp->v_type != VREG) {
-               error = EINVAL;
-               goto swapon_bailout;
-       }
-       UBCINFOCHECK("macx_swapon", vp);
-
-       /* get file size */
-       if ((error = vnode_size(vp, &file_size, &context)) != 0)
-               goto swapon_bailout;
-
-       /* resize to desired size if it's too small */
-       if ((file_size < (off_t)size) && ((error = vnode_setsize(vp, (off_t)size, 0, &context)) != 0))
-               goto swapon_bailout;
-
-       /* 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;
-               goto swapon_bailout;
-       }
+               kprintf("compressor_store_stop_compaction = TRUE\n");
+
+       } else if (flags & SWAP_COMPACT_ENABLE) {
+               compressor_store_stop_compaction = FALSE;
 
-       /* 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;
-          bs_port_table[i].vp = 0;
-          goto swapon_bailout;
+               kprintf("compressor_store_stop_compaction = FALSE\n");
        }
 
-       kr = default_pager_backing_store_create(default_pager, 
-                                       -1, /* default priority */
-                                       0, /* default cluster size */
-                                       &backing_store);
-       memory_object_default_deallocate(default_pager);
+       return 0;
+}
 
-       if(kr != KERN_SUCCESS) {
-          error = ENOMEM;
-          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;
 
-       /*
-        * 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
-        */
-
-       kr = default_pager_add_file(backing_store, (vnode_ptr_t) vp,
-                               PAGE_SIZE, (int)(file_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 (flags & (SWAP_COMPACT_DISABLE | SWAP_COMPACT_ENABLE))
+               return (macx_backing_store_compaction(flags));
 
-       /* Mark this vnode as being used for swapfile */
-       SET(vp->v_flag, VSWAP);
+       assert(FALSE);
 
-       ubc_setthreadcred(vp, p, current_thread());
+       return ENOTSUP;
+}
 
-       /*
-        * take a long term reference on the vnode to keep
-        * vnreclaim() away from this vnode.
-        */
-       vnode_ref(vp);
 
-swapon_bailout:
-       if (vp) {
-               vnode_put(vp);
-       }
-       (void) thread_funnel_set(kernel_flock, FALSE);
-       AUDIT_MACH_SYSCALL_EXIT(error);
-       return(error);
+int
+macx_swapon(
+       __unused struct macx_swapon_args *args)
+{
+       assert(FALSE);
+
+       return ENOTSUP;
 }
 
+
 /*
  *     Routine:        macx_swapoff
  *     Function:
@@ -301,88 +188,11 @@ swapon_bailout:
  */
 int
 macx_swapoff(
-       struct macx_swapoff_args *args)
+       __unused struct macx_swapoff_args *args)
 {
-       __unused int    flags = args->flags;
-       kern_return_t   kr;
-       mach_port_t     backing_store;
+       assert(FALSE);
 
-       struct vnode            *vp = 0; 
-       struct nameidata        nd, *ndp;
-       struct proc             *p =  current_proc();
-       int                     i;
-       int                     error;
-       boolean_t               funnel_state;
-       struct vfs_context context;
-
-       context.vc_proc = p;
-       context.vc_ucred = kauth_cred_get();
-
-       AUDIT_MACH_SYSCALL_ENTER(AUE_SWAPOFF);
-
-       funnel_state = thread_funnel_set(kernel_flock, TRUE);
-       backing_store = NULL;
-       ndp = &nd;
-
-       if ((error = suser(kauth_cred_get(), 0)))
-               goto swapoff_bailout;
-
-       /*
-        * Get the vnode for the paging area.
-        */
-       NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNPATH1,
-              ((IS_64BIT_PROCESS(p)) ? UIO_USERSPACE64 : UIO_USERSPACE32),
-              CAST_USER_ADDR_T(args->filename), &context);
-
-       if ((error = namei(ndp)))
-               goto swapoff_bailout;
-       nameidone(ndp);
-       vp = ndp->ni_vp;
-
-       if (vp->v_type != VREG) {
-               error = EINVAL;
-               goto swapoff_bailout;
-       }
-
-       for(i = 0; i < MAX_BACKING_STORE; i++) {
-               if(bs_port_table[i].vp == vp) {
-                       break;
-               }
-       }
-       if (i == MAX_BACKING_STORE) {
-               error = EINVAL;
-               goto swapoff_bailout;
-       }
-       backing_store = (mach_port_t)bs_port_table[i].bs;
-
-       kr = default_pager_backing_store_delete(backing_store);
-       switch (kr) {
-               case KERN_SUCCESS:
-                       error = 0;
-                       bs_port_table[i].vp = 0;
-                       /* This vnode is no longer used for swapfile */
-                       CLR(vp->v_flag, VSWAP);
-
-                       /* get rid of macx_swapon() "long term" reference */
-                       vnode_rele(vp);
-
-                       break;
-               case KERN_FAILURE:
-                       error = EAGAIN;
-                       break;
-               default:
-                       error = EAGAIN;
-                       break;
-       }
-
-swapoff_bailout:
-       /* get rid of macx_swapoff() namei() reference */
-       if (vp)
-               vnode_put(vp);
-
-       (void) thread_funnel_set(kernel_flock, FALSE);
-       AUDIT_MACH_SYSCALL_EXIT(error);
-       return(error);
+       return ENOTSUP;
 }
 
 /*
@@ -390,6 +200,10 @@ swapoff_bailout:
  *     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;
+
 int
 macx_swapinfo(
        memory_object_size_t    *total_p,
@@ -397,59 +211,19 @@ macx_swapinfo(
        vm_size_t               *pagesize_p,
        boolean_t               *encrypted_p)
 {
-       int                     error;
-       memory_object_default_t default_pager;
-       default_pager_info_64_t dpi64;
-       kern_return_t           kr;
-
-       error = 0;
-
-       /*
-        * Get a handle on the default pager.
-        */
-       default_pager = MEMORY_OBJECT_DEFAULT_NULL;
-       kr = host_default_memory_manager(host_priv_self(), &default_pager, 0);
-       if (kr != KERN_SUCCESS) {
-               error = EAGAIN; /* XXX why EAGAIN ? */
-               goto done;
-       }
-       if (default_pager == MEMORY_OBJECT_DEFAULT_NULL) {
-               /*
-                * The default pager has not initialized yet,
-                * so it can't be using any swap space at all.
-                */
-               *total_p = 0;
-               *avail_p = 0;
-               *pagesize_p = 0;
-               *encrypted_p = FALSE;
-               goto done;
-       }
-       
-       /*
-        * Get swap usage data from default pager.
-        */
-       kr = default_pager_info_64(default_pager, &dpi64);
-       if (kr != KERN_SUCCESS) {
-               error = ENOTSUP;
-               goto done;
-       }
+       if (VM_CONFIG_SWAP_IS_PRESENT) {
 
-       /*
-        * Provide default pager info to caller.
-        */
-       *total_p = dpi64.dpi_total_space;
-       *avail_p = dpi64.dpi_free_space;
-       *pagesize_p = dpi64.dpi_page_size;
-       if (dpi64.dpi_flags & DPI_ENCRYPTED) {
+               *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;
        }
-
-done:
-       if (default_pager != MEMORY_OBJECT_DEFAULT_NULL) {
-               /* release our handle on default pager */
-               memory_object_default_deallocate(default_pager);
-       }
-       return error;
+       return 0;
 }