#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>
/*
*/
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;
}
/*
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;
/*
* 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
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;
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:
*/
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;
}
/*
* 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;
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;
}