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
This commit is contained in:
John Baldwin 2006-02-21 22:09:54 +00:00
parent bd106be404
commit ca95b5146a

View File

@ -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));