summaryrefslogtreecommitdiffstats
path: root/sys/vm/vnode_pager.c
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>2000-12-26 19:41:38 +0000
committerdillon <dillon@FreeBSD.org>2000-12-26 19:41:38 +0000
commitfd223545d4ce7c8c6fe4896ce1eb916f587f77a8 (patch)
tree8bc9147cc365625dec8071f12bd60d2119d819e4 /sys/vm/vnode_pager.c
parenta042274eabc95cdbaadcbde28ce1b8bdbb79d6f8 (diff)
downloadFreeBSD-src-fd223545d4ce7c8c6fe4896ce1eb916f587f77a8.zip
FreeBSD-src-fd223545d4ce7c8c6fe4896ce1eb916f587f77a8.tar.gz
This implements a better launder limiting solution. There was a solution
in 4.2-REL which I ripped out in -stable and -current when implementing the low-memory handling solution. However, maxlaunder turns out to be the saving grace in certain very heavily loaded systems (e.g. newsreader box). The new algorithm limits the number of pages laundered in the first pageout daemon pass. If that is not sufficient then suceessive will be run without any limit. Write I/O is now pipelined using two sysctls, vfs.lorunningspace and vfs.hirunningspace. This prevents excessive buffered writes in the disk queues which cause long (multi-second) delays for reads. It leads to more stable (less jerky) and generally faster I/O streaming to disk by allowing required read ops (e.g. for indirect blocks and such) to occur without interrupting the write stream, amoung other things. NOTE: eventually, filesystem write I/O pipelining needs to be done on a per-device basis. At the moment it is globalized.
Diffstat (limited to 'sys/vm/vnode_pager.c')
-rw-r--r--sys/vm/vnode_pager.c39
1 files changed, 36 insertions, 3 deletions
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index 3dd12ec..c79f62a 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -300,10 +300,29 @@ vnode_pager_setsize(vp, nsize)
m = vm_page_lookup(object, OFF_TO_IDX(nsize));
if (m) {
+ int base = (int)nsize & PAGE_MASK;
+ int size = PAGE_SIZE - base;
+
+ /*
+ * Clear out partial-page garbage in case
+ * the page has been mapped.
+ */
kva = vm_pager_map_page(m);
- bzero((caddr_t) kva + (nsize & PAGE_MASK),
- (int) (round_page(nsize) - nsize));
+ bzero((caddr_t)kva + base, size);
vm_pager_unmap_page(kva);
+
+ /*
+ * Clear out partial-page dirty bits. This
+ * has the side effect of setting the valid
+ * bits, but that is ok. There are a bunch
+ * of places in the VM system where we expected
+ * m->dirty == VM_PAGE_BITS_ALL. The file EOF
+ * case is one of them. If the page is still
+ * partially dirty, make it fully dirty.
+ */
+ vm_page_set_validclean(m, base, size);
+ if (m->dirty != 0)
+ m->dirty = VM_PAGE_BITS_ALL;
}
}
}
@@ -424,6 +443,8 @@ vnode_pager_input_smlfs(object, m)
pbgetvp(dp, bp);
bp->b_bcount = bsize;
bp->b_bufsize = bsize;
+ bp->b_runningbufspace = bp->b_bufsize;
+ runningbufspace += bp->b_runningbufspace;
/* do the input */
BUF_STRATEGY(bp);
@@ -742,6 +763,8 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage)
pbgetvp(dp, bp);
bp->b_bcount = size;
bp->b_bufsize = size;
+ bp->b_runningbufspace = bp->b_bufsize;
+ runningbufspace += bp->b_runningbufspace;
cnt.v_vnodein++;
cnt.v_vnodepgsin += count;
@@ -888,6 +911,11 @@ vnode_pager_putpages(object, m, count, sync, rtvals)
/*
* This is now called from local media FS's to operate against their
* own vnodes if they fail to implement VOP_PUTPAGES.
+ *
+ * This is typically called indirectly via the pageout daemon and
+ * clustering has already typically occured, so in general we ask the
+ * underlying filesystem to write the data out asynchronously rather
+ * then delayed.
*/
int
vnode_pager_generic_putpages(vp, m, bytecount, flags, rtvals)
@@ -938,8 +966,13 @@ vnode_pager_generic_putpages(vp, m, bytecount, flags, rtvals)
}
}
+ /*
+ * pageouts are already clustered, use IO_ASYNC t o force a bawrite()
+ * rather then a bdwrite() to prevent paging I/O from saturating
+ * the buffer cache.
+ */
ioflags = IO_VMIO;
- ioflags |= (flags & (VM_PAGER_PUT_SYNC | VM_PAGER_PUT_INVAL)) ? IO_SYNC: 0;
+ ioflags |= (flags & (VM_PAGER_PUT_SYNC | VM_PAGER_PUT_INVAL)) ? IO_SYNC: IO_ASYNC;
ioflags |= (flags & VM_PAGER_PUT_INVAL) ? IO_INVAL: 0;
aiov.iov_base = (caddr_t) 0;
OpenPOWER on IntegriCloud