svn commit: r308778 - head/sys/vm
Gleb Smirnoff
glebius at FreeBSD.org
Thu Nov 17 20:32:33 UTC 2016
Author: glebius
Date: Thu Nov 17 20:32:32 2016
New Revision: 308778
URL: https://svnweb.freebsd.org/changeset/base/308778
Log:
- If caller specifies readbehind and readahead that together with count
doesn't fit into a buf, then trim readbehind and readahead evenly. If
rbehind was limited by the previous BMAP, then roundup its trim to
block size.
- Add KASSERT to check that b_blkno has proper offset from original
blkno returned by BMAP. [1]
- Add KASSERT to check that pages in buf are consecutive.
Reviewed by: kib
Submitted by: kib [1]
Modified:
head/sys/vm/vnode_pager.c
Modified: head/sys/vm/vnode_pager.c
==============================================================================
--- head/sys/vm/vnode_pager.c Thu Nov 17 20:00:20 2016 (r308777)
+++ head/sys/vm/vnode_pager.c Thu Nov 17 20:32:32 2016 (r308778)
@@ -743,6 +743,9 @@ vnode_pager_generic_getpages(struct vnod
struct bufobj *bo;
struct buf *bp;
off_t foff;
+#ifdef INVARIANTS
+ off_t blkno0;
+#endif
int bsize, pagesperblock, *freecnt;
int error, before, after, rbehind, rahead, poff, i;
int bytecount, secmask;
@@ -843,6 +846,9 @@ vnode_pager_generic_getpages(struct vnod
return (VM_PAGER_OK);
}
+#ifdef INVARIANTS
+ blkno0 = bp->b_blkno;
+#endif
bp->b_blkno += (foff % bsize) / DEV_BSIZE;
/* Recalculate blocks available after/before to pages. */
@@ -864,7 +870,25 @@ vnode_pager_generic_getpages(struct vnod
rbehind = min(rbehind, m[0]->pindex);
rahead = min(rahead, after);
rahead = min(rahead, object->size - m[count - 1]->pindex);
- KASSERT(rbehind + rahead + count <= sizeof(bp->b_pages),
+ /*
+ * Check that total amount of pages fit into buf. Trim rbehind and
+ * rahead evenly if not.
+ */
+ if (rbehind + rahead + count > nitems(bp->b_pages)) {
+ int trim, sum;
+
+ trim = rbehind + rahead + count - nitems(bp->b_pages) + 1;
+ sum = rbehind + rahead;
+ if (rbehind == before) {
+ /* Roundup rbehind trim to block size. */
+ rbehind -= roundup(trim * rbehind / sum, pagesperblock);
+ if (rbehind < 0)
+ rbehind = 0;
+ } else
+ rbehind -= trim * rbehind / sum;
+ rahead -= trim * rahead / sum;
+ }
+ KASSERT(rbehind + rahead + count <= nitems(bp->b_pages),
("%s: behind %d ahead %d count %d", __func__,
rbehind, rahead, count));
@@ -947,8 +971,14 @@ vnode_pager_generic_getpages(struct vnod
if (a_rahead)
*a_rahead = bp->b_pgafter;
+#ifdef INVARIANTS
KASSERT(bp->b_npages <= nitems(bp->b_pages),
("%s: buf %p overflowed", __func__, bp));
+ for (int j = 1; j < bp->b_npages; j++)
+ KASSERT(bp->b_pages[j]->pindex - 1 ==
+ bp->b_pages[j - 1]->pindex,
+ ("%s: pages array not consecutive, bp %p", __func__, bp));
+#endif
/*
* Recalculate first offset and bytecount with regards to read behind.
@@ -987,6 +1017,13 @@ vnode_pager_generic_getpages(struct vnod
bp->b_vp = vp;
bp->b_bcount = bp->b_bufsize = bp->b_runningbufspace = bytecount;
bp->b_iooffset = dbtob(bp->b_blkno);
+ KASSERT(IDX_TO_OFF(m[0]->pindex - bp->b_pages[0]->pindex) ==
+ (blkno0 - bp->b_blkno) * DEV_BSIZE +
+ IDX_TO_OFF(m[0]->pindex) % bsize,
+ ("wrong offsets bsize %d m[0] %ju b_pages[0] %ju "
+ "blkno0 %ju b_blkno %ju", bsize,
+ (uintmax_t)m[0]->pindex, (uintmax_t)bp->b_pages[0]->pindex,
+ (uintmax_t)blkno0, (uintmax_t)bp->b_blkno));
atomic_add_long(&runningbufspace, bp->b_runningbufspace);
PCPU_INC(cnt.v_vnodein);
More information about the svn-src-all
mailing list