Changeset View
Changeset View
Standalone View
Standalone View
head/sys/vm/vnode_pager.c
Show First 20 Lines • Show All 811 Lines • ▼ Show 20 Lines | #endif | ||||
object = vp->v_object; | object = vp->v_object; | ||||
foff = IDX_TO_OFF(m[0]->pindex); | foff = IDX_TO_OFF(m[0]->pindex); | ||||
bsize = vp->v_mount->mnt_stat.f_iosize; | bsize = vp->v_mount->mnt_stat.f_iosize; | ||||
pagesperblock = bsize / PAGE_SIZE; | pagesperblock = bsize / PAGE_SIZE; | ||||
KASSERT(foff < object->un_pager.vnp.vnp_size, | KASSERT(foff < object->un_pager.vnp.vnp_size, | ||||
("%s: page %p offset beyond vp %p size", __func__, m[0], vp)); | ("%s: page %p offset beyond vp %p size", __func__, m[0], vp)); | ||||
KASSERT(count <= nitems(bp->b_pages), | KASSERT(count <= atop(maxphys), | ||||
("%s: requested %d pages", __func__, count)); | ("%s: requested %d pages", __func__, count)); | ||||
/* | /* | ||||
* The last page has valid blocks. Invalid part can only | * The last page has valid blocks. Invalid part can only | ||||
* exist at the end of file, and the page is made fully valid | * exist at the end of file, and the page is made fully valid | ||||
* by zeroing in vm_pager_get_pages(). | * by zeroing in vm_pager_get_pages(). | ||||
*/ | */ | ||||
if (!vm_page_none_valid(m[count - 1]) && --count == 0) { | if (!vm_page_none_valid(m[count - 1]) && --count == 0) { | ||||
if (iodone != NULL) | if (iodone != NULL) | ||||
iodone(arg, m, 1, 0); | iodone(arg, m, 1, 0); | ||||
return (VM_PAGER_OK); | return (VM_PAGER_OK); | ||||
} | } | ||||
bp = uma_zalloc(vnode_pbuf_zone, M_WAITOK); | bp = uma_zalloc(vnode_pbuf_zone, M_WAITOK); | ||||
MPASS((bp->b_flags & B_MAXPHYS) != 0); | |||||
/* | /* | ||||
* Get the underlying device blocks for the file with VOP_BMAP(). | * Get the underlying device blocks for the file with VOP_BMAP(). | ||||
* If the file system doesn't support VOP_BMAP, use old way of | * If the file system doesn't support VOP_BMAP, use old way of | ||||
* getting pages via VOP_READ. | * getting pages via VOP_READ. | ||||
*/ | */ | ||||
error = VOP_BMAP(vp, foff / bsize, &bo, &bp->b_blkno, &after, &before); | error = VOP_BMAP(vp, foff / bsize, &bo, &bp->b_blkno, &after, &before); | ||||
if (error == EOPNOTSUPP) { | if (error == EOPNOTSUPP) { | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | #endif | ||||
rbehind = min(rbehind, before); | rbehind = min(rbehind, before); | ||||
rbehind = min(rbehind, m[0]->pindex); | rbehind = min(rbehind, m[0]->pindex); | ||||
rahead = min(rahead, after); | rahead = min(rahead, after); | ||||
rahead = min(rahead, object->size - m[count - 1]->pindex); | rahead = min(rahead, object->size - m[count - 1]->pindex); | ||||
/* | /* | ||||
* Check that total amount of pages fit into buf. Trim rbehind and | * Check that total amount of pages fit into buf. Trim rbehind and | ||||
* rahead evenly if not. | * rahead evenly if not. | ||||
*/ | */ | ||||
if (rbehind + rahead + count > nitems(bp->b_pages)) { | if (rbehind + rahead + count > atop(maxphys)) { | ||||
int trim, sum; | int trim, sum; | ||||
trim = rbehind + rahead + count - nitems(bp->b_pages) + 1; | trim = rbehind + rahead + count - atop(maxphys) + 1; | ||||
sum = rbehind + rahead; | sum = rbehind + rahead; | ||||
if (rbehind == before) { | if (rbehind == before) { | ||||
/* Roundup rbehind trim to block size. */ | /* Roundup rbehind trim to block size. */ | ||||
rbehind -= roundup(trim * rbehind / sum, pagesperblock); | rbehind -= roundup(trim * rbehind / sum, pagesperblock); | ||||
if (rbehind < 0) | if (rbehind < 0) | ||||
rbehind = 0; | rbehind = 0; | ||||
} else | } else | ||||
rbehind -= trim * rbehind / sum; | rbehind -= trim * rbehind / sum; | ||||
rahead -= trim * rahead / sum; | rahead -= trim * rahead / sum; | ||||
} | } | ||||
KASSERT(rbehind + rahead + count <= nitems(bp->b_pages), | KASSERT(rbehind + rahead + count <= atop(maxphys), | ||||
("%s: behind %d ahead %d count %d", __func__, | ("%s: behind %d ahead %d count %d maxphys %lu", __func__, | ||||
rbehind, rahead, count)); | rbehind, rahead, count, maxphys)); | ||||
/* | /* | ||||
* Fill in the bp->b_pages[] array with requested and optional | * Fill in the bp->b_pages[] array with requested and optional | ||||
* read behind or read ahead pages. Read behind pages are looked | * read behind or read ahead pages. Read behind pages are looked | ||||
* up in a backward direction, down to a first cached page. Same | * up in a backward direction, down to a first cached page. Same | ||||
* for read ahead pages, but there is no need to shift the array | * for read ahead pages, but there is no need to shift the array | ||||
* in case of encountering a cached page. | * in case of encountering a cached page. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | #endif | ||||
/* Report back actual behind/ahead read. */ | /* Report back actual behind/ahead read. */ | ||||
if (a_rbehind) | if (a_rbehind) | ||||
*a_rbehind = bp->b_pgbefore; | *a_rbehind = bp->b_pgbefore; | ||||
if (a_rahead) | if (a_rahead) | ||||
*a_rahead = bp->b_pgafter; | *a_rahead = bp->b_pgafter; | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
KASSERT(bp->b_npages <= nitems(bp->b_pages), | KASSERT(bp->b_npages <= atop(maxphys), | ||||
("%s: buf %p overflowed", __func__, bp)); | ("%s: buf %p overflowed", __func__, bp)); | ||||
for (int j = 1, prev = 0; j < bp->b_npages; j++) { | for (int j = 1, prev = 0; j < bp->b_npages; j++) { | ||||
if (bp->b_pages[j] == bogus_page) | if (bp->b_pages[j] == bogus_page) | ||||
continue; | continue; | ||||
KASSERT(bp->b_pages[j]->pindex - bp->b_pages[prev]->pindex == | KASSERT(bp->b_pages[j]->pindex - bp->b_pages[prev]->pindex == | ||||
j - prev, ("%s: pages array not consecutive, bp %p", | j - prev, ("%s: pages array not consecutive, bp %p", | ||||
__func__, bp)); | __func__, bp)); | ||||
prev = j; | prev = j; | ||||
▲ Show 20 Lines • Show All 578 Lines • Show Last 20 Lines |