svn commit: r279688 - in head/sys: sys vm

Gleb Smirnoff glebius at FreeBSD.org
Fri Mar 6 14:15:31 UTC 2015


Author: glebius
Date: Fri Mar  6 14:15:30 2015
New Revision: 279688
URL: https://svnweb.freebsd.org/changeset/base/279688

Log:
  - 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

Modified:
  head/sys/sys/buf.h
  head/sys/vm/vm_pager.c
  head/sys/vm/vnode_pager.c

Modified: head/sys/sys/buf.h
==============================================================================
--- head/sys/sys/buf.h	Fri Mar  6 11:27:58 2015	(r279687)
+++ head/sys/sys/buf.h	Fri Mar  6 14:15:30 2015	(r279688)
@@ -475,6 +475,8 @@ extern struct	buf *swbuf;		/* Swap I/O b
 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 *);

Modified: head/sys/vm/vm_pager.c
==============================================================================
--- head/sys/vm/vm_pager.c	Fri Mar  6 11:27:58 2015	(r279687)
+++ head/sys/vm/vm_pager.c	Fri Mar  6 14:15:30 2015	(r279688)
@@ -215,6 +215,7 @@ vm_pager_bufferinit()
 
 	cluster_pbuf_freecnt = nswbuf / 2;
 	vnode_pbuf_freecnt = nswbuf / 2 + 1;
+	vnode_async_pbuf_freecnt = nswbuf / 2;
 }
 
 /*

Modified: head/sys/vm/vnode_pager.c
==============================================================================
--- head/sys/vm/vnode_pager.c	Fri Mar  6 11:27:58 2015	(r279687)
+++ head/sys/vm/vnode_pager.c	Fri Mar  6 14:15:30 2015	(r279688)
@@ -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 vnod
 {
 	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 vnod
 	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 vnod
 	 */
 	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 vnod
 		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 vnod
 		 */
 	} 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 vnod
 	 * 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 vnod
 	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 vnod
 		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(
 		bp->b_pages[i] = NULL;
 	bp->b_vp = NULL;
 	pbrelbo(bp);
-	relpbuf(bp, &vnode_pbuf_freecnt);
+	relpbuf(bp, &vnode_async_pbuf_freecnt);
 }
 
 static int


More information about the svn-src-head mailing list