From owner-svn-src-head@FreeBSD.ORG Sun Jun 21 20:29:14 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 746B11065673; Sun, 21 Jun 2009 20:29:14 +0000 (UTC) (envelope-from alc@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 631ED8FC16; Sun, 21 Jun 2009 20:29:14 +0000 (UTC) (envelope-from alc@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n5LKTEaL017792; Sun, 21 Jun 2009 20:29:14 GMT (envelope-from alc@svn.freebsd.org) Received: (from alc@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n5LKTEMx017790; Sun, 21 Jun 2009 20:29:14 GMT (envelope-from alc@svn.freebsd.org) Message-Id: <200906212029.n5LKTEMx017790@svn.freebsd.org> From: Alan Cox Date: Sun, 21 Jun 2009 20:29:14 +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: r194607 - head/sys/vm X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 21 Jun 2009 20:29:15 -0000 Author: alc Date: Sun Jun 21 20:29:14 2009 New Revision: 194607 URL: http://svn.freebsd.org/changeset/base/194607 Log: Implement a mechanism within vm_phys_alloc_contig() to defer all necessary calls to vdrop() until after the free page queues lock is released. This eliminates repeatedly releasing and reacquiring the free page queues lock each time the last cached page is reclaimed from a vnode-backed object. Modified: head/sys/vm/vm_phys.c Modified: head/sys/vm/vm_phys.c ============================================================================== --- head/sys/vm/vm_phys.c Sun Jun 21 20:08:07 2009 (r194606) +++ head/sys/vm/vm_phys.c Sun Jun 21 20:29:14 2009 (r194607) @@ -594,7 +594,7 @@ vm_phys_alloc_contig(unsigned long npage struct vm_phys_seg *seg; vm_object_t m_object; vm_paddr_t pa, pa_last, size; - vm_page_t m, m_ret; + vm_page_t deferred_vdrop_list, m, m_ret; int flind, i, oind, order, pind; size = npages << PAGE_SHIFT; @@ -604,6 +604,7 @@ vm_phys_alloc_contig(unsigned long npage ("vm_phys_alloc_contig: alignment must be a power of 2")); KASSERT((boundary & (boundary - 1)) == 0, ("vm_phys_alloc_contig: boundary must be a power of 2")); + deferred_vdrop_list = NULL; /* Compute the queue that is the best fit for npages. */ for (order = 0; (1 << order) < npages; order++); mtx_lock(&vm_page_queue_free_mtx); @@ -697,10 +698,23 @@ done: ("vm_phys_alloc_contig: page %p is busy", m)); KASSERT(m->dirty == 0, ("vm_phys_alloc_contig: page %p is dirty", m)); - m_object = m->object; if ((m->flags & PG_CACHED) != 0) { m->valid = 0; + m_object = m->object; vm_page_cache_remove(m); + if (m_object->type == OBJT_VNODE && + m_object->cache == NULL) { + /* + * Enqueue the vnode for deferred vdrop(). + * + * Unmanaged pages don't use "pageq", so it + * can be safely abused to construct a short- + * lived queue of vnodes. + */ + m->pageq.tqe_prev = m_object->handle; + m->pageq.tqe_next = deferred_vdrop_list; + deferred_vdrop_list = m; + } } else { KASSERT(VM_PAGE_IS_FREE(m), ("vm_phys_alloc_contig: page %p is not free", m)); @@ -714,13 +728,6 @@ done: m->flags = PG_UNMANAGED | (m->flags & PG_ZERO); m->oflags = 0; /* Unmanaged pages don't use "act_count". */ - if (m_object != NULL && - m_object->type == OBJT_VNODE && - m_object->cache == NULL) { - mtx_unlock(&vm_page_queue_free_mtx); - vdrop(m_object->handle); - mtx_lock(&vm_page_queue_free_mtx); - } } for (; i < roundup2(npages, 1 << imin(oind, order)); i++) { m = &m_ret[i]; @@ -730,6 +737,10 @@ done: vm_phys_free_pages(m, 0); } mtx_unlock(&vm_page_queue_free_mtx); + while (deferred_vdrop_list != NULL) { + vdrop((struct vnode *)deferred_vdrop_list->pageq.tqe_prev); + deferred_vdrop_list = deferred_vdrop_list->pageq.tqe_next; + } return (m_ret); }