Place VM objects on the object list when created and never remove them.
This is ok since objects come from a NOFREE zone and allows objects to be locked while traversing the object list without triggering a LOR. Ensure that objects on the list are marked DEAD while free or stillborn, and that they have a refcount of zero. This required updating most of the pagers to explicitly mark an object as dead when deallocating it. (Only the vnode pager did this previously.) Differential Revision: https://reviews.freebsd.org/D2423 Reviewed by: alc, kib (earlier version) MFC after: 2 weeks Sponsored by: Norse Corp, Inc.
This commit is contained in:
parent
4a3690dfa1
commit
e735691b61
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=282660
@ -113,6 +113,7 @@ default_pager_dealloc(object)
|
||||
/*
|
||||
* OBJT_DEFAULT objects have no special resources allocated to them.
|
||||
*/
|
||||
object->type = OBJT_DEAD;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -254,6 +254,8 @@ dev_pager_dealloc(object)
|
||||
!= NULL)
|
||||
dev_pager_free_page(object, m);
|
||||
}
|
||||
object->handle = NULL;
|
||||
object->type = OBJT_DEAD;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -131,6 +131,8 @@ phys_pager_dealloc(vm_object_t object)
|
||||
mtx_unlock(&phys_pager_mtx);
|
||||
VM_OBJECT_WLOCK(object);
|
||||
}
|
||||
object->handle = NULL;
|
||||
object->type = OBJT_DEAD;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -130,6 +130,8 @@ sg_pager_dealloc(vm_object_t object)
|
||||
|
||||
sg = object->handle;
|
||||
sglist_free(sg);
|
||||
object->handle = NULL;
|
||||
object->type = OBJT_DEAD;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -697,6 +697,8 @@ swap_pager_dealloc(vm_object_t object)
|
||||
* if paging is still in progress on some objects.
|
||||
*/
|
||||
swp_pager_meta_free_all(object);
|
||||
object->handle = NULL;
|
||||
object->type = OBJT_DEAD;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
@ -111,14 +111,7 @@ vmtotal(SYSCTL_HANDLER_ARGS)
|
||||
*/
|
||||
mtx_lock(&vm_object_list_mtx);
|
||||
TAILQ_FOREACH(object, &vm_object_list, object_list) {
|
||||
if (!VM_OBJECT_TRYWLOCK(object)) {
|
||||
/*
|
||||
* Avoid a lock-order reversal. Consequently,
|
||||
* the reported number of active pages may be
|
||||
* greater than the actual number.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
VM_OBJECT_WLOCK(object);
|
||||
vm_object_clear_flag(object, OBJ_ACTIVE);
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
}
|
||||
@ -196,10 +189,9 @@ vmtotal(SYSCTL_HANDLER_ARGS)
|
||||
mtx_lock(&vm_object_list_mtx);
|
||||
TAILQ_FOREACH(object, &vm_object_list, object_list) {
|
||||
/*
|
||||
* Perform unsynchronized reads on the object to avoid
|
||||
* a lock-order reversal. In this case, the lack of
|
||||
* synchronization should not impair the accuracy of
|
||||
* the reported statistics.
|
||||
* Perform unsynchronized reads on the object. In
|
||||
* this case, the lack of synchronization should not
|
||||
* impair the accuracy of the reported statistics.
|
||||
*/
|
||||
if ((object->flags & OBJ_FICTITIOUS) != 0) {
|
||||
/*
|
||||
|
@ -166,6 +166,8 @@ vm_object_zdtor(void *mem, int size, void *arg)
|
||||
vm_object_t object;
|
||||
|
||||
object = (vm_object_t)mem;
|
||||
KASSERT(object->ref_count == 0,
|
||||
("object %p ref_count = %d", object, object->ref_count));
|
||||
KASSERT(TAILQ_EMPTY(&object->memq),
|
||||
("object %p has resident pages in its memq", object));
|
||||
KASSERT(vm_radix_is_empty(&object->rtree),
|
||||
@ -187,6 +189,9 @@ vm_object_zdtor(void *mem, int size, void *arg)
|
||||
KASSERT(object->shadow_count == 0,
|
||||
("object %p shadow_count = %d",
|
||||
object, object->shadow_count));
|
||||
KASSERT(object->type == OBJT_DEAD,
|
||||
("object %p has non-dead type %d",
|
||||
object, object->type));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -199,6 +204,8 @@ vm_object_zinit(void *mem, int size, int flags)
|
||||
rw_init_flags(&object->lock, "vm object", RW_DUPOK | RW_NEW);
|
||||
|
||||
/* These are true for any object that has been freed */
|
||||
object->type = OBJT_DEAD;
|
||||
object->ref_count = 0;
|
||||
object->rtree.rt_root = 0;
|
||||
object->rtree.rt_flags = 0;
|
||||
object->paging_in_progress = 0;
|
||||
@ -206,6 +213,10 @@ vm_object_zinit(void *mem, int size, int flags)
|
||||
object->shadow_count = 0;
|
||||
object->cache.rt_root = 0;
|
||||
object->cache.rt_flags = 0;
|
||||
|
||||
mtx_lock(&vm_object_list_mtx);
|
||||
TAILQ_INSERT_TAIL(&vm_object_list, object, object_list);
|
||||
mtx_unlock(&vm_object_list_mtx);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -252,10 +263,6 @@ _vm_object_allocate(objtype_t type, vm_pindex_t size, vm_object_t object)
|
||||
#if VM_NRESERVLEVEL > 0
|
||||
LIST_INIT(&object->rvq);
|
||||
#endif
|
||||
|
||||
mtx_lock(&vm_object_list_mtx);
|
||||
TAILQ_INSERT_TAIL(&vm_object_list, object, object_list);
|
||||
mtx_unlock(&vm_object_list_mtx);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -670,20 +677,10 @@ void
|
||||
vm_object_destroy(vm_object_t object)
|
||||
{
|
||||
|
||||
/*
|
||||
* Remove the object from the global object list.
|
||||
*/
|
||||
mtx_lock(&vm_object_list_mtx);
|
||||
TAILQ_REMOVE(&vm_object_list, object, object_list);
|
||||
mtx_unlock(&vm_object_list_mtx);
|
||||
|
||||
/*
|
||||
* Release the allocation charge.
|
||||
*/
|
||||
if (object->cred != NULL) {
|
||||
KASSERT(object->type == OBJT_DEFAULT ||
|
||||
object->type == OBJT_SWAP,
|
||||
("%s: non-swap obj %p has cred", __func__, object));
|
||||
swap_release_by_cred(object->charge, object->cred);
|
||||
object->charge = 0;
|
||||
crfree(object->cred);
|
||||
@ -788,6 +785,10 @@ vm_object_terminate(vm_object_t object)
|
||||
if (__predict_false(!vm_object_cache_is_empty(object)))
|
||||
vm_page_cache_free(object, 0, 0);
|
||||
|
||||
KASSERT(object->cred == NULL || object->type == OBJT_DEFAULT ||
|
||||
object->type == OBJT_SWAP,
|
||||
("%s: non-swap obj %p has cred", __func__, object));
|
||||
|
||||
/*
|
||||
* Let the pager know object is dead.
|
||||
*/
|
||||
@ -1803,6 +1804,8 @@ vm_object_collapse(vm_object_t object)
|
||||
KASSERT(backing_object->ref_count == 1, (
|
||||
"backing_object %p was somehow re-referenced during collapse!",
|
||||
backing_object));
|
||||
backing_object->type = OBJT_DEAD;
|
||||
backing_object->ref_count = 0;
|
||||
VM_OBJECT_WUNLOCK(backing_object);
|
||||
vm_object_destroy(backing_object);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user