summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2016-05-16 15:10:06 (GMT)
committerRichard Braun <rbraun@sceen.net>2016-05-16 15:17:41 (GMT)
commitb4d07d3c60449dde5c567aaeb2db0cd9f39547bd (patch)
tree607ec71c34bf1417bf1ac4c4c8e7c47d8857251d
parentbbcbebe456c921fc9494fec2bd1cbe1fa6696453 (diff)
Fix pageout deadlock
The pageout daemon uses small, internal, temporary objects to transport the data out to memory managers, which are expected to release the data once written out to backing store. Releasing this data is done with a vm_deallocate call. The problem with this is that vm_map is allowed to merge these objects, in which case vm_deallocate will only remove a reference instead of releasing the underlying pages, causing the pageout daemon to deadlock. This change makes the pageout daemon mark these objects so that they don't get merged. * vm/vm_object.c (vm_object_bootstrap): Update template. (vm_object_coalesce): Don't coalesce if an object is used for pageout. * vm/vm_object.h (struct vm_object): New `used_for_pageout` member. * vm/vm_pageout.c (vm_pageout_page): Mark new objects for pageout.
-rw-r--r--vm/vm_object.c2
-rw-r--r--vm/vm_object.h7
-rw-r--r--vm/vm_pageout.c1
3 files changed, 10 insertions, 0 deletions
diff --git a/vm/vm_object.c b/vm/vm_object.c
index bc30128..046b6c4 100644
--- a/vm/vm_object.c
+++ b/vm/vm_object.c
@@ -302,6 +302,7 @@ void vm_object_bootstrap(void)
vm_object_template.all_wanted = 0; /* all bits FALSE */
vm_object_template.paging_in_progress = 0;
+ vm_object_template.used_for_pageout = FALSE;
vm_object_template.can_persist = FALSE;
vm_object_template.cached = FALSE;
vm_object_template.internal = TRUE;
@@ -2742,6 +2743,7 @@ boolean_t vm_object_coalesce(
if ((prev_object->ref_count > 1) ||
prev_object->pager_created ||
+ prev_object->used_for_pageout ||
(prev_object->shadow != VM_OBJECT_NULL) ||
(prev_object->copy != VM_OBJECT_NULL) ||
(prev_object->paging_in_progress != 0)) {
diff --git a/vm/vm_object.h b/vm/vm_object.h
index eb8a0c2..e1dd0ba 100644
--- a/vm/vm_object.h
+++ b/vm/vm_object.h
@@ -113,6 +113,13 @@ struct vm_object {
* of these fields (i.e., don't
* collapse, destroy or terminate)
*/
+ /* boolean_t */ used_for_pageout:1,/* The object carries data sent to
+ * a memory manager, which signals
+ * it's done by releasing memory.
+ * This flag prevents coalescing so
+ * that unmapping memory immediately
+ * results in object termination.
+ */
/* boolean_t */ pager_created:1,/* Has pager ever been created? */
/* boolean_t */ pager_initialized:1,/* Are fields ready to use? */
/* boolean_t */ pager_ready:1, /* Will manager take requests? */
diff --git a/vm/vm_pageout.c b/vm/vm_pageout.c
index 72f96cb..f420804 100644
--- a/vm/vm_pageout.c
+++ b/vm/vm_pageout.c
@@ -461,6 +461,7 @@ vm_pageout_page(
* Allocate a new object into which we can put the page.
*/
new_object = vm_object_allocate(PAGE_SIZE);
+ new_object->used_for_pageout = TRUE;
/*
* Move the page into the new object.