]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/vm/dp_backing_file.c
xnu-3789.70.16.tar.gz
[apple/xnu.git] / bsd / vm / dp_backing_file.c
index cc52be8fb750fd8cf2c12a8566f0f3c895e0b79f..5548f11fda90c66d72d122129ce142350000531e 100644 (file)
 #include <sys/ubc_internal.h>
 #include <sys/malloc.h>
 #include <sys/user.h>
-#if CONFIG_PROTECT
-#include <sys/cprotect.h>
-#endif
 
 #include <default_pager/default_pager_types.h>
-#include <default_pager/default_pager_object.h>
 
 #include <security/audit/audit.h>
 #include <bsm/audit_kevents.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 <security/mac_framework.h>
 #endif
 
-void kprintf(const char *fmt, ...);
-
-/*
- * 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>
 
 
 /*
@@ -109,29 +86,9 @@ 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);
-
-backing_store_recovery_return:
-       (void) thread_funnel_set(kernel_flock, FALSE);
-       return(error);
+       return ENOTSUP;
 }
 
 /*
@@ -143,24 +100,12 @@ 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;
-
-       funnel_state = thread_funnel_set(kernel_flock, TRUE);
-       if ((error = suser(kauth_cred_get(), 0)))
-               goto backing_store_suspend_return;
-
-       vm_backing_store_disable(suspend);
-
-backing_store_suspend_return:
-       (void) thread_funnel_set(kernel_flock, FALSE);
-       return(error);
+       return ENOTSUP;
 }
 
-extern boolean_t backing_store_stop_compaction;
+
 extern boolean_t compressor_store_stop_compaction;
 
 /*
@@ -173,6 +118,9 @@ extern boolean_t compressor_store_stop_compaction;
  *             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
@@ -184,16 +132,14 @@ macx_backing_store_compaction(int flags)
                return error;
 
        if (flags & SWAP_COMPACT_DISABLE) {
-               backing_store_stop_compaction = TRUE;
                compressor_store_stop_compaction = TRUE;
 
-               kprintf("backing_store_stop_compaction = TRUE\n");
+               kprintf("compressor_store_stop_compaction = TRUE\n");
 
        } else if (flags & SWAP_COMPACT_ENABLE) {
-               backing_store_stop_compaction = FALSE;
                compressor_store_stop_compaction = FALSE;
 
-               kprintf("backing_store_stop_compaction = FALSE\n");
+               kprintf("compressor_store_stop_compaction = FALSE\n");
        }
 
        return 0;
@@ -209,245 +155,23 @@ int
 macx_triggers(
        struct macx_triggers_args *args)
 {
-       int     error;
+       int     flags = args->flags;
 
-       error = suser(kauth_cred_get(), 0);
-       if (error)
-               return error;
+       if (flags & (SWAP_COMPACT_DISABLE | SWAP_COMPACT_ENABLE))
+               return (macx_backing_store_compaction(flags));
 
-       return mach_macx_triggers(args);
+       return ENOTSUP;
 }
 
 
-extern boolean_t dp_isssd;
-extern void vm_swap_init(void);
-extern int vm_compressor_mode;
-
-/*
- * In the compressed pager world, the swapfiles are created by the kernel.
- * Well, all except the first one. That swapfile is absorbed by the kernel at
- * the end of the macx_swapon function (if swap is enabled). That's why
- * we allow the first invocation of macx_swapon to succeed.
- *
- * If the compressor pool is running low, the kernel messages the dynamic pager
- * on the port it has registered with the kernel. That port can transport 1 of 2
- * pieces of information to dynamic pager: create a swapfile or delete a swapfile.
- *
- * We choose to transmit the former. So, that message tells dynamic pager
- * to create a swapfile and activate it by calling macx_swapon. 
- *
- * We deny this new macx_swapon request. That leads dynamic pager to interpret the
- * failure as a serious error and notify all it's clients that swap is running low.
- * That's how we get the loginwindow "Resume / Force Quit Applications" dialog to appear.
- *
- * NOTE: 
- * If the kernel has already created multiple swapfiles by the time the compressor
- * pool is running low (and it has to play this trick), dynamic pager won't be able to
- * create a file in user-space and, that too will lead to a similar notification blast
- * to all of it's clients. So, that behaves as desired too.
- */
-boolean_t      macx_swapon_allowed = TRUE;
-
-/*
- *     Routine:        macx_swapon
- *     Function:
- *             Syscall interface to add a file to backing store
- */
 int
 macx_swapon(
-       struct macx_swapon_args *args)
+       __unused struct macx_swapon_args *args)
 {
-       int                     size = args->size;
-       vnode_t                 vp = (vnode_t)NULL; 
-       struct nameidata        nd, *ndp;
-       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;
-       vfs_context_t           ctx = vfs_context_current();
-       struct proc             *p =  current_proc();
-       int                     dp_cluster_size;
-
-       if (COMPRESSED_PAGER_IS_ACTIVE) {
-               if (macx_swapon_allowed == FALSE) {
-                       return EINVAL;
-               } else {
-                       if ((vm_compressor_mode == VM_PAGER_COMPRESSOR_WITH_SWAP) ||
-                           (vm_compressor_mode == VM_PAGER_FREEZER_COMPRESSOR_WITH_SWAP)) {
-                               vm_swap_init();
-                       }
-
-                       macx_swapon_allowed = FALSE;
-                       return 0;
-               }
-       }
-
-       AUDIT_MACH_SYSCALL_ENTER(AUE_SWAPON);
-       AUDIT_ARG(value32, args->priority);
-
-       funnel_state = thread_funnel_set(kernel_flock, TRUE);
-       ndp = &nd;
-
-       if ((error = suser(kauth_cred_get(), 0)))
-               goto swapon_bailout;
-
-       /*
-        * Get a vnode for the paging area.
-        */
-       NDINIT(ndp, LOOKUP, OP_LOOKUP, FOLLOW | LOCKLEAF | AUDITVNPATH1,
-              ((IS_64BIT_PROCESS(p)) ? UIO_USERSPACE64 : UIO_USERSPACE32),
-              (user_addr_t) args->filename, ctx);
-
-       if ((error = namei(ndp)))
-               goto swapon_bailout;
-       nameidone(ndp);
-       vp = ndp->ni_vp;
-
-       if (vp->v_type != VREG) {
-               error = EINVAL;
-               goto swapon_bailout;
-       }
-
-       /* get file size */
-       if ((error = vnode_size(vp, &file_size, ctx)) != 0)
-               goto swapon_bailout;
-#if CONFIG_MACF
-       vnode_lock(vp);
-       error = mac_system_check_swapon(vfs_context_ucred(ctx), vp);
-       vnode_unlock(vp);
-       if (error)
-               goto swapon_bailout;
-#endif
-
-       /* resize to desired size if it's too small */
-       if ((file_size < (off_t)size) && ((error = vnode_setsize(vp, (off_t)size, 0, ctx)) != 0))
-               goto swapon_bailout;
-
-#if CONFIG_PROTECT
-       {
-               /* initialize content protection keys manually */
-               if ((error = cp_handle_vnop(vp, CP_WRITE_ACCESS, 0)) != 0) {
-                       goto swapon_bailout;
-               }
-       }
-#endif
-
-
-       if (default_pager_init_flag == 0) {
-               start_def_pager(NULL);
-               default_pager_init_flag = 1;
-       }
-
-       /* 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;
-       }
-
-       /* 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;
-       }
-
-       if ((dp_isssd = vnode_pager_isSSD(vp)) == TRUE) {
-               /*
-                * keep the cluster size small since the
-                * seek cost is effectively 0 which means
-                * we don't care much about fragmentation
-                */
-               dp_cluster_size = 2 * PAGE_SIZE;
-       } else {
-               /*
-                * use the default cluster size
-                */
-               dp_cluster_size = 0;
-       }
-       kr = default_pager_backing_store_create(default_pager, 
-                                       -1, /* default priority */
-                                       dp_cluster_size,
-                                       &backing_store);
-       memory_object_default_deallocate(default_pager);
-
-       if(kr != KERN_SUCCESS) {
-          error = ENOMEM;
-          bs_port_table[i].vp = 0;
-          goto swapon_bailout;
-       }
-
-       /* Mark this vnode as being used for swapfile */
-       vnode_lock_spin(vp);
-       SET(vp->v_flag, VSWAP);
-       vnode_unlock(vp);
-
-       /*
-        * 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;
-
-          /* This vnode is not to be used for swapfile */
-          vnode_lock_spin(vp);
-          CLR(vp->v_flag, VSWAP);
-          vnode_unlock(vp);
-
-          goto swapon_bailout;
-       }
-       bs_port_table[i].bs = (void *)backing_store;
-       error = 0;
-
-       ubc_setthreadcred(vp, p, current_thread());
-
-       /*
-        * 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);
-
-       if (error)
-               printf("macx_swapon FAILED - %d\n", error);
-       else
-               printf("macx_swapon SUCCESS\n");
-
-       return(error);
+       return ENOTSUP;
 }
 
+
 /*
  *     Routine:        macx_swapoff
  *     Function:
@@ -455,111 +179,9 @@ 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;
-
-       struct vnode            *vp = 0; 
-       struct nameidata        nd, *ndp;
-       struct proc             *p =  current_proc();
-       int                     i;
-       int                     error;
-       boolean_t               funnel_state;
-       vfs_context_t ctx = vfs_context_current();
-       int                     orig_iopol_disk;
-
-       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, OP_LOOKUP, FOLLOW | LOCKLEAF | AUDITVNPATH1,
-              ((IS_64BIT_PROCESS(p)) ? UIO_USERSPACE64 : UIO_USERSPACE32),
-              (user_addr_t) args->filename, ctx);
-
-       if ((error = namei(ndp)))
-               goto swapoff_bailout;
-       nameidone(ndp);
-       vp = ndp->ni_vp;
-
-       if (vp->v_type != VREG) {
-               error = EINVAL;
-               goto swapoff_bailout;
-       }
-#if CONFIG_MACF
-       vnode_lock(vp);
-       error = mac_system_check_swapoff(vfs_context_ucred(ctx), vp);
-       vnode_unlock(vp);
-       if (error)
-               goto swapoff_bailout;
-#endif
-
-       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;
-
-       orig_iopol_disk = proc_get_task_policy(current_task(), current_thread(),
-                                              TASK_POLICY_INTERNAL, TASK_POLICY_IOPOL);
-
-       proc_set_task_policy(current_task(), current_thread(), TASK_POLICY_INTERNAL,
-                            TASK_POLICY_IOPOL, IOPOL_THROTTLE);
-
-       kr = default_pager_backing_store_delete(backing_store);
-
-       proc_set_task_policy(current_task(), current_thread(), TASK_POLICY_INTERNAL,
-                            TASK_POLICY_IOPOL, orig_iopol_disk);
-
-       switch (kr) {
-               case KERN_SUCCESS:
-                       error = 0;
-                       bs_port_table[i].vp = 0;
-                       /* This vnode is no longer used for swapfile */
-                       vnode_lock_spin(vp);
-                       CLR(vp->v_flag, VSWAP);
-                       vnode_unlock(vp);
-
-                       /* 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);
-
-       if (error)
-               printf("macx_swapoff FAILED - %d\n", error);
-       else
-               printf("macx_swapoff SUCCESS\n");
-
-       return(error);
+       return ENOTSUP;
 }
 
 /*
@@ -568,7 +190,6 @@ swapoff_bailout:
  *             Syscall interface to get general swap statistics
  */
 extern uint64_t vm_swap_get_total_space(void);
-extern uint64_t vm_swap_get_used_space(void);
 extern uint64_t vm_swap_get_free_space(void);
 extern boolean_t vm_swap_up;
 
@@ -579,77 +200,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;
+       if (VM_CONFIG_SWAP_IS_PRESENT) {
 
-       error = 0;
-       if (COMPRESSED_PAGER_IS_ACTIVE) {
+               *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;
 
-               if (vm_swap_up == TRUE) {
-
-                       *total_p = vm_swap_get_total_space();
-                       *avail_p = vm_swap_get_free_space();
-                       *pagesize_p = PAGE_SIZE_64;
-                       *encrypted_p = TRUE;
-
-               } else {
-
-                       *total_p = 0;
-                       *avail_p = 0;
-                       *pagesize_p = 0;
-                       *encrypted_p = FALSE;
-               }
        } else {
-
-               /*
-                * 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;
-               }
-
-               /*
-                * 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) {
-                       *encrypted_p = TRUE;
-               } else {
-                       *encrypted_p = FALSE;
-               }
-
-done:
-               if (default_pager != MEMORY_OBJECT_DEFAULT_NULL) {
-                       /* release our handle on default pager */
-                       memory_object_default_deallocate(default_pager);
-               }
+               *total_p = 0;
+               *avail_p = 0;
+               *pagesize_p = 0;
+               *encrypted_p = FALSE;
        }
-       return error;
+       return 0;
 }