]>
Commit | Line | Data |
---|---|---|
1c79356b | 1 | /* |
6d2010ae | 2 | * Copyright (c) 2000-2010 Apple Inc. All rights reserved. |
5d5c5d0d | 3 | * |
2d21ac55 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
1c79356b | 5 | * |
2d21ac55 A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
8f6c56a5 | 14 | * |
2d21ac55 A |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
8f6c56a5 A |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
2d21ac55 A |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
8f6c56a5 | 25 | * |
2d21ac55 A |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
27 | */ | |
28 | /* | |
29 | * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce | |
30 | * support for mandatory and extensible security protections. This notice | |
31 | * is included in support of clause 2.2 (b) of the Apple Public License, | |
32 | * Version 2.0. | |
1c79356b A |
33 | */ |
34 | ||
1c79356b A |
35 | #include <sys/param.h> |
36 | #include <sys/systm.h> | |
37 | #include <sys/lock.h> | |
91447636 A |
38 | #include <sys/proc_internal.h> |
39 | #include <sys/kauth.h> | |
1c79356b A |
40 | #include <sys/buf.h> |
41 | #include <sys/uio.h> | |
91447636 | 42 | #include <sys/vnode_internal.h> |
1c79356b | 43 | #include <sys/namei.h> |
91447636 A |
44 | #include <sys/ubc_internal.h> |
45 | #include <sys/malloc.h> | |
6d2010ae A |
46 | #include <sys/user.h> |
47 | #if CONFIG_PROTECT | |
48 | #include <sys/cprotect.h> | |
49 | #endif | |
91447636 A |
50 | |
51 | #include <default_pager/default_pager_types.h> | |
52 | #include <default_pager/default_pager_object.h> | |
1c79356b | 53 | |
b0d623f7 | 54 | #include <security/audit/audit.h> |
e5568f75 A |
55 | #include <bsm/audit_kevents.h> |
56 | ||
1c79356b | 57 | #include <mach/mach_types.h> |
91447636 A |
58 | #include <mach/host_priv.h> |
59 | #include <mach/mach_traps.h> | |
60 | #include <mach/boolean.h> | |
61 | ||
62 | #include <kern/kern_types.h> | |
1c79356b | 63 | #include <kern/host.h> |
91447636 | 64 | #include <kern/task.h> |
1c79356b A |
65 | #include <kern/zalloc.h> |
66 | #include <kern/kalloc.h> | |
91447636 A |
67 | #include <kern/assert.h> |
68 | ||
1c79356b | 69 | #include <libkern/libkern.h> |
1c79356b | 70 | |
91447636 A |
71 | #include <vm/vm_pageout.h> |
72 | #include <vm/vm_map.h> | |
73 | #include <vm/vm_kern.h> | |
1c79356b | 74 | #include <vm/vnode_pager.h> |
91447636 | 75 | #include <vm/vm_protos.h> |
2d21ac55 A |
76 | #if CONFIG_MACF |
77 | #include <security/mac_framework.h> | |
78 | #endif | |
1c79356b A |
79 | |
80 | /* | |
81 | * temporary support for delayed instantiation | |
82 | * of default_pager | |
83 | */ | |
84 | int default_pager_init_flag = 0; | |
85 | ||
86 | struct bs_map bs_port_table[MAX_BACKING_STORE] = { | |
87 | {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, | |
88 | {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, | |
89 | {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, | |
90 | {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, | |
91 | {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, | |
92 | {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, | |
93 | {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, | |
94 | {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, | |
95 | {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, | |
96 | {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}}; | |
97 | ||
98 | /* ###################################################### */ | |
99 | ||
100 | ||
55e303ae A |
101 | /* |
102 | * Routine: macx_backing_store_recovery | |
103 | * Function: | |
104 | * Syscall interface to set a tasks privilege | |
105 | * level so that it is not subject to | |
106 | * macx_backing_store_suspend | |
107 | */ | |
108 | int | |
109 | macx_backing_store_recovery( | |
91447636 | 110 | struct macx_backing_store_recovery_args *args) |
55e303ae | 111 | { |
91447636 | 112 | int pid = args->pid; |
55e303ae A |
113 | int error; |
114 | struct proc *p = current_proc(); | |
115 | boolean_t funnel_state; | |
116 | ||
117 | funnel_state = thread_funnel_set(kernel_flock, TRUE); | |
91447636 | 118 | if ((error = suser(kauth_cred_get(), 0))) |
55e303ae A |
119 | goto backing_store_recovery_return; |
120 | ||
121 | /* for now restrict backing_store_recovery */ | |
122 | /* usage to only present task */ | |
91447636 | 123 | if(pid != proc_selfpid()) { |
55e303ae A |
124 | error = EINVAL; |
125 | goto backing_store_recovery_return; | |
126 | } | |
127 | ||
128 | task_backing_store_privileged(p->task); | |
129 | ||
130 | backing_store_recovery_return: | |
131 | (void) thread_funnel_set(kernel_flock, FALSE); | |
132 | return(error); | |
133 | } | |
134 | ||
135 | /* | |
136 | * Routine: macx_backing_store_suspend | |
137 | * Function: | |
138 | * Syscall interface to stop new demand for | |
139 | * backing store when backing store is low | |
140 | */ | |
141 | ||
142 | int | |
143 | macx_backing_store_suspend( | |
91447636 | 144 | struct macx_backing_store_suspend_args *args) |
55e303ae | 145 | { |
91447636 | 146 | boolean_t suspend = args->suspend; |
55e303ae | 147 | int error; |
55e303ae A |
148 | boolean_t funnel_state; |
149 | ||
150 | funnel_state = thread_funnel_set(kernel_flock, TRUE); | |
91447636 | 151 | if ((error = suser(kauth_cred_get(), 0))) |
55e303ae A |
152 | goto backing_store_suspend_return; |
153 | ||
154 | vm_backing_store_disable(suspend); | |
155 | ||
156 | backing_store_suspend_return: | |
157 | (void) thread_funnel_set(kernel_flock, FALSE); | |
158 | return(error); | |
159 | } | |
160 | ||
b0d623f7 A |
161 | extern boolean_t backing_store_stop_compaction; |
162 | ||
163 | /* | |
164 | * Routine: macx_backing_store_compaction | |
165 | * Function: | |
166 | * Turn compaction of swap space on or off. This is | |
167 | * used during shutdown/restart so that the kernel | |
168 | * doesn't waste time compacting swap files that are | |
169 | * about to be deleted anyway. Compaction is always | |
170 | * on by default when the system comes up and is turned | |
171 | * off when a shutdown/restart is requested. It is | |
172 | * re-enabled if the shutdown/restart is aborted for any reason. | |
173 | */ | |
174 | ||
175 | int | |
176 | macx_backing_store_compaction(int flags) | |
177 | { | |
178 | int error; | |
179 | ||
180 | if ((error = suser(kauth_cred_get(), 0))) | |
181 | return error; | |
182 | ||
183 | if (flags & SWAP_COMPACT_DISABLE) { | |
184 | backing_store_stop_compaction = TRUE; | |
185 | ||
186 | } else if (flags & SWAP_COMPACT_ENABLE) { | |
187 | backing_store_stop_compaction = FALSE; | |
188 | } | |
189 | ||
190 | return 0; | |
191 | } | |
192 | ||
193 | /* | |
194 | * Routine: macx_triggers | |
195 | * Function: | |
196 | * Syscall interface to set the call backs for low and | |
197 | * high water marks. | |
198 | */ | |
199 | int | |
200 | macx_triggers( | |
201 | struct macx_triggers_args *args) | |
202 | { | |
203 | int error; | |
204 | ||
205 | error = suser(kauth_cred_get(), 0); | |
206 | if (error) | |
207 | return error; | |
208 | ||
209 | return mach_macx_triggers(args); | |
210 | } | |
211 | ||
0b4c1975 A |
212 | |
213 | extern boolean_t dp_isssd; | |
214 | ||
1c79356b A |
215 | /* |
216 | * Routine: macx_swapon | |
217 | * Function: | |
218 | * Syscall interface to add a file to backing store | |
219 | */ | |
220 | int | |
221 | macx_swapon( | |
91447636 | 222 | struct macx_swapon_args *args) |
1c79356b | 223 | { |
91447636 A |
224 | int size = args->size; |
225 | vnode_t vp = (vnode_t)NULL; | |
1c79356b | 226 | struct nameidata nd, *ndp; |
1c79356b A |
227 | register int error; |
228 | kern_return_t kr; | |
229 | mach_port_t backing_store; | |
0b4e3aa0 | 230 | memory_object_default_t default_pager; |
1c79356b A |
231 | int i; |
232 | boolean_t funnel_state; | |
91447636 | 233 | off_t file_size; |
2d21ac55 A |
234 | vfs_context_t ctx = vfs_context_current(); |
235 | struct proc *p = current_proc(); | |
0b4c1975 A |
236 | int dp_cluster_size; |
237 | ||
1c79356b | 238 | |
e5568f75 | 239 | AUDIT_MACH_SYSCALL_ENTER(AUE_SWAPON); |
b0d623f7 | 240 | AUDIT_ARG(value32, args->priority); |
e5568f75 | 241 | |
1c79356b A |
242 | funnel_state = thread_funnel_set(kernel_flock, TRUE); |
243 | ndp = &nd; | |
244 | ||
91447636 | 245 | if ((error = suser(kauth_cred_get(), 0))) |
1c79356b A |
246 | goto swapon_bailout; |
247 | ||
1c79356b A |
248 | /* |
249 | * Get a vnode for the paging area. | |
250 | */ | |
6d2010ae | 251 | NDINIT(ndp, LOOKUP, OP_LOOKUP, FOLLOW | LOCKLEAF | AUDITVNPATH1, |
91447636 | 252 | ((IS_64BIT_PROCESS(p)) ? UIO_USERSPACE64 : UIO_USERSPACE32), |
b0d623f7 | 253 | (user_addr_t) args->filename, ctx); |
1c79356b A |
254 | |
255 | if ((error = namei(ndp))) | |
256 | goto swapon_bailout; | |
91447636 | 257 | nameidone(ndp); |
1c79356b A |
258 | vp = ndp->ni_vp; |
259 | ||
260 | if (vp->v_type != VREG) { | |
261 | error = EINVAL; | |
1c79356b A |
262 | goto swapon_bailout; |
263 | } | |
1c79356b | 264 | |
91447636 | 265 | /* get file size */ |
2d21ac55 A |
266 | if ((error = vnode_size(vp, &file_size, ctx)) != 0) |
267 | goto swapon_bailout; | |
268 | #if CONFIG_MACF | |
269 | vnode_lock(vp); | |
270 | error = mac_system_check_swapon(vfs_context_ucred(ctx), vp); | |
271 | vnode_unlock(vp); | |
272 | if (error) | |
1c79356b | 273 | goto swapon_bailout; |
2d21ac55 | 274 | #endif |
1c79356b | 275 | |
91447636 | 276 | /* resize to desired size if it's too small */ |
2d21ac55 | 277 | if ((file_size < (off_t)size) && ((error = vnode_setsize(vp, (off_t)size, 0, ctx)) != 0)) |
91447636 | 278 | goto swapon_bailout; |
1c79356b | 279 | |
6d2010ae A |
280 | #if CONFIG_PROTECT |
281 | { | |
6d2010ae | 282 | /* initialize content protection keys manually */ |
316670eb A |
283 | if ((error = cp_handle_vnop(vp, CP_WRITE_ACCESS, 0)) != 0) { |
284 | goto swapon_bailout; | |
285 | } | |
6d2010ae A |
286 | } |
287 | #endif | |
288 | ||
289 | ||
0b4c1975 A |
290 | if (default_pager_init_flag == 0) { |
291 | start_def_pager(NULL); | |
292 | default_pager_init_flag = 1; | |
293 | } | |
294 | ||
1c79356b A |
295 | /* add new backing store to list */ |
296 | i = 0; | |
297 | while(bs_port_table[i].vp != 0) { | |
298 | if(i == MAX_BACKING_STORE) | |
299 | break; | |
300 | i++; | |
301 | } | |
302 | if(i == MAX_BACKING_STORE) { | |
303 | error = ENOMEM; | |
1c79356b A |
304 | goto swapon_bailout; |
305 | } | |
306 | ||
307 | /* remember the vnode. This vnode has namei() reference */ | |
308 | bs_port_table[i].vp = vp; | |
309 | ||
310 | /* | |
311 | * Look to see if we are already paging to this file. | |
312 | */ | |
313 | /* make certain the copy send of kernel call will work */ | |
0b4e3aa0 A |
314 | default_pager = MEMORY_OBJECT_DEFAULT_NULL; |
315 | kr = host_default_memory_manager(host_priv_self(), &default_pager, 0); | |
1c79356b A |
316 | if(kr != KERN_SUCCESS) { |
317 | error = EAGAIN; | |
1c79356b A |
318 | bs_port_table[i].vp = 0; |
319 | goto swapon_bailout; | |
320 | } | |
321 | ||
6d2010ae A |
322 | #if CONFIG_EMBEDDED |
323 | dp_cluster_size = 1 * PAGE_SIZE; | |
324 | #else | |
325 | if ((dp_isssd = vnode_pager_isSSD(vp)) == TRUE) { | |
0b4c1975 A |
326 | /* |
327 | * keep the cluster size small since the | |
328 | * seek cost is effectively 0 which means | |
329 | * we don't care much about fragmentation | |
330 | */ | |
0b4c1975 A |
331 | dp_cluster_size = 2 * PAGE_SIZE; |
332 | } else { | |
333 | /* | |
334 | * use the default cluster size | |
335 | */ | |
0b4c1975 A |
336 | dp_cluster_size = 0; |
337 | } | |
6d2010ae | 338 | #endif |
0b4e3aa0 | 339 | kr = default_pager_backing_store_create(default_pager, |
1c79356b | 340 | -1, /* default priority */ |
0b4c1975 | 341 | dp_cluster_size, |
1c79356b | 342 | &backing_store); |
0b4e3aa0 A |
343 | memory_object_default_deallocate(default_pager); |
344 | ||
1c79356b A |
345 | if(kr != KERN_SUCCESS) { |
346 | error = ENOMEM; | |
1c79356b A |
347 | bs_port_table[i].vp = 0; |
348 | goto swapon_bailout; | |
349 | } | |
350 | ||
b0d623f7 A |
351 | /* Mark this vnode as being used for swapfile */ |
352 | vnode_lock_spin(vp); | |
353 | SET(vp->v_flag, VSWAP); | |
354 | vnode_unlock(vp); | |
355 | ||
1c79356b A |
356 | /* |
357 | * NOTE: we are able to supply PAGE_SIZE here instead of | |
358 | * an actual record size or block number because: | |
359 | * a: we do not support offsets from the beginning of the | |
360 | * file (allowing for non page size/record modulo offsets. | |
361 | * b: because allow paging will be done modulo page size | |
362 | */ | |
363 | ||
91447636 A |
364 | kr = default_pager_add_file(backing_store, (vnode_ptr_t) vp, |
365 | PAGE_SIZE, (int)(file_size/PAGE_SIZE)); | |
1c79356b A |
366 | if(kr != KERN_SUCCESS) { |
367 | bs_port_table[i].vp = 0; | |
368 | if(kr == KERN_INVALID_ARGUMENT) | |
369 | error = EINVAL; | |
370 | else | |
371 | error = ENOMEM; | |
b0d623f7 A |
372 | |
373 | /* This vnode is not to be used for swapfile */ | |
374 | vnode_lock_spin(vp); | |
375 | CLR(vp->v_flag, VSWAP); | |
376 | vnode_unlock(vp); | |
377 | ||
1c79356b A |
378 | goto swapon_bailout; |
379 | } | |
380 | bs_port_table[i].bs = (void *)backing_store; | |
381 | error = 0; | |
1c79356b | 382 | |
13fec989 | 383 | ubc_setthreadcred(vp, p, current_thread()); |
55e303ae | 384 | |
1c79356b | 385 | /* |
91447636 | 386 | * take a long term reference on the vnode to keep |
1c79356b A |
387 | * vnreclaim() away from this vnode. |
388 | */ | |
91447636 | 389 | vnode_ref(vp); |
1c79356b A |
390 | |
391 | swapon_bailout: | |
392 | if (vp) { | |
91447636 | 393 | vnode_put(vp); |
1c79356b | 394 | } |
1c79356b | 395 | (void) thread_funnel_set(kernel_flock, FALSE); |
e5568f75 | 396 | AUDIT_MACH_SYSCALL_EXIT(error); |
6d2010ae A |
397 | |
398 | if (error) | |
399 | printf("macx_swapon FAILED - %d\n", error); | |
400 | else | |
401 | printf("macx_swapon SUCCESS\n"); | |
402 | ||
1c79356b A |
403 | return(error); |
404 | } | |
405 | ||
406 | /* | |
407 | * Routine: macx_swapoff | |
408 | * Function: | |
409 | * Syscall interface to remove a file from backing store | |
410 | */ | |
411 | int | |
412 | macx_swapoff( | |
91447636 | 413 | struct macx_swapoff_args *args) |
1c79356b | 414 | { |
91447636 | 415 | __unused int flags = args->flags; |
1c79356b A |
416 | kern_return_t kr; |
417 | mach_port_t backing_store; | |
418 | ||
419 | struct vnode *vp = 0; | |
420 | struct nameidata nd, *ndp; | |
421 | struct proc *p = current_proc(); | |
422 | int i; | |
423 | int error; | |
424 | boolean_t funnel_state; | |
2d21ac55 | 425 | vfs_context_t ctx = vfs_context_current(); |
6d2010ae A |
426 | struct uthread *ut; |
427 | int orig_iopol_disk; | |
1c79356b | 428 | |
e5568f75 | 429 | AUDIT_MACH_SYSCALL_ENTER(AUE_SWAPOFF); |
91447636 | 430 | |
1c79356b A |
431 | funnel_state = thread_funnel_set(kernel_flock, TRUE); |
432 | backing_store = NULL; | |
433 | ndp = &nd; | |
434 | ||
91447636 | 435 | if ((error = suser(kauth_cred_get(), 0))) |
1c79356b A |
436 | goto swapoff_bailout; |
437 | ||
1c79356b A |
438 | /* |
439 | * Get the vnode for the paging area. | |
440 | */ | |
6d2010ae | 441 | NDINIT(ndp, LOOKUP, OP_LOOKUP, FOLLOW | LOCKLEAF | AUDITVNPATH1, |
91447636 | 442 | ((IS_64BIT_PROCESS(p)) ? UIO_USERSPACE64 : UIO_USERSPACE32), |
b0d623f7 | 443 | (user_addr_t) args->filename, ctx); |
1c79356b A |
444 | |
445 | if ((error = namei(ndp))) | |
446 | goto swapoff_bailout; | |
91447636 | 447 | nameidone(ndp); |
1c79356b A |
448 | vp = ndp->ni_vp; |
449 | ||
450 | if (vp->v_type != VREG) { | |
451 | error = EINVAL; | |
1c79356b A |
452 | goto swapoff_bailout; |
453 | } | |
2d21ac55 A |
454 | #if CONFIG_MACF |
455 | vnode_lock(vp); | |
456 | error = mac_system_check_swapoff(vfs_context_ucred(ctx), vp); | |
457 | vnode_unlock(vp); | |
458 | if (error) | |
459 | goto swapoff_bailout; | |
460 | #endif | |
1c79356b A |
461 | |
462 | for(i = 0; i < MAX_BACKING_STORE; i++) { | |
463 | if(bs_port_table[i].vp == vp) { | |
1c79356b A |
464 | break; |
465 | } | |
466 | } | |
467 | if (i == MAX_BACKING_STORE) { | |
468 | error = EINVAL; | |
1c79356b A |
469 | goto swapoff_bailout; |
470 | } | |
471 | backing_store = (mach_port_t)bs_port_table[i].bs; | |
472 | ||
6d2010ae A |
473 | ut = get_bsdthread_info(current_thread()); |
474 | ||
6d2010ae A |
475 | orig_iopol_disk = proc_get_thread_selfdiskacc(); |
476 | proc_apply_thread_selfdiskacc(IOPOL_THROTTLE); | |
6d2010ae | 477 | |
1c79356b | 478 | kr = default_pager_backing_store_delete(backing_store); |
6d2010ae | 479 | |
6d2010ae | 480 | proc_apply_thread_selfdiskacc(orig_iopol_disk); |
6d2010ae | 481 | |
1c79356b A |
482 | switch (kr) { |
483 | case KERN_SUCCESS: | |
484 | error = 0; | |
485 | bs_port_table[i].vp = 0; | |
1c79356b | 486 | /* This vnode is no longer used for swapfile */ |
b0d623f7 | 487 | vnode_lock_spin(vp); |
1c79356b | 488 | CLR(vp->v_flag, VSWAP); |
b0d623f7 | 489 | vnode_unlock(vp); |
1c79356b | 490 | |
91447636 A |
491 | /* get rid of macx_swapon() "long term" reference */ |
492 | vnode_rele(vp); | |
1c79356b | 493 | |
1c79356b A |
494 | break; |
495 | case KERN_FAILURE: | |
496 | error = EAGAIN; | |
497 | break; | |
498 | default: | |
499 | error = EAGAIN; | |
500 | break; | |
501 | } | |
502 | ||
503 | swapoff_bailout: | |
504 | /* get rid of macx_swapoff() namei() reference */ | |
505 | if (vp) | |
91447636 | 506 | vnode_put(vp); |
1c79356b | 507 | |
1c79356b | 508 | (void) thread_funnel_set(kernel_flock, FALSE); |
e5568f75 | 509 | AUDIT_MACH_SYSCALL_EXIT(error); |
6d2010ae A |
510 | |
511 | if (error) | |
512 | printf("macx_swapoff FAILED - %d\n", error); | |
513 | else | |
514 | printf("macx_swapoff SUCCESS\n"); | |
515 | ||
1c79356b A |
516 | return(error); |
517 | } | |
91447636 A |
518 | |
519 | /* | |
520 | * Routine: macx_swapinfo | |
521 | * Function: | |
522 | * Syscall interface to get general swap statistics | |
523 | */ | |
524 | int | |
525 | macx_swapinfo( | |
526 | memory_object_size_t *total_p, | |
527 | memory_object_size_t *avail_p, | |
528 | vm_size_t *pagesize_p, | |
529 | boolean_t *encrypted_p) | |
530 | { | |
531 | int error; | |
532 | memory_object_default_t default_pager; | |
533 | default_pager_info_64_t dpi64; | |
534 | kern_return_t kr; | |
535 | ||
536 | error = 0; | |
537 | ||
538 | /* | |
539 | * Get a handle on the default pager. | |
540 | */ | |
541 | default_pager = MEMORY_OBJECT_DEFAULT_NULL; | |
542 | kr = host_default_memory_manager(host_priv_self(), &default_pager, 0); | |
543 | if (kr != KERN_SUCCESS) { | |
544 | error = EAGAIN; /* XXX why EAGAIN ? */ | |
545 | goto done; | |
546 | } | |
547 | if (default_pager == MEMORY_OBJECT_DEFAULT_NULL) { | |
548 | /* | |
549 | * The default pager has not initialized yet, | |
550 | * so it can't be using any swap space at all. | |
551 | */ | |
552 | *total_p = 0; | |
553 | *avail_p = 0; | |
554 | *pagesize_p = 0; | |
555 | *encrypted_p = FALSE; | |
556 | goto done; | |
557 | } | |
558 | ||
559 | /* | |
560 | * Get swap usage data from default pager. | |
561 | */ | |
562 | kr = default_pager_info_64(default_pager, &dpi64); | |
563 | if (kr != KERN_SUCCESS) { | |
564 | error = ENOTSUP; | |
565 | goto done; | |
566 | } | |
567 | ||
568 | /* | |
569 | * Provide default pager info to caller. | |
570 | */ | |
571 | *total_p = dpi64.dpi_total_space; | |
572 | *avail_p = dpi64.dpi_free_space; | |
573 | *pagesize_p = dpi64.dpi_page_size; | |
574 | if (dpi64.dpi_flags & DPI_ENCRYPTED) { | |
575 | *encrypted_p = TRUE; | |
576 | } else { | |
577 | *encrypted_p = FALSE; | |
578 | } | |
579 | ||
580 | done: | |
581 | if (default_pager != MEMORY_OBJECT_DEFAULT_NULL) { | |
582 | /* release our handle on default pager */ | |
583 | memory_object_default_deallocate(default_pager); | |
584 | } | |
585 | return error; | |
586 | } |