Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 17 Nov 2016 20:32:32 +0000 (UTC)
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r308778 - head/sys/vm
Message-ID:  <201611172032.uAHKWWcT000439@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201611172032.uAHKWWcT000439>