From owner-cvs-all@FreeBSD.ORG Sun Aug 5 21:04:33 2007 Return-Path: Delivered-To: cvs-all@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1019616A41A; Sun, 5 Aug 2007 21:04:33 +0000 (UTC) (envelope-from alc@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id F2E1913C457; Sun, 5 Aug 2007 21:04:32 +0000 (UTC) (envelope-from alc@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id l75L4WZk065083; Sun, 5 Aug 2007 21:04:32 GMT (envelope-from alc@repoman.freebsd.org) Received: (from alc@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id l75L4WM3065082; Sun, 5 Aug 2007 21:04:32 GMT (envelope-from alc) Message-Id: <200708052104.l75L4WM3065082@repoman.freebsd.org> From: Alan Cox Date: Sun, 5 Aug 2007 21:04:32 +0000 (UTC) To: src-committers@FreeBSD.org, cvs-src@FreeBSD.org, cvs-all@FreeBSD.org X-FreeBSD-CVS-Branch: HEAD Cc: Subject: cvs commit: src/sys/vm device_pager.c phys_pager.c swap_pager.c vm_pager.c X-BeenThere: cvs-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: CVS commit messages for the entire tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 05 Aug 2007 21:04:33 -0000 alc 2007-08-05 21:04:32 UTC FreeBSD src repository Modified files: sys/vm device_pager.c phys_pager.c swap_pager.c vm_pager.c Log: 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 Revision Changes Path 1.82 +0 -4 src/sys/vm/device_pager.c 1.27 +0 -4 src/sys/vm/phys_pager.c 1.295 +1 -3 src/sys/vm/swap_pager.c 1.108 +19 -7 src/sys/vm/vm_pager.c