2 * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include "vm_compressor_backing_store.h"
30 #include <vm/vm_protos.h>
32 #include <IOKit/IOHibernatePrivate.h>
35 boolean_t compressor_store_stop_compaction
= FALSE
;
36 boolean_t vm_swap_up
= FALSE
;
37 boolean_t vm_swapfile_create_needed
= FALSE
;
38 boolean_t vm_swapfile_gc_needed
= FALSE
;
40 int swapper_throttle
= -1;
41 boolean_t swapper_throttle_inited
= FALSE
;
42 uint64_t vm_swapout_thread_id
;
44 uint64_t vm_swap_put_failures
= 0;
45 uint64_t vm_swap_get_failures
= 0;
46 int vm_num_swap_files
= 0;
47 int vm_swapout_thread_processed_segments
= 0;
48 int vm_swapout_thread_awakened
= 0;
49 int vm_swapfile_create_thread_awakened
= 0;
50 int vm_swapfile_create_thread_running
= 0;
51 int vm_swapfile_gc_thread_awakened
= 0;
52 int vm_swapfile_gc_thread_running
= 0;
54 int64_t vm_swappin_avail
= 0;
55 unsigned int vm_swapfile_total_segs_alloced
= 0;
56 unsigned int vm_swapfile_total_segs_used
= 0;
59 #define SWAP_READY 0x1 /* Swap file is ready to be used */
60 #define SWAP_RECLAIM 0x2 /* Swap file is marked to be reclaimed */
61 #define SWAP_WANTED 0x4 /* Swap file has waiters */
62 #define SWAP_REUSE 0x8 /* Swap file is on the Q and has a name. Reuse after init-ing.*/
63 #define SWAP_PINNED 0x10 /* Swap file is pinned (FusionDrive) */
67 queue_head_t swp_queue
; /* list of swap files */
68 char *swp_path
; /* saved pathname of swap file */
69 struct vnode
*swp_vp
; /* backing vnode */
70 uint64_t swp_size
; /* size of this swap file */
71 uint8_t *swp_bitmap
; /* bitmap showing the alloced/freed slots in the swap file */
72 unsigned int swp_pathlen
; /* length of pathname */
73 unsigned int swp_nsegs
; /* #segments we can use */
74 unsigned int swp_nseginuse
; /* #segments in use */
75 unsigned int swp_index
; /* index of this swap file */
76 unsigned int swp_flags
; /* state of swap file */
77 unsigned int swp_free_hint
; /* offset of 1st free chunk */
78 unsigned int swp_io_count
; /* count of outstanding I/Os */
79 c_segment_t
*swp_csegs
; /* back pointers to the c_segments. Used during swap reclaim. */
81 struct trim_list
*swp_delayed_trim_list_head
;
82 unsigned int swp_delayed_trim_count
;
85 queue_head_t swf_global_queue
;
86 boolean_t swp_trim_supported
= FALSE
;
88 extern clock_sec_t dont_trim_until_ts
;
89 clock_sec_t vm_swapfile_last_failed_to_create_ts
= 0;
90 clock_sec_t vm_swapfile_last_successful_create_ts
= 0;
91 int vm_swapfile_can_be_created
= FALSE
;
92 boolean_t delayed_trim_handling_in_progress
= FALSE
;
94 static void vm_swapout_thread_throttle_adjust(void);
95 static void vm_swap_free_now(struct swapfile
*swf
, uint64_t f_offset
);
96 static void vm_swapout_thread(void);
97 static void vm_swapfile_create_thread(void);
98 static void vm_swapfile_gc_thread(void);
99 static void vm_swap_defragment();
100 static void vm_swap_handle_delayed_trims(boolean_t
);
101 static void vm_swap_do_delayed_trim();
102 static void vm_swap_wait_on_trim_handling_in_progress(void);
106 #define VM_MAX_SWAP_FILE_NUM 100
107 #define VM_SWAPFILE_DELAYED_TRIM_MAX 128
109 #define VM_SWAP_SHOULD_DEFRAGMENT() (c_swappedout_sparse_count > (vm_swapfile_total_segs_used / 4) ? 1 : 0)
110 #define VM_SWAP_SHOULD_RECLAIM() (((vm_swapfile_total_segs_alloced - vm_swapfile_total_segs_used) >= SWAPFILE_RECLAIM_THRESHOLD_SEGS) ? 1 : 0)
111 #define VM_SWAP_SHOULD_ABORT_RECLAIM() (((vm_swapfile_total_segs_alloced - vm_swapfile_total_segs_used) <= SWAPFILE_RECLAIM_MINIMUM_SEGS) ? 1 : 0)
112 #define VM_SWAP_SHOULD_PIN(_size) (vm_swappin_avail > 0 && vm_swappin_avail >= (int64_t)(_size))
113 #define VM_SWAP_SHOULD_CREATE(cur_ts) ((vm_num_swap_files < VM_MAX_SWAP_FILE_NUM) && ((vm_swapfile_total_segs_alloced - vm_swapfile_total_segs_used) < (unsigned int)VM_SWAPFILE_HIWATER_SEGS) && \
114 ((cur_ts - vm_swapfile_last_failed_to_create_ts) > VM_SWAPFILE_DELAYED_CREATE) ? 1 : 0)
115 #define VM_SWAP_SHOULD_TRIM(swf) ((swf->swp_delayed_trim_count >= VM_SWAPFILE_DELAYED_TRIM_MAX) ? 1 : 0)
118 #define VM_SWAPFILE_DELAYED_CREATE 15
120 #define VM_SWAP_BUSY() ((c_swapout_count && (swapper_throttle == THROTTLE_LEVEL_COMPRESSOR_TIER1 || swapper_throttle == THROTTLE_LEVEL_COMPRESSOR_TIER0)) ? 1 : 0)
123 #if CHECKSUM_THE_SWAP
124 extern unsigned int hash_string(char *cp
, int len
);
127 #if RECORD_THE_COMPRESSED_DATA
128 boolean_t c_compressed_record_init_done
= FALSE
;
129 int c_compressed_record_write_error
= 0;
130 struct vnode
*c_compressed_record_vp
= NULL
;
131 uint64_t c_compressed_record_file_offset
= 0;
132 void c_compressed_record_init(void);
133 void c_compressed_record_write(char *, int);
137 extern boolean_t swap_crypt_ctx_initialized
;
138 extern void swap_crypt_ctx_initialize(void);
139 extern const unsigned char swap_crypt_null_iv
[AES_BLOCK_SIZE
];
140 extern aes_ctx swap_crypt_ctx
;
141 extern unsigned long vm_page_encrypt_counter
;
142 extern unsigned long vm_page_decrypt_counter
;
143 #endif /* ENCRYPTED_SWAP */
145 extern void vm_pageout_io_throttle(void);
146 extern void vm_pageout_reinit_tuneables(void);
147 extern void vm_swap_file_set_tuneables(void);
149 struct swapfile
*vm_swapfile_for_handle(uint64_t);
152 * Called with the vm_swap_data_lock held.
156 vm_swapfile_for_handle(uint64_t f_offset
)
159 uint64_t file_offset
= 0;
160 unsigned int swapfile_index
= 0;
161 struct swapfile
* swf
= NULL
;
163 file_offset
= (f_offset
& SWAP_SLOT_MASK
);
164 swapfile_index
= (f_offset
>> SWAP_DEVICE_SHIFT
);
166 swf
= (struct swapfile
*) queue_first(&swf_global_queue
);
168 while(queue_end(&swf_global_queue
, (queue_entry_t
)swf
) == FALSE
) {
170 if (swapfile_index
== swf
->swp_index
) {
174 swf
= (struct swapfile
*) queue_next(&swf
->swp_queue
);
177 if (queue_end(&swf_global_queue
, (queue_entry_t
) swf
)) {
185 vm_compressor_swap_init()
187 thread_t thread
= NULL
;
189 lck_grp_attr_setdefault(&vm_swap_data_lock_grp_attr
);
190 lck_grp_init(&vm_swap_data_lock_grp
,
192 &vm_swap_data_lock_grp_attr
);
193 lck_attr_setdefault(&vm_swap_data_lock_attr
);
194 lck_mtx_init_ext(&vm_swap_data_lock
,
195 &vm_swap_data_lock_ext
,
196 &vm_swap_data_lock_grp
,
197 &vm_swap_data_lock_attr
);
199 queue_init(&swf_global_queue
);
202 if (kernel_thread_start_priority((thread_continue_t
)vm_swapout_thread
, NULL
,
203 BASEPRI_PREEMPT
- 1, &thread
) != KERN_SUCCESS
) {
204 panic("vm_swapout_thread: create failed");
206 vm_swapout_thread_id
= thread
->thread_id
;
208 thread_deallocate(thread
);
210 if (kernel_thread_start_priority((thread_continue_t
)vm_swapfile_create_thread
, NULL
,
211 BASEPRI_PREEMPT
- 1, &thread
) != KERN_SUCCESS
) {
212 panic("vm_swapfile_create_thread: create failed");
215 thread_deallocate(thread
);
217 if (kernel_thread_start_priority((thread_continue_t
)vm_swapfile_gc_thread
, NULL
,
218 BASEPRI_PREEMPT
- 1, &thread
) != KERN_SUCCESS
) {
219 panic("vm_swapfile_gc_thread: create failed");
221 thread_deallocate(thread
);
223 proc_set_task_policy_thread(kernel_task
, thread
->thread_id
,
224 TASK_POLICY_INTERNAL
, TASK_POLICY_IO
, THROTTLE_LEVEL_COMPRESSOR_TIER2
);
225 proc_set_task_policy_thread(kernel_task
, thread
->thread_id
,
226 TASK_POLICY_INTERNAL
, TASK_POLICY_PASSIVE_IO
, TASK_POLICY_ENABLE
);
229 if (swap_crypt_ctx_initialized
== FALSE
) {
230 swap_crypt_ctx_initialize();
232 #endif /* ENCRYPTED_SWAP */
234 memset(swapfilename
, 0, MAX_SWAPFILENAME_LEN
+ 1);
238 printf("VM Swap Subsystem is %s\n", (vm_swap_up
== TRUE
) ? "ON" : "OFF");
242 #if RECORD_THE_COMPRESSED_DATA
245 c_compressed_record_init()
247 if (c_compressed_record_init_done
== FALSE
) {
248 vm_swapfile_open("/tmp/compressed_data", &c_compressed_record_vp
);
249 c_compressed_record_init_done
= TRUE
;
254 c_compressed_record_write(char *buf
, int size
)
256 if (c_compressed_record_write_error
== 0) {
257 c_compressed_record_write_error
= vm_record_file_write(c_compressed_record_vp
, c_compressed_record_file_offset
, buf
, size
);
258 c_compressed_record_file_offset
+= size
;
266 vm_swap_file_set_tuneables()
272 if (strlen(swapfilename
) == 0) {
274 * If no swapfile name has been set, we'll
275 * use the default name.
277 * Also, this function is only called from the vm_pageout_scan thread
278 * via vm_consider_waking_compactor_swapper,
279 * so we don't need to worry about a race in checking/setting the name here.
281 strlcpy(swapfilename
, SWAP_FILE_NAME
, MAX_SWAPFILENAME_LEN
);
283 namelen
= (int)strlen(swapfilename
) + SWAPFILENAME_INDEX_LEN
+ 1;
284 pathname
= (char*)kalloc(namelen
);
285 memset(pathname
, 0, namelen
);
286 snprintf(pathname
, namelen
, "%s%d", swapfilename
, 0);
288 vm_swapfile_open(pathname
, &vp
);
293 if (vnode_pager_isSSD(vp
) == FALSE
)
294 vm_pageout_reinit_tuneables();
295 vnode_setswapmount(vp
);
296 vm_swappin_avail
= vnode_getswappin_avail(vp
);
297 vm_swapfile_close((uint64_t)pathname
, vp
);
299 kfree(pathname
, namelen
);
305 vm_swap_encrypt(c_segment_t c_seg
)
307 vm_offset_t kernel_vaddr
= 0;
311 unsigned char aes_iv
[AES_BLOCK_SIZE
];
315 assert(swap_crypt_ctx_initialized
);
317 bzero(&encrypt_iv
.aes_iv
[0], sizeof (encrypt_iv
.aes_iv
));
319 encrypt_iv
.c_seg
= (void*)c_seg
;
321 /* encrypt the "initial vector" */
322 aes_encrypt_cbc((const unsigned char *) &encrypt_iv
.aes_iv
[0],
325 &encrypt_iv
.aes_iv
[0],
326 &swap_crypt_ctx
.encrypt
);
328 kernel_vaddr
= (vm_offset_t
) c_seg
->c_store
.c_buffer
;
329 size
= round_page_32(C_SEG_OFFSET_TO_BYTES(c_seg
->c_populated_offset
));
332 * Encrypt the c_segment.
334 aes_encrypt_cbc((const unsigned char *) kernel_vaddr
,
335 &encrypt_iv
.aes_iv
[0],
336 (unsigned int)(size
/ AES_BLOCK_SIZE
),
337 (unsigned char *) kernel_vaddr
,
338 &swap_crypt_ctx
.encrypt
);
340 vm_page_encrypt_counter
+= (size
/PAGE_SIZE_64
);
344 vm_swap_decrypt(c_segment_t c_seg
)
347 vm_offset_t kernel_vaddr
= 0;
351 unsigned char aes_iv
[AES_BLOCK_SIZE
];
356 assert(swap_crypt_ctx_initialized
);
359 * Prepare an "initial vector" for the decryption.
360 * It has to be the same as the "initial vector" we
361 * used to encrypt that page.
363 bzero(&decrypt_iv
.aes_iv
[0], sizeof (decrypt_iv
.aes_iv
));
365 decrypt_iv
.c_seg
= (void*)c_seg
;
367 /* encrypt the "initial vector" */
368 aes_encrypt_cbc((const unsigned char *) &decrypt_iv
.aes_iv
[0],
371 &decrypt_iv
.aes_iv
[0],
372 &swap_crypt_ctx
.encrypt
);
374 kernel_vaddr
= (vm_offset_t
) c_seg
->c_store
.c_buffer
;
375 size
= round_page_32(C_SEG_OFFSET_TO_BYTES(c_seg
->c_populated_offset
));
378 * Decrypt the c_segment.
380 aes_decrypt_cbc((const unsigned char *) kernel_vaddr
,
381 &decrypt_iv
.aes_iv
[0],
382 (unsigned int) (size
/ AES_BLOCK_SIZE
),
383 (unsigned char *) kernel_vaddr
,
384 &swap_crypt_ctx
.decrypt
);
386 vm_page_decrypt_counter
+= (size
/PAGE_SIZE_64
);
388 #endif /* ENCRYPTED_SWAP */
392 vm_swap_consider_defragmenting()
394 if (compressor_store_stop_compaction
== FALSE
&& !VM_SWAP_BUSY() &&
395 (VM_SWAP_SHOULD_DEFRAGMENT() || VM_SWAP_SHOULD_RECLAIM())) {
397 if (!vm_swapfile_gc_thread_running
) {
398 lck_mtx_lock(&vm_swap_data_lock
);
400 if (!vm_swapfile_gc_thread_running
)
401 thread_wakeup((event_t
) &vm_swapfile_gc_needed
);
403 lck_mtx_unlock(&vm_swap_data_lock
);
409 int vm_swap_defragment_yielded
= 0;
410 int vm_swap_defragment_swapin
= 0;
411 int vm_swap_defragment_free
= 0;
412 int vm_swap_defragment_busy
= 0;
421 * have to grab the master lock w/o holding
422 * any locks in spin mode
424 PAGE_REPLACEMENT_DISALLOWED(TRUE
);
426 lck_mtx_lock_spin_always(c_list_lock
);
428 while (!queue_empty(&c_swappedout_sparse_list_head
)) {
430 if (compressor_store_stop_compaction
== TRUE
|| VM_SWAP_BUSY()) {
431 vm_swap_defragment_yielded
++;
434 c_seg
= (c_segment_t
)queue_first(&c_swappedout_sparse_list_head
);
436 lck_mtx_lock_spin_always(&c_seg
->c_lock
);
438 assert(c_seg
->c_state
== C_ON_SWAPPEDOUTSPARSE_Q
);
441 lck_mtx_unlock_always(c_list_lock
);
443 PAGE_REPLACEMENT_DISALLOWED(FALSE
);
445 * c_seg_wait_on_busy consumes c_seg->c_lock
447 c_seg_wait_on_busy(c_seg
);
449 PAGE_REPLACEMENT_DISALLOWED(TRUE
);
451 lck_mtx_lock_spin_always(c_list_lock
);
453 vm_swap_defragment_busy
++;
456 if (c_seg
->c_bytes_used
== 0) {
458 * c_seg_free_locked consumes the c_list_lock
462 c_seg_free_locked(c_seg
);
464 vm_swap_defragment_free
++;
466 lck_mtx_unlock_always(c_list_lock
);
468 c_seg_swapin(c_seg
, TRUE
);
469 lck_mtx_unlock_always(&c_seg
->c_lock
);
471 vm_swap_defragment_swapin
++;
473 PAGE_REPLACEMENT_DISALLOWED(FALSE
);
475 vm_pageout_io_throttle();
478 * because write waiters have privilege over readers,
479 * dropping and immediately retaking the master lock will
480 * still allow any thread waiting to acquire the
481 * master lock exclusively an opportunity to take it
483 PAGE_REPLACEMENT_DISALLOWED(TRUE
);
485 lck_mtx_lock_spin_always(c_list_lock
);
487 lck_mtx_unlock_always(c_list_lock
);
489 PAGE_REPLACEMENT_DISALLOWED(FALSE
);
495 vm_swapfile_create_thread(void)
500 current_thread()->options
|= TH_OPT_VMPRIV
;
502 vm_swapfile_create_thread_awakened
++;
503 vm_swapfile_create_thread_running
= 1;
507 * walk through the list of swap files
508 * and do the delayed frees/trims for
509 * any swap file whose count of delayed
510 * frees is above the batch limit
512 vm_swap_handle_delayed_trims(FALSE
);
514 lck_mtx_lock(&vm_swap_data_lock
);
516 clock_get_system_nanotime(&sec
, &nsec
);
518 if (VM_SWAP_SHOULD_CREATE(sec
) == 0)
521 lck_mtx_unlock(&vm_swap_data_lock
);
523 if (vm_swap_create_file() == FALSE
) {
524 vm_swapfile_last_failed_to_create_ts
= sec
;
525 HIBLOG("vm_swap_create_file failed @ %lu secs\n", (unsigned long)sec
);
528 vm_swapfile_last_successful_create_ts
= sec
;
530 vm_swapfile_create_thread_running
= 0;
532 assert_wait((event_t
)&vm_swapfile_create_needed
, THREAD_UNINT
);
534 lck_mtx_unlock(&vm_swap_data_lock
);
536 thread_block((thread_continue_t
)vm_swapfile_create_thread
);
543 vm_swapfile_gc_thread(void)
545 boolean_t need_defragment
;
546 boolean_t need_reclaim
;
548 vm_swapfile_gc_thread_awakened
++;
549 vm_swapfile_gc_thread_running
= 1;
553 lck_mtx_lock(&vm_swap_data_lock
);
555 if (VM_SWAP_BUSY() || compressor_store_stop_compaction
== TRUE
)
558 need_defragment
= FALSE
;
559 need_reclaim
= FALSE
;
561 if (VM_SWAP_SHOULD_DEFRAGMENT())
562 need_defragment
= TRUE
;
564 if (VM_SWAP_SHOULD_RECLAIM()) {
565 need_defragment
= TRUE
;
568 if (need_defragment
== FALSE
&& need_reclaim
== FALSE
)
571 lck_mtx_unlock(&vm_swap_data_lock
);
573 if (need_defragment
== TRUE
)
574 vm_swap_defragment();
575 if (need_reclaim
== TRUE
)
578 vm_swapfile_gc_thread_running
= 0;
580 assert_wait((event_t
)&vm_swapfile_gc_needed
, THREAD_UNINT
);
582 lck_mtx_unlock(&vm_swap_data_lock
);
584 thread_block((thread_continue_t
)vm_swapfile_gc_thread
);
591 int swapper_entered_T0
= 0;
592 int swapper_entered_T1
= 0;
593 int swapper_entered_T2
= 0;
596 vm_swapout_thread_throttle_adjust(void)
598 int swapper_throttle_new
;
600 if (swapper_throttle_inited
== FALSE
) {
602 * force this thread to be set to the correct
605 swapper_throttle_new
= THROTTLE_LEVEL_COMPRESSOR_TIER2
;
606 swapper_throttle
= THROTTLE_LEVEL_COMPRESSOR_TIER1
;
607 swapper_throttle_inited
= TRUE
;
608 swapper_entered_T2
++;
611 swapper_throttle_new
= swapper_throttle
;
614 switch(swapper_throttle
) {
616 case THROTTLE_LEVEL_COMPRESSOR_TIER2
:
618 if (SWAPPER_NEEDS_TO_UNTHROTTLE() || swapout_target_age
|| hibernate_flushing
== TRUE
) {
619 swapper_throttle_new
= THROTTLE_LEVEL_COMPRESSOR_TIER1
;
620 swapper_entered_T1
++;
625 case THROTTLE_LEVEL_COMPRESSOR_TIER1
:
627 if (VM_PAGEOUT_SCAN_NEEDS_TO_THROTTLE()) {
628 swapper_throttle_new
= THROTTLE_LEVEL_COMPRESSOR_TIER0
;
629 swapper_entered_T0
++;
632 if (COMPRESSOR_NEEDS_TO_SWAP() == 0 && swapout_target_age
== 0 && hibernate_flushing
== FALSE
) {
633 swapper_throttle_new
= THROTTLE_LEVEL_COMPRESSOR_TIER2
;
634 swapper_entered_T2
++;
639 case THROTTLE_LEVEL_COMPRESSOR_TIER0
:
641 if (COMPRESSOR_NEEDS_TO_SWAP() == 0) {
642 swapper_throttle_new
= THROTTLE_LEVEL_COMPRESSOR_TIER2
;
643 swapper_entered_T2
++;
646 if (SWAPPER_NEEDS_TO_UNTHROTTLE() == 0) {
647 swapper_throttle_new
= THROTTLE_LEVEL_COMPRESSOR_TIER1
;
648 swapper_entered_T1
++;
654 if (swapper_throttle
!= swapper_throttle_new
) {
655 proc_set_task_policy_thread(kernel_task
, vm_swapout_thread_id
,
656 TASK_POLICY_INTERNAL
, TASK_POLICY_IO
, swapper_throttle_new
);
657 proc_set_task_policy_thread(kernel_task
, vm_swapout_thread_id
,
658 TASK_POLICY_INTERNAL
, TASK_POLICY_PASSIVE_IO
, TASK_POLICY_ENABLE
);
660 swapper_throttle
= swapper_throttle_new
;
665 int vm_swapout_found_empty
= 0;
669 vm_swapout_thread(void)
671 uint64_t f_offset
= 0;
673 c_segment_t c_seg
= NULL
;
674 kern_return_t kr
= KERN_SUCCESS
;
675 vm_offset_t addr
= 0;
677 current_thread()->options
|= TH_OPT_VMPRIV
;
679 vm_swapout_thread_awakened
++;
681 lck_mtx_lock_spin_always(c_list_lock
);
683 while (!queue_empty(&c_swapout_list_head
)) {
685 c_seg
= (c_segment_t
)queue_first(&c_swapout_list_head
);
687 lck_mtx_lock_spin_always(&c_seg
->c_lock
);
689 assert(c_seg
->c_state
== C_ON_SWAPOUT_Q
);
692 lck_mtx_unlock_always(c_list_lock
);
694 c_seg_wait_on_busy(c_seg
);
696 lck_mtx_lock_spin_always(c_list_lock
);
700 vm_swapout_thread_processed_segments
++;
702 size
= round_page_32(C_SEG_OFFSET_TO_BYTES(c_seg
->c_populated_offset
));
705 assert(c_seg
->c_on_minorcompact_q
);
706 assert(c_seg
->c_bytes_used
== 0);
708 c_seg_switch_state(c_seg
, C_IS_EMPTY
, FALSE
);
709 lck_mtx_unlock_always(&c_seg
->c_lock
);
710 lck_mtx_unlock_always(c_list_lock
);
712 vm_swapout_found_empty
++;
716 c_seg
->c_busy_swapping
= 1;
718 lck_mtx_unlock_always(c_list_lock
);
720 addr
= (vm_offset_t
) c_seg
->c_store
.c_buffer
;
722 lck_mtx_unlock_always(&c_seg
->c_lock
);
724 #if CHECKSUM_THE_SWAP
725 c_seg
->cseg_hash
= hash_string((char*)addr
, (int)size
);
726 c_seg
->cseg_swap_size
= size
;
727 #endif /* CHECKSUM_THE_SWAP */
730 vm_swap_encrypt(c_seg
);
731 #endif /* ENCRYPTED_SWAP */
733 vm_swapout_thread_throttle_adjust();
735 kr
= vm_swap_put((vm_offset_t
) addr
, &f_offset
, size
, c_seg
);
737 PAGE_REPLACEMENT_DISALLOWED(TRUE
);
739 if (kr
== KERN_SUCCESS
) {
740 kernel_memory_depopulate(kernel_map
, (vm_offset_t
) addr
, size
, KMA_COMPRESSOR
);
742 lck_mtx_lock_spin_always(c_list_lock
);
743 lck_mtx_lock_spin_always(&c_seg
->c_lock
);
745 if (kr
== KERN_SUCCESS
) {
746 int new_state
= C_ON_SWAPPEDOUT_Q
;
747 boolean_t insert_head
= FALSE
;
749 if (hibernate_flushing
== TRUE
) {
750 if (c_seg
->c_generation_id
>= first_c_segment_to_warm_generation_id
&&
751 c_seg
->c_generation_id
<= last_c_segment_to_warm_generation_id
)
753 } else if (C_SEG_ONDISK_IS_SPARSE(c_seg
))
754 new_state
= C_ON_SWAPPEDOUTSPARSE_Q
;
756 c_seg_switch_state(c_seg
, new_state
, insert_head
);
758 c_seg
->c_store
.c_swap_handle
= f_offset
;
760 VM_STAT_INCR_BY(swapouts
, size
>> PAGE_SHIFT
);
762 if (c_seg
->c_bytes_used
)
763 OSAddAtomic64(-c_seg
->c_bytes_used
, &compressor_bytes_used
);
766 vm_swap_decrypt(c_seg
);
767 #endif /* ENCRYPTED_SWAP */
768 if (c_seg
->c_overage_swap
== TRUE
) {
769 c_seg
->c_overage_swap
= FALSE
;
770 c_overage_swapped_count
--;
772 c_seg_switch_state(c_seg
, C_ON_AGE_Q
, FALSE
);
774 lck_mtx_unlock_always(c_list_lock
);
776 c_seg
->c_busy_swapping
= 0;
777 C_SEG_WAKEUP_DONE(c_seg
);
778 lck_mtx_unlock_always(&c_seg
->c_lock
);
780 PAGE_REPLACEMENT_DISALLOWED(FALSE
);
782 vm_pageout_io_throttle();
784 if (c_swapout_count
== 0)
785 vm_swap_consider_defragmenting();
787 lck_mtx_lock_spin_always(c_list_lock
);
790 assert_wait((event_t
)&c_swapout_list_head
, THREAD_UNINT
);
792 lck_mtx_unlock_always(c_list_lock
);
794 thread_block((thread_continue_t
)vm_swapout_thread
);
800 vm_swap_create_file()
804 boolean_t swap_file_created
= FALSE
;
805 boolean_t swap_file_reuse
= FALSE
;
806 boolean_t swap_file_pin
= FALSE
;
807 struct swapfile
*swf
= NULL
;
810 * Any swapfile structure ready for re-use?
813 lck_mtx_lock(&vm_swap_data_lock
);
815 swf
= (struct swapfile
*) queue_first(&swf_global_queue
);
817 while (queue_end(&swf_global_queue
, (queue_entry_t
)swf
) == FALSE
) {
818 if (swf
->swp_flags
== SWAP_REUSE
) {
819 swap_file_reuse
= TRUE
;
822 swf
= (struct swapfile
*) queue_next(&swf
->swp_queue
);
825 lck_mtx_unlock(&vm_swap_data_lock
);
827 if (swap_file_reuse
== FALSE
) {
829 if (strlen(swapfilename
) == 0) {
831 * If no swapfile name has been set, we'll
832 * use the default name.
834 * Also, this function is only called from the swapfile management thread.
835 * So we don't need to worry about a race in checking/setting the name here.
838 strlcpy(swapfilename
, SWAP_FILE_NAME
, MAX_SWAPFILENAME_LEN
);
841 namelen
= (int)strlen(swapfilename
) + SWAPFILENAME_INDEX_LEN
+ 1;
843 swf
= (struct swapfile
*) kalloc(sizeof *swf
);
844 memset(swf
, 0, sizeof(*swf
));
846 swf
->swp_index
= vm_num_swap_files
+ 1;
847 swf
->swp_pathlen
= namelen
;
848 swf
->swp_path
= (char*)kalloc(swf
->swp_pathlen
);
850 memset(swf
->swp_path
, 0, namelen
);
852 snprintf(swf
->swp_path
, namelen
, "%s%d", swapfilename
, vm_num_swap_files
);
855 vm_swapfile_open(swf
->swp_path
, &swf
->swp_vp
);
857 if (swf
->swp_vp
== NULL
) {
858 if (swap_file_reuse
== FALSE
) {
859 kfree(swf
->swp_path
, swf
->swp_pathlen
);
860 kfree(swf
, sizeof *swf
);
864 vm_swapfile_can_be_created
= TRUE
;
866 size
= MAX_SWAP_FILE_SIZE
;
868 while (size
>= MIN_SWAP_FILE_SIZE
) {
870 swap_file_pin
= VM_SWAP_SHOULD_PIN(size
);
872 if (vm_swapfile_preallocate(swf
->swp_vp
, &size
, &swap_file_pin
) == 0) {
874 int num_bytes_for_bitmap
= 0;
876 swap_file_created
= TRUE
;
878 swf
->swp_size
= size
;
879 swf
->swp_nsegs
= (unsigned int) (size
/ COMPRESSED_SWAP_CHUNK_SIZE
);
880 swf
->swp_nseginuse
= 0;
881 swf
->swp_free_hint
= 0;
883 num_bytes_for_bitmap
= MAX((swf
->swp_nsegs
>> 3) , 1);
885 * Allocate a bitmap that describes the
886 * number of segments held by this swapfile.
888 swf
->swp_bitmap
= (uint8_t*)kalloc(num_bytes_for_bitmap
);
889 memset(swf
->swp_bitmap
, 0, num_bytes_for_bitmap
);
891 swf
->swp_csegs
= (c_segment_t
*) kalloc(swf
->swp_nsegs
* sizeof(c_segment_t
));
892 memset(swf
->swp_csegs
, 0, (swf
->swp_nsegs
* sizeof(c_segment_t
)));
895 * passing a NULL trim_list into vnode_trim_list
896 * will return ENOTSUP if trim isn't supported
899 if (vnode_trim_list(swf
->swp_vp
, NULL
, FALSE
) == 0)
900 swp_trim_supported
= TRUE
;
902 lck_mtx_lock(&vm_swap_data_lock
);
904 swf
->swp_flags
= SWAP_READY
;
906 if (swap_file_reuse
== FALSE
) {
907 queue_enter(&swf_global_queue
, swf
, struct swapfile
*, swp_queue
);
912 vm_swapfile_total_segs_alloced
+= swf
->swp_nsegs
;
914 if (swap_file_pin
== TRUE
) {
915 swf
->swp_flags
|= SWAP_PINNED
;
916 vm_swappin_avail
-= swf
->swp_size
;
919 lck_mtx_unlock(&vm_swap_data_lock
);
921 thread_wakeup((event_t
) &vm_num_swap_files
);
928 if (swap_file_created
== FALSE
) {
930 vm_swapfile_close((uint64_t)(swf
->swp_path
), swf
->swp_vp
);
934 if (swap_file_reuse
== FALSE
) {
935 kfree(swf
->swp_path
, swf
->swp_pathlen
);
936 kfree(swf
, sizeof *swf
);
939 return swap_file_created
;
944 vm_swap_get(vm_offset_t addr
, uint64_t f_offset
, uint64_t size
)
946 struct swapfile
*swf
= NULL
;
947 uint64_t file_offset
= 0;
954 lck_mtx_lock(&vm_swap_data_lock
);
956 swf
= vm_swapfile_for_handle(f_offset
);
958 if (swf
== NULL
|| ( !(swf
->swp_flags
& SWAP_READY
) && !(swf
->swp_flags
& SWAP_RECLAIM
))) {
964 lck_mtx_unlock(&vm_swap_data_lock
);
966 file_offset
= (f_offset
& SWAP_SLOT_MASK
);
967 retval
= vm_swapfile_io(swf
->swp_vp
, file_offset
, addr
, (int)(size
/ PAGE_SIZE_64
), SWAP_READ
);
970 VM_STAT_INCR_BY(swapins
, size
>> PAGE_SHIFT
);
972 vm_swap_get_failures
++;
975 * Free this slot in the swap structure.
977 vm_swap_free(f_offset
);
979 lck_mtx_lock(&vm_swap_data_lock
);
982 if ((swf
->swp_flags
& SWAP_WANTED
) && swf
->swp_io_count
== 0) {
984 swf
->swp_flags
&= ~SWAP_WANTED
;
985 thread_wakeup((event_t
) &swf
->swp_flags
);
988 lck_mtx_unlock(&vm_swap_data_lock
);
997 vm_swap_put(vm_offset_t addr
, uint64_t *f_offset
, uint64_t size
, c_segment_t c_seg
)
999 unsigned int segidx
= 0;
1000 struct swapfile
*swf
= NULL
;
1001 uint64_t file_offset
= 0;
1002 uint64_t swapfile_index
= 0;
1003 unsigned int byte_for_segidx
= 0;
1004 unsigned int offset_within_byte
= 0;
1005 boolean_t swf_eligible
= FALSE
;
1006 boolean_t waiting
= FALSE
;
1007 boolean_t retried
= FALSE
;
1012 if (addr
== 0 || f_offset
== NULL
) {
1013 return KERN_FAILURE
;
1016 lck_mtx_lock(&vm_swap_data_lock
);
1018 swf
= (struct swapfile
*) queue_first(&swf_global_queue
);
1020 while(queue_end(&swf_global_queue
, (queue_entry_t
)swf
) == FALSE
) {
1022 segidx
= swf
->swp_free_hint
;
1024 swf_eligible
= (swf
->swp_flags
& SWAP_READY
) && (swf
->swp_nseginuse
< swf
->swp_nsegs
);
1028 while(segidx
< swf
->swp_nsegs
) {
1030 byte_for_segidx
= segidx
>> 3;
1031 offset_within_byte
= segidx
% 8;
1033 if ((swf
->swp_bitmap
)[byte_for_segidx
] & (1 << offset_within_byte
)) {
1038 (swf
->swp_bitmap
)[byte_for_segidx
] |= (1 << offset_within_byte
);
1040 file_offset
= segidx
* COMPRESSED_SWAP_CHUNK_SIZE
;
1041 swf
->swp_nseginuse
++;
1042 swf
->swp_io_count
++;
1043 swapfile_index
= swf
->swp_index
;
1045 vm_swapfile_total_segs_used
++;
1047 clock_get_system_nanotime(&sec
, &nsec
);
1049 if (VM_SWAP_SHOULD_CREATE(sec
) && !vm_swapfile_create_thread_running
)
1050 thread_wakeup((event_t
) &vm_swapfile_create_needed
);
1052 lck_mtx_unlock(&vm_swap_data_lock
);
1057 swf
= (struct swapfile
*) queue_next(&swf
->swp_queue
);
1059 assert(queue_end(&swf_global_queue
, (queue_entry_t
) swf
));
1062 * we've run out of swap segments, but may not
1063 * be in a position to immediately create a new swap
1064 * file if we've recently failed to create due to a lack
1065 * of free space in the root filesystem... we'll try
1066 * to kick that create off, but in any event we're going
1067 * to take a breather (up to 1 second) so that we're not caught in a tight
1068 * loop back in "vm_compressor_compact_and_swap" trying to stuff
1069 * segments into swap files only to have them immediately put back
1070 * on the c_age queue due to vm_swap_put failing.
1072 * if we're doing these puts due to a hibernation flush,
1073 * no need to block... setting hibernate_no_swapspace to TRUE,
1074 * will cause "vm_compressor_compact_and_swap" to immediately abort
1076 clock_get_system_nanotime(&sec
, &nsec
);
1078 if (VM_SWAP_SHOULD_CREATE(sec
) && !vm_swapfile_create_thread_running
)
1079 thread_wakeup((event_t
) &vm_swapfile_create_needed
);
1081 if (hibernate_flushing
== FALSE
|| VM_SWAP_SHOULD_CREATE(sec
)) {
1083 assert_wait_timeout((event_t
) &vm_num_swap_files
, THREAD_INTERRUPTIBLE
, 1000, 1000*NSEC_PER_USEC
);
1085 hibernate_no_swapspace
= TRUE
;
1087 lck_mtx_unlock(&vm_swap_data_lock
);
1089 if (waiting
== TRUE
) {
1090 thread_block(THREAD_CONTINUE_NULL
);
1092 if (retried
== FALSE
&& hibernate_flushing
== TRUE
) {
1097 vm_swap_put_failures
++;
1099 return KERN_FAILURE
;
1102 error
= vm_swapfile_io(swf
->swp_vp
, file_offset
, addr
, (int) (size
/ PAGE_SIZE_64
), SWAP_WRITE
);
1104 lck_mtx_lock(&vm_swap_data_lock
);
1106 swf
->swp_csegs
[segidx
] = c_seg
;
1108 swf
->swp_io_count
--;
1110 *f_offset
= (swapfile_index
<< SWAP_DEVICE_SHIFT
) | file_offset
;
1112 if ((swf
->swp_flags
& SWAP_WANTED
) && swf
->swp_io_count
== 0) {
1114 swf
->swp_flags
&= ~SWAP_WANTED
;
1115 thread_wakeup((event_t
) &swf
->swp_flags
);
1118 lck_mtx_unlock(&vm_swap_data_lock
);
1121 vm_swap_free(*f_offset
);
1123 vm_swap_put_failures
++;
1125 return KERN_FAILURE
;
1127 return KERN_SUCCESS
;
1133 vm_swap_free_now(struct swapfile
*swf
, uint64_t f_offset
)
1135 uint64_t file_offset
= 0;
1136 unsigned int segidx
= 0;
1139 if ((swf
->swp_flags
& SWAP_READY
) || (swf
->swp_flags
& SWAP_RECLAIM
)) {
1141 unsigned int byte_for_segidx
= 0;
1142 unsigned int offset_within_byte
= 0;
1144 file_offset
= (f_offset
& SWAP_SLOT_MASK
);
1145 segidx
= (unsigned int) (file_offset
/ COMPRESSED_SWAP_CHUNK_SIZE
);
1147 byte_for_segidx
= segidx
>> 3;
1148 offset_within_byte
= segidx
% 8;
1150 if ((swf
->swp_bitmap
)[byte_for_segidx
] & (1 << offset_within_byte
)) {
1152 (swf
->swp_bitmap
)[byte_for_segidx
] &= ~(1 << offset_within_byte
);
1154 swf
->swp_csegs
[segidx
] = NULL
;
1156 swf
->swp_nseginuse
--;
1157 vm_swapfile_total_segs_used
--;
1159 if (segidx
< swf
->swp_free_hint
) {
1160 swf
->swp_free_hint
= segidx
;
1163 if (VM_SWAP_SHOULD_RECLAIM() && !vm_swapfile_gc_thread_running
)
1164 thread_wakeup((event_t
) &vm_swapfile_gc_needed
);
1169 uint32_t vm_swap_free_now_count
= 0;
1170 uint32_t vm_swap_free_delayed_count
= 0;
1174 vm_swap_free(uint64_t f_offset
)
1176 struct swapfile
*swf
= NULL
;
1177 struct trim_list
*tl
= NULL
;
1181 if (swp_trim_supported
== TRUE
)
1182 tl
= kalloc(sizeof(struct trim_list
));
1184 lck_mtx_lock(&vm_swap_data_lock
);
1186 swf
= vm_swapfile_for_handle(f_offset
);
1188 if (swf
&& (swf
->swp_flags
& (SWAP_READY
| SWAP_RECLAIM
))) {
1190 if (swp_trim_supported
== FALSE
|| (swf
->swp_flags
& SWAP_RECLAIM
)) {
1192 * don't delay the free if the underlying disk doesn't support
1193 * trim, or we're in the midst of reclaiming this swap file since
1194 * we don't want to move segments that are technically free
1195 * but not yet handled by the delayed free mechanism
1197 vm_swap_free_now(swf
, f_offset
);
1199 vm_swap_free_now_count
++;
1202 tl
->tl_offset
= f_offset
& SWAP_SLOT_MASK
;
1203 tl
->tl_length
= COMPRESSED_SWAP_CHUNK_SIZE
;
1205 tl
->tl_next
= swf
->swp_delayed_trim_list_head
;
1206 swf
->swp_delayed_trim_list_head
= tl
;
1207 swf
->swp_delayed_trim_count
++;
1210 if (VM_SWAP_SHOULD_TRIM(swf
) && !vm_swapfile_create_thread_running
) {
1211 clock_get_system_nanotime(&sec
, &nsec
);
1213 if (sec
> dont_trim_until_ts
)
1214 thread_wakeup((event_t
) &vm_swapfile_create_needed
);
1216 vm_swap_free_delayed_count
++;
1219 lck_mtx_unlock(&vm_swap_data_lock
);
1222 kfree(tl
, sizeof(struct trim_list
));
1227 vm_swap_wait_on_trim_handling_in_progress()
1229 while (delayed_trim_handling_in_progress
== TRUE
) {
1231 assert_wait((event_t
) &delayed_trim_handling_in_progress
, THREAD_UNINT
);
1232 lck_mtx_unlock(&vm_swap_data_lock
);
1234 thread_block(THREAD_CONTINUE_NULL
);
1236 lck_mtx_lock(&vm_swap_data_lock
);
1242 vm_swap_handle_delayed_trims(boolean_t force_now
)
1244 struct swapfile
*swf
= NULL
;
1247 * serialize the race between us and vm_swap_reclaim...
1248 * if vm_swap_reclaim wins it will turn off SWAP_READY
1249 * on the victim it has chosen... we can just skip over
1250 * that file since vm_swap_reclaim will first process
1251 * all of the delayed trims associated with it
1253 lck_mtx_lock(&vm_swap_data_lock
);
1255 delayed_trim_handling_in_progress
= TRUE
;
1257 lck_mtx_unlock(&vm_swap_data_lock
);
1260 * no need to hold the lock to walk the swf list since
1261 * vm_swap_create (the only place where we add to this list)
1262 * is run on the same thread as this function
1263 * and vm_swap_reclaim doesn't remove items from this list
1264 * instead marking them with SWAP_REUSE for future re-use
1266 swf
= (struct swapfile
*) queue_first(&swf_global_queue
);
1268 while (queue_end(&swf_global_queue
, (queue_entry_t
)swf
) == FALSE
) {
1270 if ((swf
->swp_flags
& SWAP_READY
) && (force_now
== TRUE
|| VM_SWAP_SHOULD_TRIM(swf
))) {
1272 assert(!(swf
->swp_flags
& SWAP_RECLAIM
));
1273 vm_swap_do_delayed_trim(swf
);
1275 swf
= (struct swapfile
*) queue_next(&swf
->swp_queue
);
1277 lck_mtx_lock(&vm_swap_data_lock
);
1279 delayed_trim_handling_in_progress
= FALSE
;
1280 thread_wakeup((event_t
) &delayed_trim_handling_in_progress
);
1282 if (VM_SWAP_SHOULD_RECLAIM() && !vm_swapfile_gc_thread_running
)
1283 thread_wakeup((event_t
) &vm_swapfile_gc_needed
);
1285 lck_mtx_unlock(&vm_swap_data_lock
);
1290 vm_swap_do_delayed_trim(struct swapfile
*swf
)
1292 struct trim_list
*tl
, *tl_head
;
1294 lck_mtx_lock(&vm_swap_data_lock
);
1296 tl_head
= swf
->swp_delayed_trim_list_head
;
1297 swf
->swp_delayed_trim_list_head
= NULL
;
1298 swf
->swp_delayed_trim_count
= 0;
1300 lck_mtx_unlock(&vm_swap_data_lock
);
1302 vnode_trim_list(swf
->swp_vp
, tl_head
, TRUE
);
1304 while ((tl
= tl_head
) != NULL
) {
1305 unsigned int segidx
= 0;
1306 unsigned int byte_for_segidx
= 0;
1307 unsigned int offset_within_byte
= 0;
1309 lck_mtx_lock(&vm_swap_data_lock
);
1311 segidx
= (unsigned int) (tl
->tl_offset
/ COMPRESSED_SWAP_CHUNK_SIZE
);
1313 byte_for_segidx
= segidx
>> 3;
1314 offset_within_byte
= segidx
% 8;
1316 if ((swf
->swp_bitmap
)[byte_for_segidx
] & (1 << offset_within_byte
)) {
1318 (swf
->swp_bitmap
)[byte_for_segidx
] &= ~(1 << offset_within_byte
);
1320 swf
->swp_csegs
[segidx
] = NULL
;
1322 swf
->swp_nseginuse
--;
1323 vm_swapfile_total_segs_used
--;
1325 if (segidx
< swf
->swp_free_hint
) {
1326 swf
->swp_free_hint
= segidx
;
1329 lck_mtx_unlock(&vm_swap_data_lock
);
1331 tl_head
= tl
->tl_next
;
1333 kfree(tl
, sizeof(struct trim_list
));
1344 int vm_swap_reclaim_yielded
= 0;
1347 vm_swap_reclaim(void)
1349 vm_offset_t addr
= 0;
1350 unsigned int segidx
= 0;
1351 uint64_t f_offset
= 0;
1352 struct swapfile
*swf
= NULL
;
1353 struct swapfile
*smallest_swf
= NULL
;
1354 unsigned int min_nsegs
= 0;
1355 unsigned int byte_for_segidx
= 0;
1356 unsigned int offset_within_byte
= 0;
1357 uint32_t c_size
= 0;
1359 c_segment_t c_seg
= NULL
;
1361 if (kernel_memory_allocate(kernel_map
, (vm_offset_t
*)(&addr
), C_SEG_BUFSIZE
, 0, KMA_KOBJECT
, VM_KERN_MEMORY_COMPRESSOR
) != KERN_SUCCESS
) {
1362 panic("vm_swap_reclaim: kernel_memory_allocate failed\n");
1365 lck_mtx_lock(&vm_swap_data_lock
);
1368 * if we're running the swapfile list looking for
1369 * candidates with delayed trims, we need to
1370 * wait before making our decision concerning
1371 * the swapfile we want to reclaim
1373 vm_swap_wait_on_trim_handling_in_progress();
1376 * from here until we knock down the SWAP_READY bit,
1377 * we need to remain behind the vm_swap_data_lock...
1378 * once that bit has been turned off, "vm_swap_handle_delayed_trims"
1379 * will not consider this swapfile for processing
1381 swf
= (struct swapfile
*) queue_first(&swf_global_queue
);
1382 min_nsegs
= MAX_SWAP_FILE_SIZE
/ COMPRESSED_SWAP_CHUNK_SIZE
;
1383 smallest_swf
= NULL
;
1385 while (queue_end(&swf_global_queue
, (queue_entry_t
)swf
) == FALSE
) {
1387 if ((swf
->swp_flags
& SWAP_READY
) && (swf
->swp_nseginuse
<= min_nsegs
)) {
1390 min_nsegs
= swf
->swp_nseginuse
;
1392 swf
= (struct swapfile
*) queue_next(&swf
->swp_queue
);
1395 if (smallest_swf
== NULL
)
1401 swf
->swp_flags
&= ~SWAP_READY
;
1402 swf
->swp_flags
|= SWAP_RECLAIM
;
1404 if (swf
->swp_delayed_trim_count
) {
1406 lck_mtx_unlock(&vm_swap_data_lock
);
1408 vm_swap_do_delayed_trim(swf
);
1410 lck_mtx_lock(&vm_swap_data_lock
);
1414 while (segidx
< swf
->swp_nsegs
) {
1418 * Wait for outgoing I/Os.
1420 while (swf
->swp_io_count
) {
1422 swf
->swp_flags
|= SWAP_WANTED
;
1424 assert_wait((event_t
) &swf
->swp_flags
, THREAD_UNINT
);
1425 lck_mtx_unlock(&vm_swap_data_lock
);
1427 thread_block(THREAD_CONTINUE_NULL
);
1429 lck_mtx_lock(&vm_swap_data_lock
);
1431 if (compressor_store_stop_compaction
== TRUE
|| VM_SWAP_SHOULD_ABORT_RECLAIM() || VM_SWAP_BUSY()) {
1432 vm_swap_reclaim_yielded
++;
1436 byte_for_segidx
= segidx
>> 3;
1437 offset_within_byte
= segidx
% 8;
1439 if (((swf
->swp_bitmap
)[byte_for_segidx
] & (1 << offset_within_byte
)) == 0) {
1445 c_seg
= swf
->swp_csegs
[segidx
];
1448 lck_mtx_lock_spin_always(&c_seg
->c_lock
);
1450 if (c_seg
->c_busy
) {
1452 * a swapped out c_segment in the process of being freed will remain in the
1453 * busy state until after the vm_swap_free is called on it... vm_swap_free
1454 * takes the vm_swap_data_lock, so can't change the swap state until after
1455 * we drop the vm_swap_data_lock... once we do, vm_swap_free will complete
1456 * which will allow c_seg_free_locked to clear busy and wake up this thread...
1457 * at that point, we re-look up the swap state which will now indicate that
1458 * this c_segment no longer exists.
1460 c_seg
->c_wanted
= 1;
1462 assert_wait((event_t
) (c_seg
), THREAD_UNINT
);
1463 lck_mtx_unlock_always(&c_seg
->c_lock
);
1465 lck_mtx_unlock(&vm_swap_data_lock
);
1467 thread_block(THREAD_CONTINUE_NULL
);
1469 lck_mtx_lock(&vm_swap_data_lock
);
1471 goto ReTry_for_cseg
;
1473 (swf
->swp_bitmap
)[byte_for_segidx
] &= ~(1 << offset_within_byte
);
1475 f_offset
= segidx
* COMPRESSED_SWAP_CHUNK_SIZE
;
1477 assert(c_seg
== swf
->swp_csegs
[segidx
]);
1478 swf
->swp_csegs
[segidx
] = NULL
;
1479 swf
->swp_nseginuse
--;
1481 vm_swapfile_total_segs_used
--;
1483 lck_mtx_unlock(&vm_swap_data_lock
);
1485 assert(C_SEG_IS_ONDISK(c_seg
));
1488 c_seg
->c_busy_swapping
= 1;
1489 #if !CHECKSUM_THE_SWAP
1490 c_seg_trim_tail(c_seg
);
1492 c_size
= round_page_32(C_SEG_OFFSET_TO_BYTES(c_seg
->c_populated_offset
));
1494 assert(c_size
<= C_SEG_BUFSIZE
&& c_size
);
1496 lck_mtx_unlock_always(&c_seg
->c_lock
);
1498 if (vm_swapfile_io(swf
->swp_vp
, f_offset
, addr
, (int)(c_size
/ PAGE_SIZE_64
), SWAP_READ
)) {
1501 * reading the data back in failed, so convert c_seg
1502 * to a swapped in c_segment that contains no data
1504 c_seg_swapin_requeue(c_seg
, FALSE
);
1506 * returns with c_busy_swapping cleared
1509 vm_swap_get_failures
++;
1510 goto swap_io_failed
;
1512 VM_STAT_INCR_BY(swapins
, c_size
>> PAGE_SHIFT
);
1514 if (vm_swap_put(addr
, &f_offset
, c_size
, c_seg
)) {
1515 vm_offset_t c_buffer
;
1518 * the put failed, so convert c_seg to a fully swapped in c_segment
1521 c_buffer
= (vm_offset_t
)C_SEG_BUFFER_ADDRESS(c_seg
->c_mysegno
);
1523 kernel_memory_populate(kernel_map
, c_buffer
, c_size
, KMA_COMPRESSOR
, VM_KERN_MEMORY_COMPRESSOR
);
1525 memcpy((char *)c_buffer
, (char *)addr
, c_size
);
1527 c_seg
->c_store
.c_buffer
= (int32_t *)c_buffer
;
1529 vm_swap_decrypt(c_seg
);
1530 #endif /* ENCRYPTED_SWAP */
1531 c_seg_swapin_requeue(c_seg
, TRUE
);
1533 * returns with c_busy_swapping cleared
1535 OSAddAtomic64(c_seg
->c_bytes_used
, &compressor_bytes_used
);
1537 goto swap_io_failed
;
1539 VM_STAT_INCR_BY(swapouts
, c_size
>> PAGE_SHIFT
);
1541 lck_mtx_lock_spin_always(&c_seg
->c_lock
);
1543 assert(C_SEG_IS_ONDISK(c_seg
));
1545 * The c_seg will now know about the new location on disk.
1547 c_seg
->c_store
.c_swap_handle
= f_offset
;
1548 c_seg
->c_busy_swapping
= 0;
1550 C_SEG_WAKEUP_DONE(c_seg
);
1552 lck_mtx_unlock_always(&c_seg
->c_lock
);
1553 lck_mtx_lock(&vm_swap_data_lock
);
1556 if (swf
->swp_nseginuse
) {
1558 swf
->swp_flags
&= ~SWAP_RECLAIM
;
1559 swf
->swp_flags
|= SWAP_READY
;
1564 * We don't remove this inactive swf from the queue.
1565 * That way, we can re-use it when needed again and
1566 * preserve the namespace. The delayed_trim processing
1567 * is also dependent on us not removing swfs from the queue.
1569 //queue_remove(&swf_global_queue, swf, struct swapfile*, swp_queue);
1571 vm_num_swap_files
--;
1573 vm_swapfile_total_segs_alloced
-= swf
->swp_nsegs
;
1575 lck_mtx_unlock(&vm_swap_data_lock
);
1577 vm_swapfile_close((uint64_t)(swf
->swp_path
), swf
->swp_vp
);
1579 kfree(swf
->swp_csegs
, swf
->swp_nsegs
* sizeof(c_segment_t
));
1580 kfree(swf
->swp_bitmap
, MAX((swf
->swp_nsegs
>> 3), 1));
1582 lck_mtx_lock(&vm_swap_data_lock
);
1584 if (swf
->swp_flags
& SWAP_PINNED
) {
1585 vm_swappin_avail
+= swf
->swp_size
;
1590 swf
->swp_free_hint
= 0;
1592 swf
->swp_flags
= SWAP_REUSE
;
1595 thread_wakeup((event_t
) &swf
->swp_flags
);
1596 lck_mtx_unlock(&vm_swap_data_lock
);
1598 kmem_free(kernel_map
, (vm_offset_t
) addr
, C_SEG_BUFSIZE
);
1603 vm_swap_get_total_space(void)
1605 uint64_t total_space
= 0;
1607 total_space
= (uint64_t)vm_swapfile_total_segs_alloced
* COMPRESSED_SWAP_CHUNK_SIZE
;
1613 vm_swap_get_used_space(void)
1615 uint64_t used_space
= 0;
1617 used_space
= (uint64_t)vm_swapfile_total_segs_used
* COMPRESSED_SWAP_CHUNK_SIZE
;
1623 vm_swap_get_free_space(void)
1625 return (vm_swap_get_total_space() - vm_swap_get_used_space());
1630 vm_swap_low_on_space(void)
1633 if (vm_num_swap_files
== 0 && vm_swapfile_can_be_created
== FALSE
)
1636 if (((vm_swapfile_total_segs_alloced
- vm_swapfile_total_segs_used
) < ((unsigned int)VM_SWAPFILE_HIWATER_SEGS
) / 8)) {
1638 if (vm_num_swap_files
== 0 && !SWAPPER_NEEDS_TO_UNTHROTTLE())
1641 if (vm_swapfile_last_failed_to_create_ts
>= vm_swapfile_last_successful_create_ts
)