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:
parent
c9aaa09a9e
commit
bc66f23e16
@ -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)))
|
||||
|
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user