1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-10-18 02:19:39 +00:00

Add OBJ_PG_DTOR flag to VM object.

Setting this flag allows us to skip pages removal from VM object queue
during object termination and to leave that for cdev_pg_dtor function.

Move pages removal code to separate function vm_object_terminate_pages()
as comments does not survive indentation.

This will be required for Intel SGX support where we will have to remove
pages from VM object manually.

Reviewed by:	kib, alc
Sponsored by:	DARPA, AFRL
Differential Revision:	https://reviews.freebsd.org/D11688
This commit is contained in:
Ruslan Bukin 2017-08-16 08:49:11 +00:00
parent 1f1c4ea123
commit 7bbdb843b6
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=322571
2 changed files with 51 additions and 36 deletions

View File

@ -693,6 +693,54 @@ vm_object_destroy(vm_object_t object)
uma_zfree(obj_zone, object);
}
/*
* vm_object_terminate_pages removes any remaining pageable pages
* from the object and resets the object to an empty state.
*/
static void
vm_object_terminate_pages(vm_object_t object)
{
vm_page_t p, p_next;
VM_OBJECT_ASSERT_WLOCKED(object);
/*
* Free any remaining pageable pages. This also removes them from the
* paging queues. However, don't free wired pages, just remove them
* from the object. Rather than incrementally removing each page from
* the object, the page and object are reset to any empty state.
*/
TAILQ_FOREACH_SAFE(p, &object->memq, listq, p_next) {
vm_page_assert_unbusied(p);
vm_page_lock(p);
/*
* Optimize the page's removal from the object by resetting
* its "object" field. Specifically, if the page is not
* wired, then the effect of this assignment is that
* vm_page_free()'s call to vm_page_remove() will return
* immediately without modifying the page or the object.
*/
p->object = NULL;
if (p->wire_count == 0) {
vm_page_free(p);
VM_CNT_INC(v_pfree);
}
vm_page_unlock(p);
}
/*
* If the object contained any pages, then reset it to an empty state.
* None of the object's fields, including "resident_page_count", were
* modified by the preceding loop.
*/
if (object->resident_page_count != 0) {
vm_radix_reclaim_allnodes(&object->rtree);
TAILQ_INIT(&object->memq);
object->resident_page_count = 0;
if (object->type == OBJT_VNODE)
vdrop(object->handle);
}
}
/*
* vm_object_terminate actually destroys the specified object, freeing
* up all previously used resources.
@ -703,7 +751,6 @@ vm_object_destroy(vm_object_t object)
void
vm_object_terminate(vm_object_t object)
{
vm_page_t p, p_next;
VM_OBJECT_ASSERT_WLOCKED(object);
@ -746,41 +793,8 @@ vm_object_terminate(vm_object_t object)
("vm_object_terminate: object with references, ref_count=%d",
object->ref_count));
/*
* Free any remaining pageable pages. This also removes them from the
* paging queues. However, don't free wired pages, just remove them
* from the object. Rather than incrementally removing each page from
* the object, the page and object are reset to any empty state.
*/
TAILQ_FOREACH_SAFE(p, &object->memq, listq, p_next) {
vm_page_assert_unbusied(p);
vm_page_lock(p);
/*
* Optimize the page's removal from the object by resetting
* its "object" field. Specifically, if the page is not
* wired, then the effect of this assignment is that
* vm_page_free()'s call to vm_page_remove() will return
* immediately without modifying the page or the object.
*/
p->object = NULL;
if (p->wire_count == 0) {
vm_page_free(p);
VM_CNT_INC(v_pfree);
}
vm_page_unlock(p);
}
/*
* If the object contained any pages, then reset it to an empty state.
* None of the object's fields, including "resident_page_count", were
* modified by the preceding loop.
*/
if (object->resident_page_count != 0) {
vm_radix_reclaim_allnodes(&object->rtree);
TAILQ_INIT(&object->memq);
object->resident_page_count = 0;
if (object->type == OBJT_VNODE)
vdrop(object->handle);
}
if ((object->flags & OBJ_PG_DTOR) == 0)
vm_object_terminate_pages(object);
#if VM_NRESERVLEVEL > 0
if (__predict_false(!LIST_EMPTY(&object->rvq)))

View File

@ -175,6 +175,7 @@ struct vm_object {
#define OBJ_NOSPLIT 0x0010 /* dont split this object */
#define OBJ_UMTXDEAD 0x0020 /* umtx pshared was terminated */
#define OBJ_PIPWNT 0x0040 /* paging in progress wanted */
#define OBJ_PG_DTOR 0x0080 /* dont reset object, leave that for dtor */
#define OBJ_MIGHTBEDIRTY 0x0100 /* object might be dirty, only for vnode */
#define OBJ_TMPFS_NODE 0x0200 /* object belongs to tmpfs VREG node */
#define OBJ_TMPFS_DIRTY 0x0400 /* dirty tmpfs obj */