summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2015-06-06 20:37:40 +0000
committerjhb <jhb@FreeBSD.org>2015-06-06 20:37:40 +0000
commit51c06666a902e195ca88afc6b333748c1d7ad639 (patch)
treed1201d664486dbe0b7e77499d73ddb7f4ac6903a
parentac9f7bc3c6a3d76b846574698062aab3d7b860f5 (diff)
downloadFreeBSD-src-51c06666a902e195ca88afc6b333748c1d7ad639.zip
FreeBSD-src-51c06666a902e195ca88afc6b333748c1d7ad639.tar.gz
MFC 261811,282660,282706:
Place VM objects on the object list when created and never remove them. 261811: Fix function name in KASSERT(). 282660: 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.) 282706: Satisfy vm_object uma zone destructor requirements after r282660 when vnode object creation raced.
-rw-r--r--sys/vm/default_pager.c1
-rw-r--r--sys/vm/device_pager.c2
-rw-r--r--sys/vm/phys_pager.c2
-rw-r--r--sys/vm/sg_pager.c2
-rw-r--r--sys/vm/swap_pager.c2
-rw-r--r--sys/vm/vm_meter.c16
-rw-r--r--sys/vm/vm_object.c32
-rw-r--r--sys/vm/vnode_pager.c6
8 files changed, 36 insertions, 27 deletions
diff --git a/sys/vm/default_pager.c b/sys/vm/default_pager.c
index 26326a5..98dee45 100644
--- a/sys/vm/default_pager.c
+++ b/sys/vm/default_pager.c
@@ -113,6 +113,7 @@ default_pager_dealloc(object)
/*
* OBJT_DEFAULT objects have no special resources allocated to them.
*/
+ object->type = OBJT_DEAD;
}
/*
diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c
index 89e3818..60c1beb 100644
--- a/sys/vm/device_pager.c
+++ b/sys/vm/device_pager.c
@@ -252,6 +252,8 @@ dev_pager_dealloc(object)
!= NULL)
dev_pager_free_page(object, m);
}
+ object->handle = NULL;
+ object->type = OBJT_DEAD;
}
static int
diff --git a/sys/vm/phys_pager.c b/sys/vm/phys_pager.c
index 9e98006..885a451 100644
--- a/sys/vm/phys_pager.c
+++ b/sys/vm/phys_pager.c
@@ -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;
}
/*
diff --git a/sys/vm/sg_pager.c b/sys/vm/sg_pager.c
index e35741e..23ebd3a 100644
--- a/sys/vm/sg_pager.c
+++ b/sys/vm/sg_pager.c
@@ -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
diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c
index 1e8b6b7..04e9fb9 100644
--- a/sys/vm/swap_pager.c
+++ b/sys/vm/swap_pager.c
@@ -693,6 +693,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;
}
/************************************************************************
diff --git a/sys/vm/vm_meter.c b/sys/vm/vm_meter.c
index 713a2be..75974c6 100644
--- a/sys/vm/vm_meter.c
+++ b/sys/vm/vm_meter.c
@@ -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) {
/*
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index 7c1d592..ab1562e 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -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
@@ -200,6 +205,8 @@ vm_object_zinit(void *mem, int size, int flags)
rw_init_flags(&object->lock, "vm object", RW_DUPOK);
/* 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;
@@ -207,6 +214,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);
}
@@ -253,10 +264,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);
}
/*
@@ -672,20 +679,9 @@ 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,
- ("vm_object_terminate: non-swap obj %p has cred",
- object));
swap_release_by_cred(object->charge, object->cred);
object->charge = 0;
crfree(object->cred);
@@ -790,6 +786,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.
*/
@@ -1805,6 +1805,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);
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index 3353b70..b960d6e 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -227,6 +227,12 @@ retry:
* Object has been created while we were sleeping
*/
VI_UNLOCK(vp);
+ VM_OBJECT_WLOCK(object);
+ KASSERT(object->ref_count == 1,
+ ("leaked ref %p %d", object, object->ref_count));
+ object->type = OBJT_DEAD;
+ object->ref_count = 0;
+ VM_OBJECT_WUNLOCK(object);
vm_object_destroy(object);
goto retry;
}
OpenPOWER on IntegriCloud