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_bytes_used
== 0);
707 c_seg_switch_state(c_seg
, C_IS_EMPTY
, FALSE
);
708 lck_mtx_unlock_always(&c_seg
->c_lock
);
709 lck_mtx_unlock_always(c_list_lock
);
711 vm_swapout_found_empty
++;
715 c_seg
->c_busy_swapping
= 1;
717 lck_mtx_unlock_always(c_list_lock
);
719 addr
= (vm_offset_t
) c_seg
->c_store
.c_buffer
;
721 lck_mtx_unlock_always(&c_seg
->c_lock
);
723 #if CHECKSUM_THE_SWAP
724 c_seg
->cseg_hash
= hash_string((char*)addr
, (int)size
);
725 c_seg
->cseg_swap_size
= size
;
726 #endif /* CHECKSUM_THE_SWAP */
729 vm_swap_encrypt(c_seg
);
730 #endif /* ENCRYPTED_SWAP */
732 vm_swapout_thread_throttle_adjust();
734 kr
= vm_swap_put((vm_offset_t
) addr
, &f_offset
, size
, c_seg
);
736 PAGE_REPLACEMENT_DISALLOWED(TRUE
);
738 if (kr
== KERN_SUCCESS
) {
739 kernel_memory_depopulate(kernel_map
, (vm_offset_t
) addr
, size
, KMA_COMPRESSOR
);
741 lck_mtx_lock_spin_always(c_list_lock
);
742 lck_mtx_lock_spin_always(&c_seg
->c_lock
);
744 if (kr
== KERN_SUCCESS
) {
745 int new_state
= C_ON_SWAPPEDOUT_Q
;
746 boolean_t insert_head
= FALSE
;
748 if (hibernate_flushing
== TRUE
) {
749 if (c_seg
->c_generation_id
>= first_c_segment_to_warm_generation_id
&&
750 c_seg
->c_generation_id
<= last_c_segment_to_warm_generation_id
)
752 } else if (C_SEG_ONDISK_IS_SPARSE(c_seg
))
753 new_state
= C_ON_SWAPPEDOUTSPARSE_Q
;
755 c_seg_switch_state(c_seg
, new_state
, insert_head
);
757 c_seg
->c_store
.c_swap_handle
= f_offset
;
759 VM_STAT_INCR_BY(swapouts
, size
>> PAGE_SHIFT
);
761 if (c_seg
->c_bytes_used
)
762 OSAddAtomic64(-c_seg
->c_bytes_used
, &compressor_bytes_used
);
765 vm_swap_decrypt(c_seg
);
766 #endif /* ENCRYPTED_SWAP */
767 if (c_seg
->c_overage_swap
== TRUE
) {
768 c_seg
->c_overage_swap
= FALSE
;
769 c_overage_swapped_count
--;
771 c_seg_switch_state(c_seg
, C_ON_AGE_Q
, FALSE
);
773 lck_mtx_unlock_always(c_list_lock
);
775 c_seg
->c_busy_swapping
= 0;
776 C_SEG_WAKEUP_DONE(c_seg
);
777 lck_mtx_unlock_always(&c_seg
->c_lock
);
779 PAGE_REPLACEMENT_DISALLOWED(FALSE
);
781 vm_pageout_io_throttle();
783 if (c_swapout_count
== 0)
784 vm_swap_consider_defragmenting();
786 lck_mtx_lock_spin_always(c_list_lock
);
789 assert_wait((event_t
)&c_swapout_list_head
, THREAD_UNINT
);
791 lck_mtx_unlock_always(c_list_lock
);
793 thread_block((thread_continue_t
)vm_swapout_thread
);
799 vm_swap_create_file()
803 boolean_t swap_file_created
= FALSE
;
804 boolean_t swap_file_reuse
= FALSE
;
805 boolean_t swap_file_pin
= FALSE
;
806 struct swapfile
*swf
= NULL
;
809 * Any swapfile structure ready for re-use?
812 lck_mtx_lock(&vm_swap_data_lock
);
814 swf
= (struct swapfile
*) queue_first(&swf_global_queue
);
816 while (queue_end(&swf_global_queue
, (queue_entry_t
)swf
) == FALSE
) {
817 if (swf
->swp_flags
== SWAP_REUSE
) {
818 swap_file_reuse
= TRUE
;
821 swf
= (struct swapfile
*) queue_next(&swf
->swp_queue
);
824 lck_mtx_unlock(&vm_swap_data_lock
);
826 if (swap_file_reuse
== FALSE
) {
828 if (strlen(swapfilename
) == 0) {
830 * If no swapfile name has been set, we'll
831 * use the default name.
833 * Also, this function is only called from the swapfile management thread.
834 * So we don't need to worry about a race in checking/setting the name here.
837 strlcpy(swapfilename
, SWAP_FILE_NAME
, MAX_SWAPFILENAME_LEN
);
840 namelen
= (int)strlen(swapfilename
) + SWAPFILENAME_INDEX_LEN
+ 1;
842 swf
= (struct swapfile
*) kalloc(sizeof *swf
);
843 memset(swf
, 0, sizeof(*swf
));
845 swf
->swp_index
= vm_num_swap_files
+ 1;
846 swf
->swp_pathlen
= namelen
;
847 swf
->swp_path
= (char*)kalloc(swf
->swp_pathlen
);
849 memset(swf
->swp_path
, 0, namelen
);
851 snprintf(swf
->swp_path
, namelen
, "%s%d", swapfilename
, vm_num_swap_files
);
854 vm_swapfile_open(swf
->swp_path
, &swf
->swp_vp
);
856 if (swf
->swp_vp
== NULL
) {
857 if (swap_file_reuse
== FALSE
) {
858 kfree(swf
->swp_path
, swf
->swp_pathlen
);
859 kfree(swf
, sizeof *swf
);
863 vm_swapfile_can_be_created
= TRUE
;
865 size
= MAX_SWAP_FILE_SIZE
;
867 while (size
>= MIN_SWAP_FILE_SIZE
) {
869 swap_file_pin
= VM_SWAP_SHOULD_PIN(size
);
871 if (vm_swapfile_preallocate(swf
->swp_vp
, &size
, &swap_file_pin
) == 0) {
873 int num_bytes_for_bitmap
= 0;
875 swap_file_created
= TRUE
;
877 swf
->swp_size
= size
;
878 swf
->swp_nsegs
= (unsigned int) (size
/ COMPRESSED_SWAP_CHUNK_SIZE
);
879 swf
->swp_nseginuse
= 0;
880 swf
->swp_free_hint
= 0;
882 num_bytes_for_bitmap
= MAX((swf
->swp_nsegs
>> 3) , 1);
884 * Allocate a bitmap that describes the
885 * number of segments held by this swapfile.
887 swf
->swp_bitmap
= (uint8_t*)kalloc(num_bytes_for_bitmap
);
888 memset(swf
->swp_bitmap
, 0, num_bytes_for_bitmap
);
890 swf
->swp_csegs
= (c_segment_t
*) kalloc(swf
->swp_nsegs
* sizeof(c_segment_t
));
891 memset(swf
->swp_csegs
, 0, (swf
->swp_nsegs
* sizeof(c_segment_t
)));
894 * passing a NULL trim_list into vnode_trim_list
895 * will return ENOTSUP if trim isn't supported
898 if (vnode_trim_list(swf
->swp_vp
, NULL
, FALSE
) == 0)
899 swp_trim_supported
= TRUE
;
901 lck_mtx_lock(&vm_swap_data_lock
);
903 swf
->swp_flags
= SWAP_READY
;
905 if (swap_file_reuse
== FALSE
) {
906 queue_enter(&swf_global_queue
, swf
, struct swapfile
*, swp_queue
);
911 vm_swapfile_total_segs_alloced
+= swf
->swp_nsegs
;
913 if (swap_file_pin
== TRUE
) {
914 swf
->swp_flags
|= SWAP_PINNED
;
915 vm_swappin_avail
-= swf
->swp_size
;
918 lck_mtx_unlock(&vm_swap_data_lock
);
920 thread_wakeup((event_t
) &vm_num_swap_files
);
927 if (swap_file_created
== FALSE
) {
929 vm_swapfile_close((uint64_t)(swf
->swp_path
), swf
->swp_vp
);
933 if (swap_file_reuse
== FALSE
) {
934 kfree(swf
->swp_path
, swf
->swp_pathlen
);
935 kfree(swf
, sizeof *swf
);
938 return swap_file_created
;
943 vm_swap_get(vm_offset_t addr
, uint64_t f_offset
, uint64_t size
)
945 struct swapfile
*swf
= NULL
;
946 uint64_t file_offset
= 0;
953 lck_mtx_lock(&vm_swap_data_lock
);
955 swf
= vm_swapfile_for_handle(f_offset
);
957 if (swf
== NULL
|| ( !(swf
->swp_flags
& SWAP_READY
) && !(swf
->swp_flags
& SWAP_RECLAIM
))) {
963 lck_mtx_unlock(&vm_swap_data_lock
);
965 file_offset
= (f_offset
& SWAP_SLOT_MASK
);
966 retval
= vm_swapfile_io(swf
->swp_vp
, file_offset
, addr
, (int)(size
/ PAGE_SIZE_64
), SWAP_READ
);
969 VM_STAT_INCR_BY(swapins
, size
>> PAGE_SHIFT
);
971 vm_swap_get_failures
++;
974 * Free this slot in the swap structure.
976 vm_swap_free(f_offset
);
978 lck_mtx_lock(&vm_swap_data_lock
);
981 if ((swf
->swp_flags
& SWAP_WANTED
) && swf
->swp_io_count
== 0) {
983 swf
->swp_flags
&= ~SWAP_WANTED
;
984 thread_wakeup((event_t
) &swf
->swp_flags
);
987 lck_mtx_unlock(&vm_swap_data_lock
);
996 vm_swap_put(vm_offset_t addr
, uint64_t *f_offset
, uint64_t size
, c_segment_t c_seg
)
998 unsigned int segidx
= 0;
999 struct swapfile
*swf
= NULL
;
1000 uint64_t file_offset
= 0;
1001 uint64_t swapfile_index
= 0;
1002 unsigned int byte_for_segidx
= 0;
1003 unsigned int offset_within_byte
= 0;
1004 boolean_t swf_eligible
= FALSE
;
1005 boolean_t waiting
= FALSE
;
1006 boolean_t retried
= FALSE
;
1011 if (addr
== 0 || f_offset
== NULL
) {
1012 return KERN_FAILURE
;
1015 lck_mtx_lock(&vm_swap_data_lock
);
1017 swf
= (struct swapfile
*) queue_first(&swf_global_queue
);
1019 while(queue_end(&swf_global_queue
, (queue_entry_t
)swf
) == FALSE
) {
1021 segidx
= swf
->swp_free_hint
;
1023 swf_eligible
= (swf
->swp_flags
& SWAP_READY
) && (swf
->swp_nseginuse
< swf
->swp_nsegs
);
1027 while(segidx
< swf
->swp_nsegs
) {
1029 byte_for_segidx
= segidx
>> 3;
1030 offset_within_byte
= segidx
% 8;
1032 if ((swf
->swp_bitmap
)[byte_for_segidx
] & (1 << offset_within_byte
)) {
1037 (swf
->swp_bitmap
)[byte_for_segidx
] |= (1 << offset_within_byte
);
1039 file_offset
= segidx
* COMPRESSED_SWAP_CHUNK_SIZE
;
1040 swf
->swp_nseginuse
++;
1041 swf
->swp_io_count
++;
1042 swapfile_index
= swf
->swp_index
;
1044 vm_swapfile_total_segs_used
++;
1046 clock_get_system_nanotime(&sec
, &nsec
);
1048 if (VM_SWAP_SHOULD_CREATE(sec
) && !vm_swapfile_create_thread_running
)
1049 thread_wakeup((event_t
) &vm_swapfile_create_needed
);
1051 lck_mtx_unlock(&vm_swap_data_lock
);
1056 swf
= (struct swapfile
*) queue_next(&swf
->swp_queue
);
1058 assert(queue_end(&swf_global_queue
, (queue_entry_t
) swf
));
1061 * we've run out of swap segments, but may not
1062 * be in a position to immediately create a new swap
1063 * file if we've recently failed to create due to a lack
1064 * of free space in the root filesystem... we'll try
1065 * to kick that create off, but in any event we're going
1066 * to take a breather (up to 1 second) so that we're not caught in a tight
1067 * loop back in "vm_compressor_compact_and_swap" trying to stuff
1068 * segments into swap files only to have them immediately put back
1069 * on the c_age queue due to vm_swap_put failing.
1071 * if we're doing these puts due to a hibernation flush,
1072 * no need to block... setting hibernate_no_swapspace to TRUE,
1073 * will cause "vm_compressor_compact_and_swap" to immediately abort
1075 clock_get_system_nanotime(&sec
, &nsec
);
1077 if (VM_SWAP_SHOULD_CREATE(sec
) && !vm_swapfile_create_thread_running
)
1078 thread_wakeup((event_t
) &vm_swapfile_create_needed
);
1080 if (hibernate_flushing
== FALSE
|| VM_SWAP_SHOULD_CREATE(sec
)) {
1082 assert_wait_timeout((event_t
) &vm_num_swap_files
, THREAD_INTERRUPTIBLE
, 1000, 1000*NSEC_PER_USEC
);
1084 hibernate_no_swapspace
= TRUE
;
1086 lck_mtx_unlock(&vm_swap_data_lock
);
1088 if (waiting
== TRUE
) {
1089 thread_block(THREAD_CONTINUE_NULL
);
1091 if (retried
== FALSE
&& hibernate_flushing
== TRUE
) {
1096 vm_swap_put_failures
++;
1098 return KERN_FAILURE
;
1101 error
= vm_swapfile_io(swf
->swp_vp
, file_offset
, addr
, (int) (size
/ PAGE_SIZE_64
), SWAP_WRITE
);
1103 lck_mtx_lock(&vm_swap_data_lock
);
1105 swf
->swp_csegs
[segidx
] = c_seg
;
1107 swf
->swp_io_count
--;
1109 *f_offset
= (swapfile_index
<< SWAP_DEVICE_SHIFT
) | file_offset
;
1111 if ((swf
->swp_flags
& SWAP_WANTED
) && swf
->swp_io_count
== 0) {
1113 swf
->swp_flags
&= ~SWAP_WANTED
;
1114 thread_wakeup((event_t
) &swf
->swp_flags
);
1117 lck_mtx_unlock(&vm_swap_data_lock
);
1120 vm_swap_free(*f_offset
);
1122 vm_swap_put_failures
++;
1124 return KERN_FAILURE
;
1126 return KERN_SUCCESS
;
1132 vm_swap_free_now(struct swapfile
*swf
, uint64_t f_offset
)
1134 uint64_t file_offset
= 0;
1135 unsigned int segidx
= 0;
1138 if ((swf
->swp_flags
& SWAP_READY
) || (swf
->swp_flags
& SWAP_RECLAIM
)) {
1140 unsigned int byte_for_segidx
= 0;
1141 unsigned int offset_within_byte
= 0;
1143 file_offset
= (f_offset
& SWAP_SLOT_MASK
);
1144 segidx
= (unsigned int) (file_offset
/ COMPRESSED_SWAP_CHUNK_SIZE
);
1146 byte_for_segidx
= segidx
>> 3;
1147 offset_within_byte
= segidx
% 8;
1149 if ((swf
->swp_bitmap
)[byte_for_segidx
] & (1 << offset_within_byte
)) {
1151 (swf
->swp_bitmap
)[byte_for_segidx
] &= ~(1 << offset_within_byte
);
1153 swf
->swp_csegs
[segidx
] = NULL
;
1155 swf
->swp_nseginuse
--;
1156 vm_swapfile_total_segs_used
--;
1158 if (segidx
< swf
->swp_free_hint
) {
1159 swf
->swp_free_hint
= segidx
;
1162 if (VM_SWAP_SHOULD_RECLAIM() && !vm_swapfile_gc_thread_running
)
1163 thread_wakeup((event_t
) &vm_swapfile_gc_needed
);
1168 uint32_t vm_swap_free_now_count
= 0;
1169 uint32_t vm_swap_free_delayed_count
= 0;
1173 vm_swap_free(uint64_t f_offset
)
1175 struct swapfile
*swf
= NULL
;
1176 struct trim_list
*tl
= NULL
;
1180 if (swp_trim_supported
== TRUE
)
1181 tl
= kalloc(sizeof(struct trim_list
));
1183 lck_mtx_lock(&vm_swap_data_lock
);
1185 swf
= vm_swapfile_for_handle(f_offset
);
1187 if (swf
&& (swf
->swp_flags
& (SWAP_READY
| SWAP_RECLAIM
))) {
1189 if (swp_trim_supported
== FALSE
|| (swf
->swp_flags
& SWAP_RECLAIM
)) {
1191 * don't delay the free if the underlying disk doesn't support
1192 * trim, or we're in the midst of reclaiming this swap file since
1193 * we don't want to move segments that are technically free
1194 * but not yet handled by the delayed free mechanism
1196 vm_swap_free_now(swf
, f_offset
);
1198 vm_swap_free_now_count
++;
1201 tl
->tl_offset
= f_offset
& SWAP_SLOT_MASK
;
1202 tl
->tl_length
= COMPRESSED_SWAP_CHUNK_SIZE
;
1204 tl
->tl_next
= swf
->swp_delayed_trim_list_head
;
1205 swf
->swp_delayed_trim_list_head
= tl
;
1206 swf
->swp_delayed_trim_count
++;
1209 if (VM_SWAP_SHOULD_TRIM(swf
) && !vm_swapfile_create_thread_running
) {
1210 clock_get_system_nanotime(&sec
, &nsec
);
1212 if (sec
> dont_trim_until_ts
)
1213 thread_wakeup((event_t
) &vm_swapfile_create_needed
);
1215 vm_swap_free_delayed_count
++;
1218 lck_mtx_unlock(&vm_swap_data_lock
);
1221 kfree(tl
, sizeof(struct trim_list
));
1226 vm_swap_wait_on_trim_handling_in_progress()
1228 while (delayed_trim_handling_in_progress
== TRUE
) {
1230 assert_wait((event_t
) &delayed_trim_handling_in_progress
, THREAD_UNINT
);
1231 lck_mtx_unlock(&vm_swap_data_lock
);
1233 thread_block(THREAD_CONTINUE_NULL
);
1235 lck_mtx_lock(&vm_swap_data_lock
);
1241 vm_swap_handle_delayed_trims(boolean_t force_now
)
1243 struct swapfile
*swf
= NULL
;
1246 * serialize the race between us and vm_swap_reclaim...
1247 * if vm_swap_reclaim wins it will turn off SWAP_READY
1248 * on the victim it has chosen... we can just skip over
1249 * that file since vm_swap_reclaim will first process
1250 * all of the delayed trims associated with it
1252 lck_mtx_lock(&vm_swap_data_lock
);
1254 delayed_trim_handling_in_progress
= TRUE
;
1256 lck_mtx_unlock(&vm_swap_data_lock
);
1259 * no need to hold the lock to walk the swf list since
1260 * vm_swap_create (the only place where we add to this list)
1261 * is run on the same thread as this function
1262 * and vm_swap_reclaim doesn't remove items from this list
1263 * instead marking them with SWAP_REUSE for future re-use
1265 swf
= (struct swapfile
*) queue_first(&swf_global_queue
);
1267 while (queue_end(&swf_global_queue
, (queue_entry_t
)swf
) == FALSE
) {
1269 if ((swf
->swp_flags
& SWAP_READY
) && (force_now
== TRUE
|| VM_SWAP_SHOULD_TRIM(swf
))) {
1271 assert(!(swf
->swp_flags
& SWAP_RECLAIM
));
1272 vm_swap_do_delayed_trim(swf
);
1274 swf
= (struct swapfile
*) queue_next(&swf
->swp_queue
);
1276 lck_mtx_lock(&vm_swap_data_lock
);
1278 delayed_trim_handling_in_progress
= FALSE
;
1279 thread_wakeup((event_t
) &delayed_trim_handling_in_progress
);
1281 if (VM_SWAP_SHOULD_RECLAIM() && !vm_swapfile_gc_thread_running
)
1282 thread_wakeup((event_t
) &vm_swapfile_gc_needed
);
1284 lck_mtx_unlock(&vm_swap_data_lock
);
1289 vm_swap_do_delayed_trim(struct swapfile
*swf
)
1291 struct trim_list
*tl
, *tl_head
;
1293 lck_mtx_lock(&vm_swap_data_lock
);
1295 tl_head
= swf
->swp_delayed_trim_list_head
;
1296 swf
->swp_delayed_trim_list_head
= NULL
;
1297 swf
->swp_delayed_trim_count
= 0;
1299 lck_mtx_unlock(&vm_swap_data_lock
);
1301 vnode_trim_list(swf
->swp_vp
, tl_head
, TRUE
);
1303 while ((tl
= tl_head
) != NULL
) {
1304 unsigned int segidx
= 0;
1305 unsigned int byte_for_segidx
= 0;
1306 unsigned int offset_within_byte
= 0;
1308 lck_mtx_lock(&vm_swap_data_lock
);
1310 segidx
= (unsigned int) (tl
->tl_offset
/ COMPRESSED_SWAP_CHUNK_SIZE
);
1312 byte_for_segidx
= segidx
>> 3;
1313 offset_within_byte
= segidx
% 8;
1315 if ((swf
->swp_bitmap
)[byte_for_segidx
] & (1 << offset_within_byte
)) {
1317 (swf
->swp_bitmap
)[byte_for_segidx
] &= ~(1 << offset_within_byte
);
1319 swf
->swp_csegs
[segidx
] = NULL
;
1321 swf
->swp_nseginuse
--;
1322 vm_swapfile_total_segs_used
--;
1324 if (segidx
< swf
->swp_free_hint
) {
1325 swf
->swp_free_hint
= segidx
;
1328 lck_mtx_unlock(&vm_swap_data_lock
);
1330 tl_head
= tl
->tl_next
;
1332 kfree(tl
, sizeof(struct trim_list
));
1343 int vm_swap_reclaim_yielded
= 0;
1346 vm_swap_reclaim(void)
1348 vm_offset_t addr
= 0;
1349 unsigned int segidx
= 0;
1350 uint64_t f_offset
= 0;
1351 struct swapfile
*swf
= NULL
;
1352 struct swapfile
*smallest_swf
= NULL
;
1353 unsigned int min_nsegs
= 0;
1354 unsigned int byte_for_segidx
= 0;
1355 unsigned int offset_within_byte
= 0;
1356 uint32_t c_size
= 0;
1358 c_segment_t c_seg
= NULL
;
1360 if (kernel_memory_allocate(kernel_map
, (vm_offset_t
*)(&addr
), C_SEG_BUFSIZE
, 0, KMA_KOBJECT
, VM_KERN_MEMORY_COMPRESSOR
) != KERN_SUCCESS
) {
1361 panic("vm_swap_reclaim: kernel_memory_allocate failed\n");
1364 lck_mtx_lock(&vm_swap_data_lock
);
1367 * if we're running the swapfile list looking for
1368 * candidates with delayed trims, we need to
1369 * wait before making our decision concerning
1370 * the swapfile we want to reclaim
1372 vm_swap_wait_on_trim_handling_in_progress();
1375 * from here until we knock down the SWAP_READY bit,
1376 * we need to remain behind the vm_swap_data_lock...
1377 * once that bit has been turned off, "vm_swap_handle_delayed_trims"
1378 * will not consider this swapfile for processing
1380 swf
= (struct swapfile
*) queue_first(&swf_global_queue
);
1381 min_nsegs
= MAX_SWAP_FILE_SIZE
/ COMPRESSED_SWAP_CHUNK_SIZE
;
1382 smallest_swf
= NULL
;
1384 while (queue_end(&swf_global_queue
, (queue_entry_t
)swf
) == FALSE
) {
1386 if ((swf
->swp_flags
& SWAP_READY
) && (swf
->swp_nseginuse
<= min_nsegs
)) {
1389 min_nsegs
= swf
->swp_nseginuse
;
1391 swf
= (struct swapfile
*) queue_next(&swf
->swp_queue
);
1394 if (smallest_swf
== NULL
)
1400 swf
->swp_flags
&= ~SWAP_READY
;
1401 swf
->swp_flags
|= SWAP_RECLAIM
;
1403 if (swf
->swp_delayed_trim_count
) {
1405 lck_mtx_unlock(&vm_swap_data_lock
);
1407 vm_swap_do_delayed_trim(swf
);
1409 lck_mtx_lock(&vm_swap_data_lock
);
1413 while (segidx
< swf
->swp_nsegs
) {
1417 * Wait for outgoing I/Os.
1419 while (swf
->swp_io_count
) {
1421 swf
->swp_flags
|= SWAP_WANTED
;
1423 assert_wait((event_t
) &swf
->swp_flags
, THREAD_UNINT
);
1424 lck_mtx_unlock(&vm_swap_data_lock
);
1426 thread_block(THREAD_CONTINUE_NULL
);
1428 lck_mtx_lock(&vm_swap_data_lock
);
1430 if (compressor_store_stop_compaction
== TRUE
|| VM_SWAP_SHOULD_ABORT_RECLAIM() || VM_SWAP_BUSY()) {
1431 vm_swap_reclaim_yielded
++;
1435 byte_for_segidx
= segidx
>> 3;
1436 offset_within_byte
= segidx
% 8;
1438 if (((swf
->swp_bitmap
)[byte_for_segidx
] & (1 << offset_within_byte
)) == 0) {
1444 c_seg
= swf
->swp_csegs
[segidx
];
1447 lck_mtx_lock_spin_always(&c_seg
->c_lock
);
1449 if (c_seg
->c_busy
) {
1451 * a swapped out c_segment in the process of being freed will remain in the
1452 * busy state until after the vm_swap_free is called on it... vm_swap_free
1453 * takes the vm_swap_data_lock, so can't change the swap state until after
1454 * we drop the vm_swap_data_lock... once we do, vm_swap_free will complete
1455 * which will allow c_seg_free_locked to clear busy and wake up this thread...
1456 * at that point, we re-look up the swap state which will now indicate that
1457 * this c_segment no longer exists.
1459 c_seg
->c_wanted
= 1;
1461 assert_wait((event_t
) (c_seg
), THREAD_UNINT
);
1462 lck_mtx_unlock_always(&c_seg
->c_lock
);
1464 lck_mtx_unlock(&vm_swap_data_lock
);
1466 thread_block(THREAD_CONTINUE_NULL
);
1468 lck_mtx_lock(&vm_swap_data_lock
);
1470 goto ReTry_for_cseg
;
1472 (swf
->swp_bitmap
)[byte_for_segidx
] &= ~(1 << offset_within_byte
);
1474 f_offset
= segidx
* COMPRESSED_SWAP_CHUNK_SIZE
;
1476 assert(c_seg
== swf
->swp_csegs
[segidx
]);
1477 swf
->swp_csegs
[segidx
] = NULL
;
1478 swf
->swp_nseginuse
--;
1480 vm_swapfile_total_segs_used
--;
1482 lck_mtx_unlock(&vm_swap_data_lock
);
1484 assert(C_SEG_IS_ONDISK(c_seg
));
1487 c_seg
->c_busy_swapping
= 1;
1488 #if !CHECKSUM_THE_SWAP
1489 c_seg_trim_tail(c_seg
);
1491 c_size
= round_page_32(C_SEG_OFFSET_TO_BYTES(c_seg
->c_populated_offset
));
1493 assert(c_size
<= C_SEG_BUFSIZE
&& c_size
);
1495 lck_mtx_unlock_always(&c_seg
->c_lock
);
1497 if (vm_swapfile_io(swf
->swp_vp
, f_offset
, addr
, (int)(c_size
/ PAGE_SIZE_64
), SWAP_READ
)) {
1500 * reading the data back in failed, so convert c_seg
1501 * to a swapped in c_segment that contains no data
1503 c_seg_swapin_requeue(c_seg
, FALSE
);
1505 * returns with c_busy_swapping cleared
1508 vm_swap_get_failures
++;
1509 goto swap_io_failed
;
1511 VM_STAT_INCR_BY(swapins
, c_size
>> PAGE_SHIFT
);
1513 if (vm_swap_put(addr
, &f_offset
, c_size
, c_seg
)) {
1514 vm_offset_t c_buffer
;
1517 * the put failed, so convert c_seg to a fully swapped in c_segment
1520 c_buffer
= (vm_offset_t
)C_SEG_BUFFER_ADDRESS(c_seg
->c_mysegno
);
1522 kernel_memory_populate(kernel_map
, c_buffer
, c_size
, KMA_COMPRESSOR
, VM_KERN_MEMORY_COMPRESSOR
);
1524 memcpy((char *)c_buffer
, (char *)addr
, c_size
);
1526 c_seg
->c_store
.c_buffer
= (int32_t *)c_buffer
;
1528 vm_swap_decrypt(c_seg
);
1529 #endif /* ENCRYPTED_SWAP */
1530 c_seg_swapin_requeue(c_seg
, TRUE
);
1532 * returns with c_busy_swapping cleared
1534 OSAddAtomic64(c_seg
->c_bytes_used
, &compressor_bytes_used
);
1536 goto swap_io_failed
;
1538 VM_STAT_INCR_BY(swapouts
, c_size
>> PAGE_SHIFT
);
1540 lck_mtx_lock_spin_always(&c_seg
->c_lock
);
1542 assert(C_SEG_IS_ONDISK(c_seg
));
1544 * The c_seg will now know about the new location on disk.
1546 c_seg
->c_store
.c_swap_handle
= f_offset
;
1547 c_seg
->c_busy_swapping
= 0;
1549 C_SEG_WAKEUP_DONE(c_seg
);
1551 lck_mtx_unlock_always(&c_seg
->c_lock
);
1552 lck_mtx_lock(&vm_swap_data_lock
);
1555 if (swf
->swp_nseginuse
) {
1557 swf
->swp_flags
&= ~SWAP_RECLAIM
;
1558 swf
->swp_flags
|= SWAP_READY
;
1563 * We don't remove this inactive swf from the queue.
1564 * That way, we can re-use it when needed again and
1565 * preserve the namespace. The delayed_trim processing
1566 * is also dependent on us not removing swfs from the queue.
1568 //queue_remove(&swf_global_queue, swf, struct swapfile*, swp_queue);
1570 vm_num_swap_files
--;
1572 vm_swapfile_total_segs_alloced
-= swf
->swp_nsegs
;
1574 lck_mtx_unlock(&vm_swap_data_lock
);
1576 vm_swapfile_close((uint64_t)(swf
->swp_path
), swf
->swp_vp
);
1578 kfree(swf
->swp_csegs
, swf
->swp_nsegs
* sizeof(c_segment_t
));
1579 kfree(swf
->swp_bitmap
, MAX((swf
->swp_nsegs
>> 3), 1));
1581 lck_mtx_lock(&vm_swap_data_lock
);
1583 if (swf
->swp_flags
& SWAP_PINNED
) {
1584 vm_swappin_avail
+= swf
->swp_size
;
1589 swf
->swp_free_hint
= 0;
1591 swf
->swp_flags
= SWAP_REUSE
;
1594 thread_wakeup((event_t
) &swf
->swp_flags
);
1595 lck_mtx_unlock(&vm_swap_data_lock
);
1597 kmem_free(kernel_map
, (vm_offset_t
) addr
, C_SEG_BUFSIZE
);
1602 vm_swap_get_total_space(void)
1604 uint64_t total_space
= 0;
1606 total_space
= (uint64_t)vm_swapfile_total_segs_alloced
* COMPRESSED_SWAP_CHUNK_SIZE
;
1612 vm_swap_get_used_space(void)
1614 uint64_t used_space
= 0;
1616 used_space
= (uint64_t)vm_swapfile_total_segs_used
* COMPRESSED_SWAP_CHUNK_SIZE
;
1622 vm_swap_get_free_space(void)
1624 return (vm_swap_get_total_space() - vm_swap_get_used_space());
1629 vm_swap_low_on_space(void)
1632 if (vm_num_swap_files
== 0 && vm_swapfile_can_be_created
== FALSE
)
1635 if (((vm_swapfile_total_segs_alloced
- vm_swapfile_total_segs_used
) < ((unsigned int)VM_SWAPFILE_HIWATER_SEGS
) / 8)) {
1637 if (vm_num_swap_files
== 0 && !SWAPPER_NEEDS_TO_UNTHROTTLE())
1640 if (vm_swapfile_last_failed_to_create_ts
>= vm_swapfile_last_successful_create_ts
)