svn commit: r202979 - stable/7/sys/vm
John Baldwin
jhb at FreeBSD.org
Mon Jan 25 18:15:10 UTC 2010
Author: jhb
Date: Mon Jan 25 18:15:10 2010
New Revision: 202979
URL: http://svn.freebsd.org/changeset/base/202979
Log:
MFC 194607:
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.
Approved by: re (kib)
Modified:
stable/7/sys/vm/vm_phys.c
Directory Properties:
stable/7/sys/ (props changed)
stable/7/sys/cddl/contrib/opensolaris/ (props changed)
stable/7/sys/contrib/dev/acpica/ (props changed)
stable/7/sys/contrib/pf/ (props changed)
Modified: stable/7/sys/vm/vm_phys.c
==============================================================================
--- stable/7/sys/vm/vm_phys.c Mon Jan 25 17:51:34 2010 (r202978)
+++ stable/7/sys/vm/vm_phys.c Mon Jan 25 18:15:10 2010 (r202979)
@@ -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);
@@ -700,10 +701,23 @@ done:
KASSERT(pmap_page_get_memattr(m) == VM_MEMATTR_DEFAULT,
("vm_phys_alloc_contig: page %p has unexpected memattr %d",
m, pmap_page_get_memattr(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));
@@ -717,13 +731,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];
@@ -733,6 +740,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);
}
More information about the svn-src-all
mailing list