Changeset View
Changeset View
Standalone View
Standalone View
head/sys/vm/swap_pager.c
Show First 20 Lines • Show All 1,191 Lines • ▼ Show 20 Lines | swap_pager_getpages(vm_object_t object, vm_page_t *ma, int count, int *rbehind, | ||||
int *rahead) | int *rahead) | ||||
{ | { | ||||
struct buf *bp; | struct buf *bp; | ||||
vm_page_t bm, mpred, msucc, p; | vm_page_t bm, mpred, msucc, p; | ||||
vm_pindex_t pindex; | vm_pindex_t pindex; | ||||
daddr_t blk; | daddr_t blk; | ||||
int i, maxahead, maxbehind, reqcount; | int i, maxahead, maxbehind, reqcount; | ||||
VM_OBJECT_WLOCK(object); | |||||
reqcount = count; | reqcount = count; | ||||
KASSERT(object->type == OBJT_SWAP, | KASSERT(object->type == OBJT_SWAP, | ||||
("%s: object not swappable", __func__)); | ("%s: object not swappable", __func__)); | ||||
if (!swap_pager_haspage(object, ma[0]->pindex, &maxbehind, &maxahead)) | if (!swap_pager_haspage(object, ma[0]->pindex, &maxbehind, &maxahead)) { | ||||
VM_OBJECT_WUNLOCK(object); | |||||
return (VM_PAGER_FAIL); | return (VM_PAGER_FAIL); | ||||
} | |||||
KASSERT(reqcount - 1 <= maxahead, | KASSERT(reqcount - 1 <= maxahead, | ||||
("page count %d extends beyond swap block", reqcount)); | ("page count %d extends beyond swap block", reqcount)); | ||||
/* | /* | ||||
* Do not transfer any pages other than those that are xbusied | * Do not transfer any pages other than those that are xbusied | ||||
* when running during a split or collapse operation. This | * when running during a split or collapse operation. This | ||||
* prevents clustering from re-creating pages which are being | * prevents clustering from re-creating pages which are being | ||||
▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | swap_pager_getpages(vm_object_t object, vm_page_t *ma, int count, int *rbehind, | ||||
swp_pager_strategy(bp); | swp_pager_strategy(bp); | ||||
/* | /* | ||||
* Wait for the pages we want to complete. VPO_SWAPINPROG is always | * Wait for the pages we want to complete. VPO_SWAPINPROG is always | ||||
* cleared on completion. If an I/O error occurs, SWAPBLK_NONE | * cleared on completion. If an I/O error occurs, SWAPBLK_NONE | ||||
* is set in the metadata for each page in the request. | * is set in the metadata for each page in the request. | ||||
*/ | */ | ||||
VM_OBJECT_WLOCK(object); | VM_OBJECT_WLOCK(object); | ||||
/* This could be implemented more efficiently with aflags */ | |||||
while ((ma[0]->oflags & VPO_SWAPINPROG) != 0) { | while ((ma[0]->oflags & VPO_SWAPINPROG) != 0) { | ||||
ma[0]->oflags |= VPO_SWAPSLEEP; | ma[0]->oflags |= VPO_SWAPSLEEP; | ||||
VM_CNT_INC(v_intrans); | VM_CNT_INC(v_intrans); | ||||
if (VM_OBJECT_SLEEP(object, &object->handle, PSWP, | if (VM_OBJECT_SLEEP(object, &object->handle, PSWP, | ||||
"swread", hz * 20)) { | "swread", hz * 20)) { | ||||
printf( | printf( | ||||
"swap_pager: indefinite wait buffer: bufobj: %p, blkno: %jd, size: %ld\n", | "swap_pager: indefinite wait buffer: bufobj: %p, blkno: %jd, size: %ld\n", | ||||
bp->b_bufobj, (intmax_t)bp->b_blkno, bp->b_bcount); | bp->b_bufobj, (intmax_t)bp->b_blkno, bp->b_bcount); | ||||
} | } | ||||
} | } | ||||
VM_OBJECT_WUNLOCK(object); | |||||
/* | /* | ||||
* If we had an unrecoverable read error pages will not be valid. | * If we had an unrecoverable read error pages will not be valid. | ||||
*/ | */ | ||||
for (i = 0; i < reqcount; i++) | for (i = 0; i < reqcount; i++) | ||||
if (ma[i]->valid != VM_PAGE_BITS_ALL) | if (ma[i]->valid != VM_PAGE_BITS_ALL) | ||||
return (VM_PAGER_ERROR); | return (VM_PAGER_ERROR); | ||||
Show All 15 Lines | |||||
*/ | */ | ||||
static int | static int | ||||
swap_pager_getpages_async(vm_object_t object, vm_page_t *ma, int count, | swap_pager_getpages_async(vm_object_t object, vm_page_t *ma, int count, | ||||
int *rbehind, int *rahead, pgo_getpages_iodone_t iodone, void *arg) | int *rbehind, int *rahead, pgo_getpages_iodone_t iodone, void *arg) | ||||
{ | { | ||||
int r, error; | int r, error; | ||||
r = swap_pager_getpages(object, ma, count, rbehind, rahead); | r = swap_pager_getpages(object, ma, count, rbehind, rahead); | ||||
VM_OBJECT_WUNLOCK(object); | |||||
switch (r) { | switch (r) { | ||||
case VM_PAGER_OK: | case VM_PAGER_OK: | ||||
error = 0; | error = 0; | ||||
break; | break; | ||||
case VM_PAGER_ERROR: | case VM_PAGER_ERROR: | ||||
error = EIO; | error = EIO; | ||||
break; | break; | ||||
case VM_PAGER_FAIL: | case VM_PAGER_FAIL: | ||||
error = EINVAL; | error = EINVAL; | ||||
break; | break; | ||||
default: | default: | ||||
panic("unhandled swap_pager_getpages() error %d", r); | panic("unhandled swap_pager_getpages() error %d", r); | ||||
} | } | ||||
(iodone)(arg, ma, count, error); | (iodone)(arg, ma, count, error); | ||||
VM_OBJECT_WLOCK(object); | |||||
return (r); | return (r); | ||||
} | } | ||||
/* | /* | ||||
* swap_pager_putpages: | * swap_pager_putpages: | ||||
* | * | ||||
* Assign swap (if necessary) and initiate I/O on the specified pages. | * Assign swap (if necessary) and initiate I/O on the specified pages. | ||||
▲ Show 20 Lines • Show All 364 Lines • ▼ Show 20 Lines | KASSERT(object->type == OBJT_SWAP, | ||||
("%s: Object not swappable", __func__)); | ("%s: Object not swappable", __func__)); | ||||
vm_object_pip_add(object, npages); | vm_object_pip_add(object, npages); | ||||
vm_page_grab_pages(object, pindex, VM_ALLOC_NORMAL, ma, npages); | vm_page_grab_pages(object, pindex, VM_ALLOC_NORMAL, ma, npages); | ||||
for (i = j = 0;; i++) { | for (i = j = 0;; i++) { | ||||
/* Count nonresident pages, to page-in all at once. */ | /* Count nonresident pages, to page-in all at once. */ | ||||
if (i < npages && ma[i]->valid != VM_PAGE_BITS_ALL) | if (i < npages && ma[i]->valid != VM_PAGE_BITS_ALL) | ||||
continue; | continue; | ||||
if (j < i) { | if (j < i) { | ||||
VM_OBJECT_WUNLOCK(object); | |||||
/* Page-in nonresident pages. Mark for laundering. */ | /* Page-in nonresident pages. Mark for laundering. */ | ||||
if (swap_pager_getpages(object, &ma[j], i - j, NULL, | if (swap_pager_getpages(object, &ma[j], i - j, NULL, | ||||
NULL) != VM_PAGER_OK) | NULL) != VM_PAGER_OK) | ||||
panic("%s: read from swap failed", __func__); | panic("%s: read from swap failed", __func__); | ||||
VM_OBJECT_WLOCK(object); | |||||
do { | do { | ||||
swp_pager_force_launder(ma[j]); | swp_pager_force_launder(ma[j]); | ||||
} while (++j < i); | } while (++j < i); | ||||
} | } | ||||
if (i == npages) | if (i == npages) | ||||
break; | break; | ||||
/* Mark dirty a resident page. */ | /* Mark dirty a resident page. */ | ||||
swp_pager_force_dirty(ma[j++]); | swp_pager_force_dirty(ma[j++]); | ||||
▲ Show 20 Lines • Show All 1,329 Lines • Show Last 20 Lines |