Fix a perf regression from r355122. We can use a shared lock to drop the

last ref on vnodes.

Reviewed by:	kib, markj
Differential Revision:	https://reviews.freebsd.org/D22565
This commit is contained in:
Jeff Roberson 2019-11-29 19:47:40 +00:00
parent 846419f898
commit 26c4e9831b

View File

@ -520,15 +520,22 @@ static void
vm_object_vndeallocate(vm_object_t object) vm_object_vndeallocate(vm_object_t object)
{ {
struct vnode *vp = (struct vnode *) object->handle; struct vnode *vp = (struct vnode *) object->handle;
bool last;
KASSERT(object->type == OBJT_VNODE, KASSERT(object->type == OBJT_VNODE,
("vm_object_vndeallocate: not a vnode object")); ("vm_object_vndeallocate: not a vnode object"));
KASSERT(vp != NULL, ("vm_object_vndeallocate: missing vp")); KASSERT(vp != NULL, ("vm_object_vndeallocate: missing vp"));
/* Object lock to protect handle lookup. */
last = refcount_release(&object->ref_count);
VM_OBJECT_RUNLOCK(object);
if (!last)
return;
if (!umtx_shm_vnobj_persistent) if (!umtx_shm_vnobj_persistent)
umtx_shm_object_terminated(object); umtx_shm_object_terminated(object);
VM_OBJECT_WUNLOCK(object);
/* vrele may need the vnode lock. */ /* vrele may need the vnode lock. */
vrele(vp); vrele(vp);
} }
@ -548,7 +555,7 @@ void
vm_object_deallocate(vm_object_t object) vm_object_deallocate(vm_object_t object)
{ {
vm_object_t robject, temp; vm_object_t robject, temp;
bool last, released; bool released;
while (object != NULL) { while (object != NULL) {
/* /*
@ -565,18 +572,22 @@ vm_object_deallocate(vm_object_t object)
if (released) if (released)
return; return;
VM_OBJECT_WLOCK(object);
KASSERT(object->ref_count != 0,
("vm_object_deallocate: object deallocated too many times: %d", object->type));
last = refcount_release(&object->ref_count);
if (object->type == OBJT_VNODE) { if (object->type == OBJT_VNODE) {
if (last) VM_OBJECT_RLOCK(object);
if (object->type == OBJT_VNODE) {
vm_object_vndeallocate(object); vm_object_vndeallocate(object);
else return;
VM_OBJECT_WUNLOCK(object); }
return; VM_OBJECT_RUNLOCK(object);
} }
VM_OBJECT_WLOCK(object);
KASSERT(object->ref_count > 0,
("vm_object_deallocate: object deallocated too many times: %d",
object->type));
if (refcount_release(&object->ref_count))
goto doterm;
if (object->ref_count > 1) { if (object->ref_count > 1) {
VM_OBJECT_WUNLOCK(object); VM_OBJECT_WUNLOCK(object);
return; return;