- 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
This commit is contained in:
parent
fd8dd3a6d7
commit
73e9030e61
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=279688
@ -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 *);
|
||||
|
@ -215,6 +215,7 @@ vm_pager_bufferinit()
|
||||
|
||||
cluster_pbuf_freecnt = nswbuf / 2;
|
||||
vnode_pbuf_freecnt = nswbuf / 2 + 1;
|
||||
vnode_async_pbuf_freecnt = nswbuf / 2;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user