Changeset View
Standalone View
sys/vm/swap_pager.c
Show First 20 Lines • Show All 532 Lines • ▼ Show 20 Lines | swap_pager_swap_init(void) | ||||
* devices but is probably a little low if you have more. Even so, | * devices but is probably a little low if you have more. Even so, | ||||
* a higher value would probably generate only a limited improvement | * a higher value would probably generate only a limited improvement | ||||
* with three or four active swap devices since the system does not | * with three or four active swap devices since the system does not | ||||
* typically have to pageout at extreme bandwidths. We will want | * typically have to pageout at extreme bandwidths. We will want | ||||
* at least 2 per swap devices, and 4 is a pretty good value if you | * at least 2 per swap devices, and 4 is a pretty good value if you | ||||
* have one NFS swap device due to the command/ack latency over NFS. | * have one NFS swap device due to the command/ack latency over NFS. | ||||
* So it all works out pretty well. | * So it all works out pretty well. | ||||
*/ | */ | ||||
nsw_cluster_max = min((MAXPHYS/PAGE_SIZE), MAX_PAGEOUT_CLUSTER); | nsw_cluster_max = min((MAXPHYS/PAGE_SIZE), MAX_PAGEOUT_CLUSTER); | ||||
alc: Keep this and the above change separate. The parentheses around MAXPHYS / PAGE_SIZE are not… | |||||
nsw_wcount_async = 4; | nsw_wcount_async = 4; | ||||
nsw_wcount_async_max = nsw_wcount_async; | nsw_wcount_async_max = nsw_wcount_async; | ||||
mtx_init(&swbuf_mtx, "async swbuf mutex", NULL, MTX_DEF); | mtx_init(&swbuf_mtx, "async swbuf mutex", NULL, MTX_DEF); | ||||
swwbuf_zone = pbuf_zsecond_create("swwbuf", nswbuf / 4); | swwbuf_zone = pbuf_zsecond_create("swwbuf", nswbuf / 4); | ||||
swrbuf_zone = pbuf_zsecond_create("swrbuf", nswbuf / 2); | swrbuf_zone = pbuf_zsecond_create("swrbuf", nswbuf / 2); | ||||
▲ Show 20 Lines • Show All 1,121 Lines • ▼ Show 20 Lines | swp_pager_force_launder(vm_page_t m) | ||||
vm_page_dirty(m); | vm_page_dirty(m); | ||||
vm_page_lock(m); | vm_page_lock(m); | ||||
vm_page_launder(m); | vm_page_launder(m); | ||||
vm_page_unlock(m); | vm_page_unlock(m); | ||||
vm_page_xunbusy(m); | vm_page_xunbusy(m); | ||||
} | } | ||||
/* | /* | ||||
* SWP_PAGER_FORCE_PAGEIN() - force a swap block to be paged in | * SWP_PAGER_FORCE_PAGEIN() - force swap blocks to be paged in | ||||
* | * | ||||
* This routine dissociates the page at the given index within an object | * This routine dissociates pages starting at the given index within an | ||||
* from its backing store, paging it in if it does not reside in memory. | * object from their backing store, paging them in if they do not reside | ||||
* If the page is paged in, it is marked dirty and placed in the laundry | * in memory. Page that are paged in are marked dirty and placed in the | ||||
Done Inline Actions"Page that ..." -> "Pages that ..." alc: "Page that ..." -> "Pages that ..." | |||||
* queue. The page is marked dirty because it no longer has backing | * laundry queue. Pages are marked dirty because they no longer have | ||||
* store. It is placed in the laundry queue because it has not been | * backing store. They are placed in the laundry queue because they have | ||||
* accessed recently. Otherwise, it would already reside in memory. | * not been accessed recently. Otherwise, they would already reside in | ||||
* | * memory. | ||||
* We also attempt to swap in all other pages in the swap block. | |||||
* However, we only guarantee that the one at the specified index is | |||||
* paged in. | |||||
* | |||||
* XXX - The code to page the whole block in doesn't work, so we | |||||
* revert to the one-by-one behavior for now. Sigh. | |||||
*/ | */ | ||||
static void | static void | ||||
swp_pager_force_pagein(vm_object_t object, vm_pindex_t pindex) | swp_pager_force_pagein(vm_object_t object, vm_pindex_t pindex, int npages) | ||||
Done Inline ActionsI would also KASSERT that npages is greater than zero. alc: I would also KASSERT that npages is greater than zero. | |||||
{ | { | ||||
vm_page_t m; | vm_page_t ma[npages]; | ||||
int i, j; | |||||
vm_object_pip_add(object, 1); | KASSERT(npages <= MAXPHYS/PAGE_SIZE, | ||||
m = vm_page_grab(object, pindex, VM_ALLOC_NORMAL); | ("%s: Too many pages: %d", __func__, npages)); | ||||
if (m->valid == VM_PAGE_BITS_ALL) { | if (npages == 0) | ||||
vm_object_pip_wakeup(object); | |||||
swp_pager_force_dirty(m); | |||||
vm_pager_page_unswapped(m); | |||||
return; | return; | ||||
vm_object_pip_add(object, npages); | |||||
vm_page_grab_pages(object, pindex, VM_ALLOC_NORMAL, ma, npages); | |||||
for (i = j = 0;; i++) { | |||||
/* Count nonresident pages, to page-in all at once. */ | |||||
if (i < npages && ma[i]->valid != VM_PAGE_BITS_ALL) | |||||
continue; | |||||
if (j < i) { | |||||
/* Page-in nonresident pages. Mark for laundering. */ | |||||
if (swap_pager_getpages(object, &ma[j], i - j, NULL, | |||||
NULL) != VM_PAGER_OK) | |||||
panic("%s: read from swap failed", __func__); | |||||
do { | |||||
vm_object_pip_wakeup(object); | |||||
Done Inline ActionsGiven that we are within swap_pager.c, I would call swap_pager_unswapped() directly. Moreover, it would be reasonable to perform that call as the last statement in swp_pager_force_launder() and swp_pager_force_dirty(). (Marking the page dirty and calling "unswapped" on it are logically related.) alc: Given that we are within swap_pager.c, I would call swap_pager_unswapped() directly. Moreover… | |||||
swp_pager_force_launder(ma[j]); | |||||
vm_pager_page_unswapped(ma[j]); | |||||
} while (++j < i); | |||||
} | } | ||||
if (i == npages) | |||||
if (swap_pager_getpages(object, &m, 1, NULL, NULL) != VM_PAGER_OK) | break; | ||||
panic("swap_pager_force_pagein: read from swap failed");/*XXX*/ | /* Mark dirty a resident page. */ | ||||
Done Inline ActionsStyle(9) alc: Style(9) | |||||
vm_object_pip_wakeup(object); | vm_object_pip_wakeup(object); | ||||
swp_pager_force_launder(m); | swp_pager_force_dirty(ma[j]); | ||||
vm_pager_page_unswapped(m); | vm_pager_page_unswapped(ma[j++]); | ||||
} | } | ||||
/* vm_object_pip_wakeupn(object, npages); */ | |||||
Done Inline ActionsGo ahead and replace the one-by-one wakeups with this call. alc: Go ahead and replace the one-by-one wakeups with this call. | |||||
} | |||||
/* | /* | ||||
* swap_pager_swapoff_object: | * swap_pager_swapoff_object: | ||||
* | * | ||||
* Page in all of the pages that have been paged out for an object | * Page in all of the pages that have been paged out for an object | ||||
* from a given swap device. | * from a swap device. | ||||
Done Inline Actions"from" -> "to" alc: "from" -> "to" | |||||
*/ | */ | ||||
static void | static void | ||||
swap_pager_swapoff_object(struct swdevt *sp, vm_object_t object) | swap_pager_swapoff_object(struct swdevt *sp, vm_object_t object) | ||||
{ | { | ||||
struct swblk *sb; | struct swblk *sb; | ||||
Not Done Inline ActionsI think we traditionally put {} around the body of do/while loops, always. kib: I think we traditionally put {} around the body of do/while loops, always. | |||||
vm_pindex_t pi; | vm_pindex_t pi, s_pindex; | ||||
daddr_t blk, n_blks, s_blk; | |||||
int i; | int i; | ||||
bool ondev; | |||||
s_blk = SWAPBLK_NONE; | |||||
s_pindex = 0; | |||||
n_blks = 0; | |||||
for (pi = 0; (sb = SWAP_PCTRIE_LOOKUP_GE( | for (pi = 0; (sb = SWAP_PCTRIE_LOOKUP_GE( | ||||
&object->un_pager.swp.swp_blks, pi)) != NULL; ) { | &object->un_pager.swp.swp_blks, pi)) != NULL; ) { | ||||
pi = sb->p + SWAP_META_PAGES; | |||||
for (i = 0; i < SWAP_META_PAGES; i++) { | for (i = 0; i < SWAP_META_PAGES; i++) { | ||||
if (sb->d[i] == SWAPBLK_NONE) | blk = sb->d[i]; | ||||
ondev = swp_pager_isondev(blk, sp); | |||||
if (ondev && | |||||
n_blks < MAXPHYS/PAGE_SIZE && | |||||
s_blk + n_blks == blk && | |||||
s_pindex + n_blks == sb->p + i) { | |||||
Done Inline ActionsSpelling: "accumlated" alc: Spelling: "accumlated" | |||||
++n_blks; | |||||
continue; | continue; | ||||
if (swp_pager_isondev(sb->d[i], sp)) | |||||
swp_pager_force_pagein(object, sb->p + i); | |||||
} | } | ||||
swp_pager_force_pagein(object, s_pindex, n_blks); | |||||
s_blk = ondev ? blk : SWAPBLK_NONE; | |||||
s_pindex = sb->p + i; | |||||
Done Inline ActionsPlease add a comment here explaining why this test is necessary. alc: Please add a comment here explaining why this test is necessary. | |||||
n_blks = (s_blk != SWAPBLK_NONE) ? 1 : 0; | |||||
} | } | ||||
Not Done Inline ActionsI would add "()" after "swp_pager_force_pagein" to make it unambiguous that you are talking about a function. (There is no need to repost a new version of this patch here. Just add the "()" before committing.) alc: I would add "()" after "swp_pager_force_pagein" to make it unambiguous that you are talking… | |||||
pi = sb->p + SWAP_META_PAGES; | |||||
} | |||||
swp_pager_force_pagein(object, s_pindex, n_blks); | |||||
} | } | ||||
Done Inline ActionsPlease add a comment here explaining why a "restart" is necessary. alc: Please add a comment here explaining why a "restart" is necessary. | |||||
/* | /* | ||||
* swap_pager_swapoff: | * swap_pager_swapoff: | ||||
* | * | ||||
Done Inline ActionsAdd a blank line before this comment. alc: Add a blank line before this comment. | |||||
* Page in all of the pages that have been paged out to the | * Page in all of the pages that have been paged out to the | ||||
* given device. The corresponding blocks in the bitmap must be | * given device. The corresponding blocks in the bitmap must be | ||||
Done Inline Actions"them all out" -> "them all in" alc: "them all out" -> "them all in" | |||||
* marked as allocated and the device must be flagged SW_CLOSING. | * marked as allocated and the device must be flagged SW_CLOSING. | ||||
* There may be no processes swapped out to the device. | * There may be no processes swapped out to the device. | ||||
* | * | ||||
* This routine may block. | * This routine may block. | ||||
*/ | */ | ||||
static void | static void | ||||
swap_pager_swapoff(struct swdevt *sp) | swap_pager_swapoff(struct swdevt *sp) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 1,205 Lines • Show Last 20 Lines |
Keep this and the above change separate. The parentheses around MAXPHYS / PAGE_SIZE are not required.