aboutsummaryrefslogtreecommitdiff
path: root/sys/vm/vnode_pager.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/vm/vnode_pager.c')
-rw-r--r--sys/vm/vnode_pager.c49
1 files changed, 40 insertions, 9 deletions
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index 92c28f3098ad..b466d32e11af 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -466,10 +466,6 @@ vnode_pager_setsize(struct vnode *vp, vm_ooffset_t nsize)
* replacement from working properly.
*/
vm_page_clear_dirty(m, base, PAGE_SIZE - base);
- } else if ((nsize & PAGE_MASK) &&
- vm_page_is_cached(object, OFF_TO_IDX(nsize))) {
- vm_page_cache_free(object, OFF_TO_IDX(nsize),
- nobjsize);
}
}
object->un_pager.vnp.vnp_size = nsize;
@@ -747,6 +743,9 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count,
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;
@@ -847,6 +846,9 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count,
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. */
@@ -868,7 +870,25 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count,
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));
@@ -894,8 +914,7 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count,
for (tpindex = m[0]->pindex - 1;
tpindex >= startpindex && tpindex < m[0]->pindex;
tpindex--, i++) {
- p = vm_page_alloc(object, tpindex, VM_ALLOC_NORMAL |
- VM_ALLOC_IFNOTCACHED);
+ p = vm_page_alloc(object, tpindex, VM_ALLOC_NORMAL);
if (p == NULL) {
/* Shift the array. */
for (int j = 0; j < i; j++)
@@ -932,8 +951,7 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count,
for (tpindex = m[count - 1]->pindex + 1;
tpindex < endpindex; i++, tpindex++) {
- p = vm_page_alloc(object, tpindex, VM_ALLOC_NORMAL |
- VM_ALLOC_IFNOTCACHED);
+ p = vm_page_alloc(object, tpindex, VM_ALLOC_NORMAL);
if (p == NULL)
break;
bp->b_pages[i] = p;
@@ -953,8 +971,14 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count,
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.
@@ -993,6 +1017,13 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count,
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);