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
@ -113,6 +113,7 @@ default_pager_dealloc(object)
|
|||||||
/*
|
/*
|
||||||
* OBJT_DEFAULT objects have no special resources allocated to them.
|
* OBJT_DEFAULT objects have no special resources allocated to them.
|
||||||
*/
|
*/
|
||||||
|
object->type = OBJT_DEAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -254,6 +254,8 @@ dev_pager_dealloc(object)
|
|||||||
!= NULL)
|
!= NULL)
|
||||||
dev_pager_free_page(object, m);
|
dev_pager_free_page(object, m);
|
||||||
}
|
}
|
||||||
|
object->handle = NULL;
|
||||||
|
object->type = OBJT_DEAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -131,6 +131,8 @@ phys_pager_dealloc(vm_object_t object)
|
|||||||
mtx_unlock(&phys_pager_mtx);
|
mtx_unlock(&phys_pager_mtx);
|
||||||
VM_OBJECT_WLOCK(object);
|
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;
|
sg = object->handle;
|
||||||
sglist_free(sg);
|
sglist_free(sg);
|
||||||
|
object->handle = NULL;
|
||||||
|
object->type = OBJT_DEAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -697,6 +697,8 @@ swap_pager_dealloc(vm_object_t object)
|
|||||||
* if paging is still in progress on some objects.
|
* if paging is still in progress on some objects.
|
||||||
*/
|
*/
|
||||||
swp_pager_meta_free_all(object);
|
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);
|
mtx_lock(&vm_object_list_mtx);
|
||||||
TAILQ_FOREACH(object, &vm_object_list, object_list) {
|
TAILQ_FOREACH(object, &vm_object_list, object_list) {
|
||||||
if (!VM_OBJECT_TRYWLOCK(object)) {
|
VM_OBJECT_WLOCK(object);
|
||||||
/*
|
|
||||||
* Avoid a lock-order reversal. Consequently,
|
|
||||||
* the reported number of active pages may be
|
|
||||||
* greater than the actual number.
|
|
||||||
*/
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
vm_object_clear_flag(object, OBJ_ACTIVE);
|
vm_object_clear_flag(object, OBJ_ACTIVE);
|
||||||
VM_OBJECT_WUNLOCK(object);
|
VM_OBJECT_WUNLOCK(object);
|
||||||
}
|
}
|
||||||
@ -196,10 +189,9 @@ vmtotal(SYSCTL_HANDLER_ARGS)
|
|||||||
mtx_lock(&vm_object_list_mtx);
|
mtx_lock(&vm_object_list_mtx);
|
||||||
TAILQ_FOREACH(object, &vm_object_list, object_list) {
|
TAILQ_FOREACH(object, &vm_object_list, object_list) {
|
||||||
/*
|
/*
|
||||||
* Perform unsynchronized reads on the object to avoid
|
* Perform unsynchronized reads on the object. In
|
||||||
* a lock-order reversal. In this case, the lack of
|
* this case, the lack of synchronization should not
|
||||||
* synchronization should not impair the accuracy of
|
* impair the accuracy of the reported statistics.
|
||||||
* the reported statistics.
|
|
||||||
*/
|
*/
|
||||||
if ((object->flags & OBJ_FICTITIOUS) != 0) {
|
if ((object->flags & OBJ_FICTITIOUS) != 0) {
|
||||||
/*
|
/*
|
||||||
|
@ -166,6 +166,8 @@ vm_object_zdtor(void *mem, int size, void *arg)
|
|||||||
vm_object_t object;
|
vm_object_t object;
|
||||||
|
|
||||||
object = (vm_object_t)mem;
|
object = (vm_object_t)mem;
|
||||||
|
KASSERT(object->ref_count == 0,
|
||||||
|
("object %p ref_count = %d", object, object->ref_count));
|
||||||
KASSERT(TAILQ_EMPTY(&object->memq),
|
KASSERT(TAILQ_EMPTY(&object->memq),
|
||||||
("object %p has resident pages in its memq", object));
|
("object %p has resident pages in its memq", object));
|
||||||
KASSERT(vm_radix_is_empty(&object->rtree),
|
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,
|
KASSERT(object->shadow_count == 0,
|
||||||
("object %p shadow_count = %d",
|
("object %p shadow_count = %d",
|
||||||
object, object->shadow_count));
|
object, object->shadow_count));
|
||||||
|
KASSERT(object->type == OBJT_DEAD,
|
||||||
|
("object %p has non-dead type %d",
|
||||||
|
object, object->type));
|
||||||
}
|
}
|
||||||
#endif
|
#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);
|
rw_init_flags(&object->lock, "vm object", RW_DUPOK | RW_NEW);
|
||||||
|
|
||||||
/* These are true for any object that has been freed */
|
/* 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_root = 0;
|
||||||
object->rtree.rt_flags = 0;
|
object->rtree.rt_flags = 0;
|
||||||
object->paging_in_progress = 0;
|
object->paging_in_progress = 0;
|
||||||
@ -206,6 +213,10 @@ vm_object_zinit(void *mem, int size, int flags)
|
|||||||
object->shadow_count = 0;
|
object->shadow_count = 0;
|
||||||
object->cache.rt_root = 0;
|
object->cache.rt_root = 0;
|
||||||
object->cache.rt_flags = 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);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,10 +263,6 @@ _vm_object_allocate(objtype_t type, vm_pindex_t size, vm_object_t object)
|
|||||||
#if VM_NRESERVLEVEL > 0
|
#if VM_NRESERVLEVEL > 0
|
||||||
LIST_INIT(&object->rvq);
|
LIST_INIT(&object->rvq);
|
||||||
#endif
|
#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)
|
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.
|
* Release the allocation charge.
|
||||||
*/
|
*/
|
||||||
if (object->cred != NULL) {
|
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);
|
swap_release_by_cred(object->charge, object->cred);
|
||||||
object->charge = 0;
|
object->charge = 0;
|
||||||
crfree(object->cred);
|
crfree(object->cred);
|
||||||
@ -788,6 +785,10 @@ vm_object_terminate(vm_object_t object)
|
|||||||
if (__predict_false(!vm_object_cache_is_empty(object)))
|
if (__predict_false(!vm_object_cache_is_empty(object)))
|
||||||
vm_page_cache_free(object, 0, 0);
|
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.
|
* Let the pager know object is dead.
|
||||||
*/
|
*/
|
||||||
@ -1803,6 +1804,8 @@ vm_object_collapse(vm_object_t object)
|
|||||||
KASSERT(backing_object->ref_count == 1, (
|
KASSERT(backing_object->ref_count == 1, (
|
||||||
"backing_object %p was somehow re-referenced during collapse!",
|
"backing_object %p was somehow re-referenced during collapse!",
|
||||||
backing_object));
|
backing_object));
|
||||||
|
backing_object->type = OBJT_DEAD;
|
||||||
|
backing_object->ref_count = 0;
|
||||||
VM_OBJECT_WUNLOCK(backing_object);
|
VM_OBJECT_WUNLOCK(backing_object);
|
||||||
vm_object_destroy(backing_object);
|
vm_object_destroy(backing_object);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user