Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 21 Jun 2009 20:29:14 +0000 (UTC)
From:      Alan Cox <alc@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r194607 - head/sys/vm
Message-ID:  <200906212029.n5LKTEMx017790@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906212029.n5LKTEMx017790>