From cab23fb54d10843158e874d87dd3725ddbb2b4db Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Mon, 26 Jun 2023 14:26:54 +0300 Subject: vm: Eagerly release deallocated pages If a deallocated VM map entry refers to an object that only has a single reference and doesn't have a pager port, we can eagerly release any physical pages that were contained in the deallocated range. This is not a 100% solution: it is still possible to "leak" physical pages that can never appear in virtual memory again by creating several references to a memory object (perhaps by forking a VM map with VM_INHERIT_SHARE) and deallocating the pages from all the maps referring to the object. That being said, it should help to release the pages in the common case sooner. Message-Id: <20230626112656.435622-6-bugaevc@gmail.com> --- vm/vm_map.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/vm/vm_map.c b/vm/vm_map.c index a708b7eb..62fb87b9 100644 --- a/vm/vm_map.c +++ b/vm/vm_map.c @@ -1877,11 +1877,13 @@ void vm_map_entry_delete( vm_map_entry_t entry) { vm_offset_t s, e; + vm_size_t size; vm_object_t object; extern vm_object_t kernel_object; s = entry->vme_start; e = entry->vme_end; + size = e - s; /*Check if projected buffer*/ if (map != kernel_map && entry->projected_on != 0) { @@ -1920,15 +1922,29 @@ void vm_map_entry_delete( if (object == kernel_object) { vm_object_lock(object); vm_object_page_remove(object, entry->offset, - entry->offset + (e - s)); + entry->offset + size); vm_object_unlock(object); } else if (entry->is_shared) { vm_object_pmap_remove(object, entry->offset, - entry->offset + (e - s)); - } - else { + entry->offset + size); + } else { pmap_remove(map->pmap, s, e); + /* + * If this object has no pager and our + * reference to the object is the only + * one, we can release the deleted pages + * now. + */ + vm_object_lock(object); + if ((!object->pager_created) && + (object->ref_count == 1) && + (object->paging_in_progress == 0)) { + vm_object_page_remove(object, + entry->offset, + entry->offset + size); + } + vm_object_unlock(object); } } @@ -1943,7 +1959,7 @@ void vm_map_entry_delete( vm_object_deallocate(entry->object.vm_object); vm_map_entry_unlink(map, entry); - map->size -= e - s; + map->size -= size; vm_map_entry_dispose(map, entry); } -- cgit v1.2.3