diff options
author | alc <alc@FreeBSD.org> | 2007-08-05 21:04:32 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 2007-08-05 21:04:32 +0000 |
commit | a1f1ba2d5660f8201e2fb4b1c9bed80049ed3261 (patch) | |
tree | 17f01c3fb32d0e3cf3fce4398a84d22a4d3c405c /sys/vm/device_pager.c | |
parent | 4ee3bb0e270ba406106fbe67ce54703024ad6ad5 (diff) | |
download | FreeBSD-src-a1f1ba2d5660f8201e2fb4b1c9bed80049ed3261.zip FreeBSD-src-a1f1ba2d5660f8201e2fb4b1c9bed80049ed3261.tar.gz |
Consider a scenario in which one processor, call it Pt, is performing
vm_object_terminate() on a device-backed object at the same time that
another processor, call it Pa, is performing dev_pager_alloc() on the
same device. The problem is that vm_pager_object_lookup() should not be
allowed to return a doomed object, i.e., an object with OBJ_DEAD set,
but it does. In detail, the unfortunate sequence of events is: Pt in
vm_object_terminate() holds the doomed object's lock and sets OBJ_DEAD
on the object. Pa in dev_pager_alloc() holds dev_pager_sx and calls
vm_pager_object_lookup(), which returns the doomed object. Next, Pa
calls vm_object_reference(), which requires the doomed object's lock, so
Pa waits for Pt to release the doomed object's lock. Pt proceeds to the
point in vm_object_terminate() where it releases the doomed object's
lock. Pa is now able to complete vm_object_reference() because it can
now complete the acquisition of the doomed object's lock. So, now the
doomed object has a reference count of one! Pa releases dev_pager_sx
and returns the doomed object from dev_pager_alloc(). Pt now acquires
dev_pager_mtx, removes the doomed object from dev_pager_object_list,
releases dev_pager_mtx, and finally calls uma_zfree with the doomed
object. However, the doomed object is still in use by Pa.
Repeating my key point, vm_pager_object_lookup() must not return a
doomed object. Moreover, the test for the object's state, i.e.,
doomed or not, and the increment of the object's reference count
should be carried out atomically.
Reviewed by: kib
Approved by: re (kensmith)
MFC after: 3 weeks
Diffstat (limited to 'sys/vm/device_pager.c')
-rw-r--r-- | sys/vm/device_pager.c | 4 |
1 files changed, 0 insertions, 4 deletions
diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c index e9b9e73..bbca5cc 100644 --- a/sys/vm/device_pager.c +++ b/sys/vm/device_pager.c @@ -160,10 +160,6 @@ dev_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot, vm_ooffset_t fo TAILQ_INSERT_TAIL(&dev_pager_object_list, object, pager_object_list); mtx_unlock(&dev_pager_mtx); } else { - /* - * Gain a reference to the object. - */ - vm_object_reference(object); if (pindex > object->size) object->size = pindex; } |