diff options
author | glebius <glebius@FreeBSD.org> | 2015-03-06 14:15:30 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2015-03-06 14:15:30 +0000 |
commit | 3a52ecfa6691c2702c8ab7eb611b6b51323de6e1 (patch) | |
tree | 33f79cfb5a744d12e8ef2f1f89482f6993118f59 | |
parent | 3169d96832fc12e9f0c5896400304a6d54bb6ee0 (diff) | |
download | FreeBSD-src-3a52ecfa6691c2702c8ab7eb611b6b51323de6e1.zip FreeBSD-src-3a52ecfa6691c2702c8ab7eb611b6b51323de6e1.tar.gz |
- In vnode_pager_generic_getpages() use different free counters for
synchronous and asynchronous requests. The latter can saturate the
I/O and we do not want them to affect regular paging.
- Allocate the pbuf at the very beginning of the function, so that
if we are low on certain kind of pbufs don't even proceed to BMAP,
but sleep.
Reviewed by: kib
Sponsored by: Nginx, Inc.
Sponsored by: Netflix
-rw-r--r-- | sys/sys/buf.h | 2 | ||||
-rw-r--r-- | sys/vm/vm_pager.c | 1 | ||||
-rw-r--r-- | sys/vm/vnode_pager.c | 17 |
3 files changed, 16 insertions, 4 deletions
diff --git a/sys/sys/buf.h b/sys/sys/buf.h index 71ef74f..72ab61b 100644 --- a/sys/sys/buf.h +++ b/sys/sys/buf.h @@ -475,6 +475,8 @@ extern struct buf *swbuf; /* Swap I/O buffer headers. */ extern int nswbuf; /* Number of swap I/O buffer headers. */ extern int cluster_pbuf_freecnt; /* Number of pbufs for clusters */ extern int vnode_pbuf_freecnt; /* Number of pbufs for vnode pager */ +extern int vnode_async_pbuf_freecnt; /* Number of pbufs for vnode pager, + asynchronous reads */ extern caddr_t unmapped_buf; void runningbufwakeup(struct buf *); diff --git a/sys/vm/vm_pager.c b/sys/vm/vm_pager.c index 65193c3..5f69468 100644 --- a/sys/vm/vm_pager.c +++ b/sys/vm/vm_pager.c @@ -215,6 +215,7 @@ vm_pager_bufferinit() cluster_pbuf_freecnt = nswbuf / 2; vnode_pbuf_freecnt = nswbuf / 2 + 1; + vnode_async_pbuf_freecnt = nswbuf / 2; } /* diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index 3695d23..3d67333 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -104,6 +104,7 @@ struct pagerops vnodepagerops = { }; int vnode_pbuf_freecnt; +int vnode_async_pbuf_freecnt; /* Create the VM system backing object for this vnode */ int @@ -751,7 +752,7 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int bytecount, { vm_object_t object; off_t foff; - int i, j, size, bsize, first; + int i, j, size, bsize, first, *freecnt; daddr_t firstaddr, reqblock; struct bufobj *bo; int runpg; @@ -771,6 +772,10 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int bytecount, bsize = vp->v_mount->mnt_stat.f_iosize; foff = IDX_TO_OFF(m[reqpage]->pindex); + freecnt = iodone != NULL ? + &vnode_async_pbuf_freecnt : &vnode_pbuf_freecnt; + bp = getpbuf(freecnt); + /* * Get the underlying device blocks for the file with VOP_BMAP(). * If the file system doesn't support VOP_BMAP, use old way of @@ -778,8 +783,8 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int bytecount, */ error = VOP_BMAP(vp, foff / bsize, &bo, &reqblock, NULL, NULL); if (error == EOPNOTSUPP) { + relpbuf(bp, freecnt); VM_OBJECT_WLOCK(object); - for (i = 0; i < count; i++) if (i != reqpage) { vm_page_lock(m[i]); @@ -792,6 +797,7 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int bytecount, VM_OBJECT_WUNLOCK(object); return (error); } else if (error != 0) { + relpbuf(bp, freecnt); vm_pager_free_nonreq(object, m, reqpage, count); return (VM_PAGER_ERROR); @@ -802,6 +808,7 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int bytecount, */ } else if ((PAGE_SIZE / bsize) > 1 && (vp->v_mount->mnt_stat.f_type != nfs_mount_type)) { + relpbuf(bp, freecnt); vm_pager_free_nonreq(object, m, reqpage, count); PCPU_INC(cnt.v_vnodein); PCPU_INC(cnt.v_vnodepgsin); @@ -820,9 +827,11 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int bytecount, * media. */ if (m[reqpage]->valid == VM_PAGE_BITS_ALL) { + relpbuf(bp, freecnt); vm_pager_free_nonreq(object, m, reqpage, count); return (VM_PAGER_OK); } else if (reqblock == -1) { + relpbuf(bp, freecnt); pmap_zero_page(m[reqpage]); KASSERT(m[reqpage]->dirty == 0, ("vnode_pager_generic_getpages: page %p is dirty", m)); @@ -853,6 +862,7 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int bytecount, for (first = 0, i = 0; i < count; i = runend) { if (vnode_pager_addr(vp, IDX_TO_OFF(m[i]->pindex), &firstaddr, &runpg) != 0) { + relpbuf(bp, freecnt); VM_OBJECT_WLOCK(object); for (; i < count; i++) if (i != reqpage) { @@ -941,7 +951,6 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int bytecount, size = (size + secmask) & ~secmask; } - bp = getpbuf(&vnode_pbuf_freecnt); bp->b_kvaalloc = bp->b_data; /* @@ -1016,7 +1025,7 @@ vnode_pager_generic_getpages_done_async(struct buf *bp) bp->b_pages[i] = NULL; bp->b_vp = NULL; pbrelbo(bp); - relpbuf(bp, &vnode_pbuf_freecnt); + relpbuf(bp, &vnode_async_pbuf_freecnt); } static int |