X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/bd504ef0e0b883cdd7917b73b3574eb9ce669905..39236c6e673c41db228275375ab7fdb0f837b292:/osfmk/vm/default_freezer.c

diff --git a/osfmk/vm/default_freezer.c b/osfmk/vm/default_freezer.c
index c6e9c8ef6..b7127b39e 100644
--- a/osfmk/vm/default_freezer.c
+++ b/osfmk/vm/default_freezer.c
@@ -296,7 +296,8 @@ default_freezer_pack_page(
 	df_handle->dfh_compact_offset += PAGE_SIZE;
 }
 
-void
+
+kern_return_t
 default_freezer_unpack(
 		 default_freezer_handle_t df_handle)
 {
@@ -311,6 +312,7 @@ default_freezer_unpack(
 	default_freezer_memory_object_t		fo = NULL;
 	default_freezer_mapping_table_t 	freeze_table = NULL;
 	boolean_t				should_unlock_handle = FALSE;
+	kern_return_t				kr;
 
 	assert(df_handle);
 
@@ -326,11 +328,11 @@ default_freezer_unpack(
 	assert(compact_object->pager_ready);
 	
 	/* Bring the pages back in */
-	if (vm_object_pagein(compact_object) != KERN_SUCCESS) {
+	if ((kr = vm_object_pagein(compact_object)) != KERN_SUCCESS) {
 		if (should_unlock_handle) {
 			default_freezer_handle_unlock(df_handle);
 		}
-        	return;
+        	return (kr);
 	}
 
 	vm_object_lock(compact_object);
@@ -399,6 +401,7 @@ default_freezer_unpack(
 		df_handle->dfh_compact_offset = 0;
 		default_freezer_handle_unlock(df_handle);
 	}
+	return (KERN_SUCCESS);
 }
 
 void
@@ -517,6 +520,7 @@ df_memory_object_data_request(
 	memory_object_t pager = NULL;
 	kern_return_t kr = KERN_SUCCESS;
 	boolean_t	drop_object_ref = FALSE;
+	vm_page_t compact_page, dst_page;
 
 	default_freezer_memory_object_t fo = (default_freezer_memory_object_t)mem_obj;
 	default_freezer_handle_t	df_handle = NULL;
@@ -563,7 +567,7 @@ df_memory_object_data_request(
 		upl_t        upl;
 		unsigned int page_list_count = 0;
 
-		request_flags = UPL_NO_SYNC | UPL_RET_ONLY_ABSENT | UPL_SET_LITE;
+		request_flags = UPL_NO_SYNC | UPL_RET_ONLY_ABSENT | UPL_SET_LITE | UPL_SET_INTERNAL;
 		/*
 		 * Should we decide to activate USE_PRECIOUS (from default_pager_internal.h)
 		 * here, then the request_flags will need to add these to the ones above:
@@ -588,79 +592,86 @@ df_memory_object_data_request(
 
 		return KERN_SUCCESS;
 	}
+	vm_object_lock(compact_object);
 
 	assert(compact_object->alive);
 	assert(!compact_object->terminating);
-	assert(compact_object->pager_ready);
-
-	vm_object_lock(compact_object);
 
+	/*
+	 * note that the activity_in_progress could be non-zero, but
+	 * the pager has not yet been created since the activity_in_progress
+	 * count is bumped via vm_pageout_cluster, while the pager isn't created
+	 * until the pageout thread runs and starts to process the pages
+	 * placed on the I/O queue... once the processing of the compact object
+	 * proceeds to the point where it's placed the first page on the I/O
+	 * queue, we need to wait until the entire freeze operation has completed.
+	 */
 	vm_object_paging_wait(compact_object, THREAD_UNINT);
-	vm_object_paging_begin(compact_object);
 
-	compact_object->blocked_access = TRUE;
-	pager = (memory_object_t)compact_object->pager;
+	if (compact_object->pager_ready) {
+		vm_object_paging_begin(compact_object);
 
-	vm_object_unlock(compact_object);
+		compact_object->blocked_access = TRUE;
+		pager = (memory_object_t)compact_object->pager;
 
-	((vm_object_fault_info_t) fault_info)->io_sync = TRUE;
+		vm_object_unlock(compact_object);
 
-	/*
-	 * We have a reference on both the default_freezer
-	 * memory object handle and the compact object.
-	 */
-	kr = dp_memory_object_data_request(pager,
-					compact_offset,
-					length,
-					protection_required,
-					fault_info);
-	if (kr == KERN_SUCCESS){
+		((vm_object_fault_info_t) fault_info)->io_sync = TRUE;
 
-		vm_page_t compact_page = VM_PAGE_NULL, dst_page = VM_PAGE_NULL;
+		/*
+		 * We have a reference on both the default_freezer
+		 * memory object handle and the compact object.
+		 */
+		kr = dp_memory_object_data_request(pager,
+						   compact_offset,
+						   length,
+						   protection_required,
+						   fault_info);
+		if (kr != KERN_SUCCESS)
+			panic("%d: default_freezer TOC pointed us to default_pager incorrectly\n", kr);
 
 		vm_object_lock(compact_object);
 
 		compact_object->blocked_access = FALSE;
 		vm_object_paging_end(compact_object);
+	}
+	vm_object_lock(src_object);
 
-		vm_object_lock(src_object);
-
-		if ((compact_page = vm_page_lookup(compact_object, compact_offset)) != VM_PAGE_NULL){
+	if ((compact_page = vm_page_lookup(compact_object, compact_offset)) != VM_PAGE_NULL){
 			
-			dst_page = vm_page_lookup(src_object, offset - src_object->paging_offset);
+		dst_page = vm_page_lookup(src_object, offset - src_object->paging_offset);
 			
-			if (!dst_page->absent){
-				/*
-				 * Someone raced us here and unpacked
-				 * the object behind us.
-				 * So cleanup before we return.
-				 */
-				VM_PAGE_FREE(compact_page);
-			} else {
+		if (dst_page && !dst_page->absent){
+			/*
+			 * Someone raced us here and unpacked
+			 * the object behind us.
+			 * So cleanup before we return.
+			 */
+			VM_PAGE_FREE(compact_page);
+		} else {
+			if (dst_page != NULL) {
 				VM_PAGE_FREE(dst_page);
-				vm_page_rename(compact_page, src_object, offset - src_object->paging_offset, FALSE);
-				
-				if (default_freezer_mapping_update(fo->fo_df_handle->dfh_table,
-								mem_obj,
-								offset,
-								NULL,
-								TRUE) != KERN_SUCCESS) {
-					printf("Page for object: 0x%lx at offset: 0x%lx not found in table\n", (uintptr_t)src_object, (uintptr_t)offset);
-				}
+			}
+			vm_page_rename(compact_page, src_object, offset - src_object->paging_offset, FALSE);
 				
-				PAGE_WAKEUP_DONE(compact_page);
+			if (default_freezer_mapping_update(fo->fo_df_handle->dfh_table,
+							   mem_obj,
+							   offset,
+							   NULL,
+							   TRUE) != KERN_SUCCESS) {
+				printf("Page for object: 0x%lx at offset: 0x%lx not found in table\n", (uintptr_t)src_object, (uintptr_t)offset);
 			}
-		} else {
-			printf("%d: default_freezer: compact_object doesn't have the page for object 0x%lx at offset 0x%lx \n", kr, (uintptr_t)compact_object, (uintptr_t)compact_offset);
-			kr = KERN_SUCCESS;
+			
+			PAGE_WAKEUP_DONE(compact_page);
 		}
-		vm_object_unlock(src_object);
-		vm_object_unlock(compact_object);
-		vm_object_deallocate(compact_object);
 	} else {
-		panic("%d: default_freezer TOC pointed us to default_pager incorrectly\n", kr);
+		printf("%d: default_freezer: compact_object doesn't have the page for object 0x%lx at offset 0x%lx \n", kr, (uintptr_t)compact_object, (uintptr_t)compact_offset);
+		kr = KERN_SUCCESS;
 	}
-	
+	vm_object_unlock(src_object);
+	vm_object_unlock(compact_object);
+	vm_object_deallocate(compact_object);
+
 	return kr;
 }