From owner-svn-src-all@FreeBSD.ORG Sun May 2 16:44:06 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id DC281106566B; Sun, 2 May 2010 16:44:06 +0000 (UTC) (envelope-from alc@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [69.147.83.44]) by mx1.freebsd.org (Postfix) with ESMTP id CCCD58FC14; Sun, 2 May 2010 16:44:06 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o42Gi6TB015410; Sun, 2 May 2010 16:44:06 GMT (envelope-from alc@svn.freebsd.org) Received: (from alc@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o42Gi6fS015409; Sun, 2 May 2010 16:44:06 GMT (envelope-from alc@svn.freebsd.org) Message-Id: <201005021644.o42Gi6fS015409@svn.freebsd.org> From: Alan Cox Date: Sun, 2 May 2010 16:44:06 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r207519 - head/sys/vm X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 02 May 2010 16:44:07 -0000 Author: alc Date: Sun May 2 16:44:06 2010 New Revision: 207519 URL: http://svn.freebsd.org/changeset/base/207519 Log: This change addresses the race condition that was introduced by the previous revision, r207450, to this file. Specifically, between dropping the page queues lock in vm_contig_launder() and reacquiring it in vm_contig_launder_page(), the page may be removed from the active or inactive queue. It could be wired, freed, cached, etc. None of which vm_contig_launder_page() is prepared for. Reviewed by: kib, kmacy Modified: head/sys/vm/vm_contig.c Modified: head/sys/vm/vm_contig.c ============================================================================== --- head/sys/vm/vm_contig.c Sun May 2 16:40:18 2010 (r207518) +++ head/sys/vm/vm_contig.c Sun May 2 16:44:06 2010 (r207519) @@ -96,33 +96,33 @@ vm_contig_launder_page(vm_page_t m, vm_p vm_page_t m_tmp; struct vnode *vp; struct mount *mp; - int vfslocked, dirty; + int vfslocked; - vm_page_lock(m); - vm_page_lock_queues(); + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + vm_page_lock_assert(m, MA_OWNED); object = m->object; if (!VM_OBJECT_TRYLOCK(object) && !vm_pageout_fallback_object_lock(m, next)) { - VM_OBJECT_UNLOCK(object); - vm_page_unlock_queues(); vm_page_unlock(m); + VM_OBJECT_UNLOCK(object); return (EAGAIN); } if (vm_page_sleep_if_busy(m, TRUE, "vpctw0")) { VM_OBJECT_UNLOCK(object); + vm_page_lock_queues(); return (EBUSY); } vm_page_test_dirty(m); if (m->dirty == 0 && m->hold_count == 0) pmap_remove_all(m); - if ((dirty = m->dirty) != 0) { - vm_page_unlock_queues(); + if (m->dirty != 0) { vm_page_unlock(m); if ((object->flags & OBJ_DEAD) != 0) { VM_OBJECT_UNLOCK(object); return (EAGAIN); } if (object->type == OBJT_VNODE) { + vm_page_unlock_queues(); vp = object->handle; vm_object_reference_locked(object); VM_OBJECT_UNLOCK(object); @@ -136,19 +136,20 @@ vm_contig_launder_page(vm_page_t m, vm_p VFS_UNLOCK_GIANT(vfslocked); vm_object_deallocate(object); vn_finished_write(mp); + vm_page_lock_queues(); return (0); } else if (object->type == OBJT_SWAP || object->type == OBJT_DEFAULT) { + vm_page_unlock_queues(); m_tmp = m; vm_pageout_flush(&m_tmp, 1, VM_PAGER_PUT_SYNC); VM_OBJECT_UNLOCK(object); + vm_page_lock_queues(); return (0); } - } else if (m->hold_count == 0) - vm_page_cache(m); - - if (dirty == 0) { - vm_page_unlock_queues(); + } else { + if (m->hold_count == 0) + vm_page_cache(m); vm_page_unlock(m); } VM_OBJECT_UNLOCK(object); @@ -167,11 +168,12 @@ vm_contig_launder(int queue) if ((m->flags & PG_MARKER) != 0) continue; + if (!vm_page_trylock(m)) + continue; KASSERT(VM_PAGE_INQUEUE2(m, queue), ("vm_contig_launder: page %p's queue is not %d", m, queue)); - vm_page_unlock_queues(); error = vm_contig_launder_page(m, &next); - vm_page_lock_queues(); + vm_page_lock_assert(m, MA_NOTOWNED); if (error == 0) return (TRUE); if (error == EBUSY)