From ca95b5146adf136993166ee524ba047a76c1d7d6 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Tue, 21 Feb 2006 22:09:54 +0000 Subject: [PATCH] Lock the vm_object while checking its type to see if it is a vnode-backed object that requires Giant in vm_object_deallocate(). This is somewhat hairy in that if we can't obtain Giant directly, we have to drop the object lock, then lock Giant, then relock the object lock and verify that we still need Giant. If we don't (because the object changed to OBJT_DEAD for example), then we drop Giant before continuing. Reviewed by: alc Tested by: kris --- sys/vm/vm_object.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 5000db4c88a..5321b537b5b 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -438,23 +438,37 @@ vm_object_deallocate(vm_object_t object) while (object != NULL) { int vfslocked; - /* - * In general, the object should be locked when working with - * its type. In this case, in order to maintain proper lock - * ordering, an exception is possible because a vnode-backed - * object never changes its type. - */ + vfslocked = 0; - if (object->type == OBJT_VNODE) { - struct vnode *vp = (struct vnode *) object->handle; - vfslocked = VFS_LOCK_GIANT(vp->v_mount); - } + restart: VM_OBJECT_LOCK(object); if (object->type == OBJT_VNODE) { + struct vnode *vp = (struct vnode *) object->handle; + + /* + * Conditionally acquire Giant for a vnode-backed + * object. We have to be careful since the type of + * a vnode object can change while the object is + * unlocked. + */ + if (VFS_NEEDSGIANT(vp->v_mount) && !vfslocked) { + vfslocked = 1; + if (!mtx_trylock(&Giant)) { + VM_OBJECT_UNLOCK(object); + mtx_lock(&Giant); + goto restart; + } + } vm_object_vndeallocate(object); VFS_UNLOCK_GIANT(vfslocked); return; - } + } else + /* + * This is to handle the case that the object + * changed type while we dropped its lock to + * obtain Giant. + */ + VFS_UNLOCK_GIANT(vfslocked); KASSERT(object->ref_count != 0, ("vm_object_deallocate: object deallocated too many times: %d", object->type));