mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-14 10:09:48 +00:00
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:
parent
bd106be404
commit
ca95b5146a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=155884
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user