summaryrefslogtreecommitdiffstats
path: root/sys/vm
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2014-09-15 17:14:09 +0000
committeralc <alc@FreeBSD.org>2014-09-15 17:14:09 +0000
commit17021239d9d97ea75b0e7eb686bdccc78175565d (patch)
tree5262675ad912eb482a0c3c8e573c2421739769d1 /sys/vm
parentfb532b9858b5102c5001cf866a6bb27ce8b5410c (diff)
downloadFreeBSD-src-17021239d9d97ea75b0e7eb686bdccc78175565d.zip
FreeBSD-src-17021239d9d97ea75b0e7eb686bdccc78175565d.tar.gz
Three improvements to vnode_pager_generic_getpages():
Eliminate an exclusive object lock acquisition and release on the expected execution path. Do page zeroing before the object lock is acquired rather than during the time that the object lock is held. Use vm_pager_free_nonreq() to eliminate duplicated code. Reviewed by: kib MFC after: 6 weeks Sponsored by: EMC / Isilon Storage Division
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/vnode_pager.c24
1 files changed, 13 insertions, 11 deletions
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index 817516d..050f1b0 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -772,24 +772,24 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int bytecount,
}
/*
+ * Since the caller has busied the requested page, that page's valid
+ * field will not be changed by other threads.
+ */
+ vm_page_assert_xbusied(m[reqpage]);
+
+ /*
* If we have a completely valid page available to us, we can
* clean up and return. Otherwise we have to re-read the
* media.
*/
- VM_OBJECT_WLOCK(object);
if (m[reqpage]->valid == VM_PAGE_BITS_ALL) {
- for (i = 0; i < count; i++)
- if (i != reqpage) {
- vm_page_lock(m[i]);
- vm_page_free(m[i]);
- vm_page_unlock(m[i]);
- }
- VM_OBJECT_WUNLOCK(object);
- return VM_PAGER_OK;
+ vm_pager_free_nonreq(object, m, reqpage, count);
+ return (VM_PAGER_OK);
} else if (reqblock == -1) {
pmap_zero_page(m[reqpage]);
KASSERT(m[reqpage]->dirty == 0,
("vnode_pager_generic_getpages: page %p is dirty", m));
+ VM_OBJECT_WLOCK(object);
m[reqpage]->valid = VM_PAGE_BITS_ALL;
for (i = 0; i < count; i++)
if (i != reqpage) {
@@ -799,9 +799,11 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int bytecount,
}
VM_OBJECT_WUNLOCK(object);
return (VM_PAGER_OK);
+ } else if (m[reqpage]->valid != 0) {
+ VM_OBJECT_WLOCK(object);
+ m[reqpage]->valid = 0;
+ VM_OBJECT_WUNLOCK(object);
}
- m[reqpage]->valid = 0;
- VM_OBJECT_WUNLOCK(object);
/*
* here on direct device I/O
OpenPOWER on IntegriCloud