Changeset View
Changeset View
Standalone View
Standalone View
sys/vm/swap_pager.c
Show First 20 Lines • Show All 315 Lines • ▼ Show 20 Lines | swap_release_by_cred(vm_ooffset_t decr, struct ucred *cred) | ||||
if (prev < pdecr) | if (prev < pdecr) | ||||
printf("negative vmsize for uid = %d\n", uip->ui_uid); | printf("negative vmsize for uid = %d\n", uip->ui_uid); | ||||
#ifdef RACCT | #ifdef RACCT | ||||
if (racct_enable) | if (racct_enable) | ||||
racct_sub_cred(cred, RACCT_SWAP, decr); | racct_sub_cred(cred, RACCT_SWAP, decr); | ||||
#endif | #endif | ||||
} | } | ||||
#define SWM_POP 0x01 /* pop out */ | |||||
static int swap_pager_full = 2; /* swap space exhaustion (task killing) */ | static int swap_pager_full = 2; /* swap space exhaustion (task killing) */ | ||||
static int swap_pager_almost_full = 1; /* swap space exhaustion (w/hysteresis)*/ | static int swap_pager_almost_full = 1; /* swap space exhaustion (w/hysteresis)*/ | ||||
static struct mtx swbuf_mtx; /* to sync nsw_wcount_async */ | static struct mtx swbuf_mtx; /* to sync nsw_wcount_async */ | ||||
static int nsw_wcount_async; /* limit async write buffers */ | static int nsw_wcount_async; /* limit async write buffers */ | ||||
static int nsw_wcount_async_max;/* assigned maximum */ | static int nsw_wcount_async_max;/* assigned maximum */ | ||||
static int nsw_cluster_max; /* maximum VOP I/O allowed */ | static int nsw_cluster_max; /* maximum VOP I/O allowed */ | ||||
static int sysctl_swap_async_max(SYSCTL_HANDLER_ARGS); | static int sysctl_swap_async_max(SYSCTL_HANDLER_ARGS); | ||||
▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | |||||
static void swp_pager_freeswapspace(daddr_t blk, daddr_t npages); | static void swp_pager_freeswapspace(daddr_t blk, daddr_t npages); | ||||
static daddr_t swp_pager_getswapspace(int *npages, int limit); | static daddr_t swp_pager_getswapspace(int *npages, int limit); | ||||
/* | /* | ||||
* Metadata functions | * Metadata functions | ||||
*/ | */ | ||||
static daddr_t swp_pager_meta_build(vm_object_t, vm_pindex_t, daddr_t); | static daddr_t swp_pager_meta_build(vm_object_t, vm_pindex_t, daddr_t); | ||||
static void swp_pager_meta_free(vm_object_t, vm_pindex_t, vm_pindex_t); | static void swp_pager_meta_free(vm_object_t, vm_pindex_t, vm_pindex_t); | ||||
static void swp_pager_meta_copy_free(vm_object_t src, vm_object_t dst, | |||||
vm_pindex_t, vm_pindex_t); | |||||
static void swp_pager_meta_free_all(vm_object_t); | static void swp_pager_meta_free_all(vm_object_t); | ||||
static daddr_t swp_pager_meta_ctl(vm_object_t, vm_pindex_t, int); | static daddr_t swp_pager_meta_lookup(vm_object_t, vm_pindex_t); | ||||
static daddr_t swp_pager_meta_remove(vm_object_t, vm_pindex_t); | |||||
static void | static void | ||||
swp_pager_init_freerange(daddr_t *start, daddr_t *num) | swp_pager_init_freerange(daddr_t *start, daddr_t *num) | ||||
{ | { | ||||
*start = SWAPBLK_NONE; | *start = SWAPBLK_NONE; | ||||
*num = 0; | *num = 0; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 493 Lines • ▼ Show 20 Lines | for (j = 0; j < n; ++j) { | ||||
addr); | addr); | ||||
} | } | ||||
} | } | ||||
swp_pager_freeswapspace(s_free, n_free); | swp_pager_freeswapspace(s_free, n_free); | ||||
VM_OBJECT_WUNLOCK(object); | VM_OBJECT_WUNLOCK(object); | ||||
return (0); | return (0); | ||||
} | } | ||||
static bool | |||||
swp_pager_copy_source(vm_object_t srcobject, vm_object_t dstobject, | |||||
vm_pindex_t pindex, daddr_t addr) | |||||
{ | |||||
daddr_t dstaddr; | |||||
if (dstobject == NULL || | |||||
swp_pager_meta_lookup(dstobject, pindex) != SWAPBLK_NONE) { | |||||
/* | /* | ||||
* Destination has valid swapblk or it is represented by a | |||||
* resident page. Caller should destroy the source block. | |||||
kib: How the 'represented by a resident page' part is checked ? | |||||
*/ | |||||
return (false); | |||||
Not Done Inline ActionsI don't think that the comment about the destination not being resident is guaranteed to be true. alc: I don't think that the comment about the destination not being resident is guaranteed to be… | |||||
} | |||||
/* | |||||
* Destination has no swapblk and is not resident, copy source. | |||||
* | |||||
* swp_pager_meta_build() can sleep. | |||||
Done Inline ActionsI do not think this blank comment line is useful. kib: I do not think this blank comment line is useful. | |||||
*/ | |||||
vm_object_pip_add(srcobject, 1); | |||||
VM_OBJECT_WUNLOCK(srcobject); | |||||
vm_object_pip_add(dstobject, 1); | |||||
dstaddr = swp_pager_meta_build(dstobject, pindex, addr); | |||||
KASSERT(dstaddr == SWAPBLK_NONE, | |||||
("Unexpected destination swapblk")); | |||||
vm_object_pip_wakeup(dstobject); | |||||
VM_OBJECT_WLOCK(srcobject); | |||||
vm_object_pip_wakeup(srcobject); | |||||
return (true); | |||||
} | |||||
/* | |||||
* SWAP_PAGER_COPY() - copy blocks from source pager to destination pager | * SWAP_PAGER_COPY() - copy blocks from source pager to destination pager | ||||
* and destroy the source. | * and destroy the source. | ||||
* | * | ||||
* Copy any valid swapblks from the source to the destination. In | * Copy any valid swapblks from the source to the destination. In | ||||
* cases where both the source and destination have a valid swapblk, | * cases where both the source and destination have a valid swapblk, | ||||
* we keep the destination's. | * we keep the destination's. | ||||
* | * | ||||
* This routine is allowed to sleep. It may sleep allocating metadata | * This routine is allowed to sleep. It may sleep allocating metadata | ||||
* indirectly through swp_pager_meta_build() or if paging is still in | * indirectly through swp_pager_meta_build() or if paging is still in | ||||
* progress on the source. | * progress on the source. | ||||
* | * | ||||
* The source object contains no vm_page_t's (which is just as well) | * The source object contains no vm_page_t's (which is just as well) | ||||
* | * | ||||
* The source object is of type OBJT_SWAP. | * The source object is of type OBJT_SWAP. | ||||
* | * | ||||
* The source and destination objects must be locked. | * The source and destination objects must be locked. | ||||
* Both object locks may temporarily be released. | * Both object locks may temporarily be released. | ||||
*/ | */ | ||||
void | void | ||||
swap_pager_copy(vm_object_t srcobject, vm_object_t dstobject, | swap_pager_copy(vm_object_t srcobject, vm_object_t dstobject, | ||||
vm_pindex_t offset, int destroysource) | vm_pindex_t offset, int destroysource) | ||||
{ | { | ||||
vm_pindex_t i; | |||||
daddr_t dstaddr, n_free, s_free, srcaddr; | |||||
VM_OBJECT_ASSERT_WLOCKED(srcobject); | VM_OBJECT_ASSERT_WLOCKED(srcobject); | ||||
VM_OBJECT_ASSERT_WLOCKED(dstobject); | VM_OBJECT_ASSERT_WLOCKED(dstobject); | ||||
/* | /* | ||||
* If destroysource is set, we remove the source object from the | * If destroysource is set, we remove the source object from the | ||||
* swap_pager internal queue now. | * swap_pager internal queue now. | ||||
*/ | */ | ||||
Show All 10 Lines | if (destroysource && srcobject->handle != NULL) { | ||||
vm_object_pip_wakeup(dstobject); | vm_object_pip_wakeup(dstobject); | ||||
VM_OBJECT_WLOCK(srcobject); | VM_OBJECT_WLOCK(srcobject); | ||||
vm_object_pip_wakeup(srcobject); | vm_object_pip_wakeup(srcobject); | ||||
} | } | ||||
/* | /* | ||||
* Transfer source to destination. | * Transfer source to destination. | ||||
*/ | */ | ||||
swp_pager_init_freerange(&s_free, &n_free); | swp_pager_meta_copy_free(srcobject, dstobject, offset, dstobject->size); | ||||
for (i = 0; i < dstobject->size; ++i) { | |||||
srcaddr = swp_pager_meta_ctl(srcobject, i + offset, SWM_POP); | |||||
if (srcaddr == SWAPBLK_NONE) | |||||
continue; | |||||
dstaddr = swp_pager_meta_ctl(dstobject, i, 0); | |||||
if (dstaddr != SWAPBLK_NONE) { | |||||
/* | |||||
* Destination has valid swapblk or it is represented | |||||
* by a resident page. We destroy the source block. | |||||
*/ | |||||
swp_pager_update_freerange(&s_free, &n_free, srcaddr); | |||||
continue; | |||||
} | |||||
/* | /* | ||||
* Destination has no swapblk and is not resident, | |||||
* copy source. | |||||
* | |||||
* swp_pager_meta_build() can sleep. | |||||
*/ | |||||
vm_object_pip_add(srcobject, 1); | |||||
VM_OBJECT_WUNLOCK(srcobject); | |||||
vm_object_pip_add(dstobject, 1); | |||||
dstaddr = swp_pager_meta_build(dstobject, i, srcaddr); | |||||
KASSERT(dstaddr == SWAPBLK_NONE, | |||||
("Unexpected destination swapblk")); | |||||
vm_object_pip_wakeup(dstobject); | |||||
VM_OBJECT_WLOCK(srcobject); | |||||
vm_object_pip_wakeup(srcobject); | |||||
} | |||||
swp_pager_freeswapspace(s_free, n_free); | |||||
/* | |||||
* Free left over swap blocks in source. | * Free left over swap blocks in source. | ||||
* | * | ||||
* We have to revert the type to OBJT_DEFAULT so we do not accidentally | * We have to revert the type to OBJT_DEFAULT so we do not accidentally | ||||
* double-remove the object from the swap queues. | * double-remove the object from the swap queues. | ||||
*/ | */ | ||||
if (destroysource) { | if (destroysource) { | ||||
swp_pager_meta_free_all(srcobject); | swp_pager_meta_free_all(srcobject); | ||||
/* | /* | ||||
Show All 23 Lines | swap_pager_haspage(vm_object_t object, vm_pindex_t pindex, int *before, | ||||
daddr_t blk, blk0; | daddr_t blk, blk0; | ||||
int i; | int i; | ||||
VM_OBJECT_ASSERT_LOCKED(object); | VM_OBJECT_ASSERT_LOCKED(object); | ||||
/* | /* | ||||
* do we have good backing store at the requested index ? | * do we have good backing store at the requested index ? | ||||
*/ | */ | ||||
blk0 = swp_pager_meta_ctl(object, pindex, 0); | blk0 = swp_pager_meta_lookup(object, pindex); | ||||
if (blk0 == SWAPBLK_NONE) { | if (blk0 == SWAPBLK_NONE) { | ||||
if (before) | if (before) | ||||
*before = 0; | *before = 0; | ||||
if (after) | if (after) | ||||
*after = 0; | *after = 0; | ||||
return (FALSE); | return (FALSE); | ||||
} | } | ||||
/* | /* | ||||
* find backwards-looking contiguous good backing store | * find backwards-looking contiguous good backing store | ||||
*/ | */ | ||||
if (before != NULL) { | if (before != NULL) { | ||||
for (i = 1; i < SWB_NPAGES; i++) { | for (i = 1; i < SWB_NPAGES; i++) { | ||||
if (i > pindex) | if (i > pindex) | ||||
break; | break; | ||||
blk = swp_pager_meta_ctl(object, pindex - i, 0); | blk = swp_pager_meta_lookup(object, pindex - i); | ||||
if (blk != blk0 - i) | if (blk != blk0 - i) | ||||
break; | break; | ||||
} | } | ||||
*before = i - 1; | *before = i - 1; | ||||
} | } | ||||
/* | /* | ||||
* find forward-looking contiguous good backing store | * find forward-looking contiguous good backing store | ||||
*/ | */ | ||||
if (after != NULL) { | if (after != NULL) { | ||||
for (i = 1; i < SWB_NPAGES; i++) { | for (i = 1; i < SWB_NPAGES; i++) { | ||||
blk = swp_pager_meta_ctl(object, pindex + i, 0); | blk = swp_pager_meta_lookup(object, pindex + i); | ||||
if (blk != blk0 + i) | if (blk != blk0 + i) | ||||
break; | break; | ||||
} | } | ||||
*after = i - 1; | *after = i - 1; | ||||
} | } | ||||
return (TRUE); | return (TRUE); | ||||
} | } | ||||
Show All 16 Lines | |||||
* | * | ||||
* The object containing the page must be locked. | * The object containing the page must be locked. | ||||
*/ | */ | ||||
static void | static void | ||||
swap_pager_unswapped(vm_page_t m) | swap_pager_unswapped(vm_page_t m) | ||||
{ | { | ||||
daddr_t srcaddr; | daddr_t srcaddr; | ||||
srcaddr = swp_pager_meta_ctl(m->object, m->pindex, SWM_POP); | srcaddr = swp_pager_meta_remove(m->object, m->pindex); | ||||
if (srcaddr != SWAPBLK_NONE) | if (srcaddr != SWAPBLK_NONE) | ||||
swp_pager_freeswapspace(srcaddr, 1); | swp_pager_freeswapspace(srcaddr, 1); | ||||
} | } | ||||
/* | /* | ||||
* swap_pager_getpages() - bring pages in from swap | * swap_pager_getpages() - bring pages in from swap | ||||
* | * | ||||
* Attempt to page in the pages in array "ma" of length "count". The | * Attempt to page in the pages in array "ma" of length "count". The | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | swap_pager_getpages(vm_object_t object, vm_page_t *ma, int count, int *rbehind, | ||||
if (rbehind != NULL) | if (rbehind != NULL) | ||||
count += *rbehind; | count += *rbehind; | ||||
if (rahead != NULL) | if (rahead != NULL) | ||||
count += *rahead; | count += *rahead; | ||||
vm_object_pip_add(object, count); | vm_object_pip_add(object, count); | ||||
pindex = bm->pindex; | pindex = bm->pindex; | ||||
blk = swp_pager_meta_ctl(object, pindex, 0); | blk = swp_pager_meta_lookup(object, pindex); | ||||
KASSERT(blk != SWAPBLK_NONE, | KASSERT(blk != SWAPBLK_NONE, | ||||
("no swap blocking containing %p(%jx)", object, (uintmax_t)pindex)); | ("no swap blocking containing %p(%jx)", object, (uintmax_t)pindex)); | ||||
VM_OBJECT_WUNLOCK(object); | VM_OBJECT_WUNLOCK(object); | ||||
bp = uma_zalloc(swrbuf_zone, M_WAITOK); | bp = uma_zalloc(swrbuf_zone, M_WAITOK); | ||||
/* Pages cannot leave the object while busy. */ | /* Pages cannot leave the object while busy. */ | ||||
for (i = 0, p = bm; i < count; i++, p = TAILQ_NEXT(p, listq)) { | for (i = 0, p = bm; i < count; i++, p = TAILQ_NEXT(p, listq)) { | ||||
MPASS(p->pindex == bm->pindex + i); | MPASS(p->pindex == bm->pindex + i); | ||||
▲ Show 20 Lines • Show All 772 Lines • ▼ Show 20 Lines | if (swapblk == SWAPBLK_NONE && | ||||
swp_pager_swblk_empty(sb, 0, SWAP_META_PAGES)) { | swp_pager_swblk_empty(sb, 0, SWAP_META_PAGES)) { | ||||
SWAP_PCTRIE_REMOVE(&object->un_pager.swp.swp_blks, rdpi); | SWAP_PCTRIE_REMOVE(&object->un_pager.swp.swp_blks, rdpi); | ||||
uma_zfree(swblk_zone, sb); | uma_zfree(swblk_zone, sb); | ||||
} | } | ||||
return (prev_swapblk); | return (prev_swapblk); | ||||
} | } | ||||
/* | /* | ||||
* SWP_PAGER_META_FREE() - free a range of blocks in the object's swap metadata | * SWP_PAGER_META_COPY_FREE() - free a range of blocks in the srcobject's swap | ||||
* metadata, or copy it into dstobject. | |||||
* | * | ||||
* The requested range of blocks is freed, with any associated swap | * The requested range of blocks is freed, with any associated swap | ||||
* returned to the swap bitmap. | * returned to the swap bitmap. | ||||
Done Inline ActionsI think this part of the description is not longer valid. kib: I think this part of the description is not longer valid. | |||||
* | |||||
* This routine will free swap metadata structures as they are cleaned | |||||
* out. This routine does *NOT* operate on swap metadata associated | |||||
* with resident pages. | |||||
*/ | */ | ||||
Done Inline ActionsI don't think that this sentence is true. alc: I don't think that this sentence is true. | |||||
static void | static void | ||||
swp_pager_meta_free(vm_object_t object, vm_pindex_t pindex, vm_pindex_t count) | swp_pager_meta_copy_free(vm_object_t srcobject, vm_object_t dstobject, | ||||
vm_pindex_t pindex, vm_pindex_t count) | |||||
Done Inline ActionsIndent of the continuation line is wrong. kib: Indent of the continuation line is wrong. | |||||
Done Inline ActionsThis function now either transfer to another object or free. How about swp_pager_meta_xfer / swp_pager_meta_transfer with implication of transferring to NULL is a removal? swp_pager_meta_free() is exclusive use for free. ota_j.email.ne.jp: This function now either transfer to another object or free.
The source doesn't keep at all.
I… | |||||
{ | { | ||||
struct swblk *sb; | struct swblk *sb; | ||||
daddr_t n_free, s_free; | daddr_t n_free, s_free; | ||||
vm_pindex_t last; | vm_pindex_t offset, last; | ||||
int i, limit, start; | int i, limit, start; | ||||
VM_OBJECT_ASSERT_WLOCKED(object); | VM_OBJECT_ASSERT_WLOCKED(srcobject); | ||||
if (object->type != OBJT_SWAP || count == 0) | if (srcobject->type != OBJT_SWAP || count == 0) | ||||
return; | return; | ||||
swp_pager_init_freerange(&s_free, &n_free); | swp_pager_init_freerange(&s_free, &n_free); | ||||
offset = pindex; | |||||
last = pindex + count; | last = pindex + count; | ||||
for (;;) { | for (;;) { | ||||
sb = SWAP_PCTRIE_LOOKUP_GE(&object->un_pager.swp.swp_blks, | sb = SWAP_PCTRIE_LOOKUP_GE(&srcobject->un_pager.swp.swp_blks, | ||||
rounddown(pindex, SWAP_META_PAGES)); | rounddown(pindex, SWAP_META_PAGES)); | ||||
if (sb == NULL || sb->p >= last) | if (sb == NULL || sb->p >= last) | ||||
break; | break; | ||||
start = pindex > sb->p ? pindex - sb->p : 0; | start = pindex > sb->p ? pindex - sb->p : 0; | ||||
limit = last - sb->p < SWAP_META_PAGES ? last - sb->p : | limit = last - sb->p < SWAP_META_PAGES ? last - sb->p : | ||||
SWAP_META_PAGES; | SWAP_META_PAGES; | ||||
for (i = start; i < limit; i++) { | for (i = start; i < limit; i++) { | ||||
if (sb->d[i] == SWAPBLK_NONE) | if (sb->d[i] == SWAPBLK_NONE) | ||||
continue; | continue; | ||||
swp_pager_update_freerange(&s_free, &n_free, sb->d[i]); | if (!swp_pager_copy_source(srcobject, dstobject, | ||||
sb->p + i - offset, sb->d[i])) { | |||||
Done Inline ActionsAgain indent is wrong. kib: Again indent is wrong. | |||||
swp_pager_update_freerange(&s_free, &n_free, | |||||
sb->d[i]); | |||||
} | |||||
sb->d[i] = SWAPBLK_NONE; | sb->d[i] = SWAPBLK_NONE; | ||||
} | } | ||||
pindex = sb->p + SWAP_META_PAGES; | pindex = sb->p + SWAP_META_PAGES; | ||||
if (swp_pager_swblk_empty(sb, 0, start) && | if (swp_pager_swblk_empty(sb, 0, start) && | ||||
swp_pager_swblk_empty(sb, limit, SWAP_META_PAGES)) { | swp_pager_swblk_empty(sb, limit, SWAP_META_PAGES)) { | ||||
SWAP_PCTRIE_REMOVE(&object->un_pager.swp.swp_blks, | SWAP_PCTRIE_REMOVE(&srcobject->un_pager.swp.swp_blks, | ||||
sb->p); | sb->p); | ||||
uma_zfree(swblk_zone, sb); | uma_zfree(swblk_zone, sb); | ||||
} | } | ||||
} | } | ||||
swp_pager_freeswapspace(s_free, n_free); | swp_pager_freeswapspace(s_free, n_free); | ||||
} | } | ||||
/* | /* | ||||
* SWP_PAGER_META_FREE() - free a range of blocks in the object's swap metadata | |||||
* | |||||
* The requested range of blocks is freed, with any associated swap | |||||
* returned to the swap bitmap. | |||||
* | |||||
* This routine will free swap metadata structures as they are cleaned | |||||
* out. This routine does *NOT* operate on swap metadata associated | |||||
* with resident pages. | |||||
*/ | |||||
static void | |||||
swp_pager_meta_free(vm_object_t object, vm_pindex_t pindex, vm_pindex_t count) | |||||
{ | |||||
swp_pager_meta_copy_free(object, NULL, pindex, count); | |||||
} | |||||
/* | |||||
* SWP_PAGER_META_FREE_ALL() - destroy all swap metadata associated with object | * SWP_PAGER_META_FREE_ALL() - destroy all swap metadata associated with object | ||||
* | * | ||||
* This routine locates and destroys all swap metadata associated with | * This routine locates and destroys all swap metadata associated with | ||||
* an object. | * an object. | ||||
*/ | */ | ||||
static void | static void | ||||
swp_pager_meta_free_all(vm_object_t object) | swp_pager_meta_free_all(vm_object_t object) | ||||
{ | { | ||||
Show All 17 Lines | for (pindex = 0; (sb = SWAP_PCTRIE_LOOKUP_GE( | ||||
} | } | ||||
SWAP_PCTRIE_REMOVE(&object->un_pager.swp.swp_blks, sb->p); | SWAP_PCTRIE_REMOVE(&object->un_pager.swp.swp_blks, sb->p); | ||||
uma_zfree(swblk_zone, sb); | uma_zfree(swblk_zone, sb); | ||||
} | } | ||||
swp_pager_freeswapspace(s_free, n_free); | swp_pager_freeswapspace(s_free, n_free); | ||||
} | } | ||||
/* | /* | ||||
* SWP_PAGER_METACTL() - misc control of swap meta data. | * SWP_PAGER_META_LOOKUP() - look up swap meta data. | ||||
* | * | ||||
* This routine is capable of looking up, or removing swapblk | * Look up swapblk assignments in the swap meta data. Returns the swapblk | ||||
* assignments in the swap meta data. It returns the swapblk being | * for (pindex = 0; (sb = being looked-up, or SWAPBLK_NONE if the block | ||||
* looked-up, popped, or SWAPBLK_NONE if the block was invalid. | * was invalid. | ||||
* | * | ||||
* When acting on a busy resident page and paging is in progress, we | * When acting on a busy resident page and paging is in progress, we | ||||
* have to wait until paging is complete but otherwise can act on the | * have to wait until paging is complete but otherwise can act on the | ||||
* busy page. | * busy page. | ||||
*/ | |||||
static daddr_t | |||||
swp_pager_meta_lookup(vm_object_t object, vm_pindex_t pindex) | |||||
{ | |||||
struct swblk *sb; | |||||
VM_OBJECT_ASSERT_LOCKED(object); | |||||
/* | |||||
* The meta data only exists if the object is OBJT_SWAP | |||||
* and even then might not be allocated yet. | |||||
*/ | |||||
if (object->type != OBJT_SWAP) | |||||
return (SWAPBLK_NONE); | |||||
sb = SWAP_PCTRIE_LOOKUP(&object->un_pager.swp.swp_blks, | |||||
rounddown(pindex, SWAP_META_PAGES)); | |||||
if (sb == NULL) | |||||
return (SWAPBLK_NONE); | |||||
return (sb->d[pindex % SWAP_META_PAGES]); | |||||
} | |||||
/* | |||||
* SWP_PAGER_META_REMOVE() - remove swap meta data. | |||||
* | * | ||||
* SWM_POP remove from meta data but do not free it | * This routine is capable of removing swapblk assignments in the swap | ||||
* for (pindex = 0; (sb = meta data. It returns the swapblk being | |||||
* removed, or SWAPBLK_NONE if the block was invalid. | |||||
* | |||||
* When acting on a busy resident page and paging is in progress, we | |||||
* have to wait until paging is complete but otherwise can act on the | |||||
* busy page. | |||||
*/ | */ | ||||
static daddr_t | static daddr_t | ||||
swp_pager_meta_ctl(vm_object_t object, vm_pindex_t pindex, int flags) | swp_pager_meta_remove(vm_object_t object, vm_pindex_t pindex) | ||||
{ | { | ||||
struct swblk *sb; | struct swblk *sb; | ||||
daddr_t r1; | daddr_t r1; | ||||
if ((flags & SWM_POP) != 0) | |||||
VM_OBJECT_ASSERT_WLOCKED(object); | VM_OBJECT_ASSERT_WLOCKED(object); | ||||
else | |||||
VM_OBJECT_ASSERT_LOCKED(object); | |||||
/* | /* | ||||
* The meta data only exists if the object is OBJT_SWAP | * The meta data only exists if the object is OBJT_SWAP | ||||
* and even then might not be allocated yet. | * and even then might not be allocated yet. | ||||
*/ | */ | ||||
if (object->type != OBJT_SWAP) | if (object->type != OBJT_SWAP) | ||||
return (SWAPBLK_NONE); | return (SWAPBLK_NONE); | ||||
sb = SWAP_PCTRIE_LOOKUP(&object->un_pager.swp.swp_blks, | sb = SWAP_PCTRIE_LOOKUP(&object->un_pager.swp.swp_blks, | ||||
rounddown(pindex, SWAP_META_PAGES)); | rounddown(pindex, SWAP_META_PAGES)); | ||||
if (sb == NULL) | if (sb == NULL) | ||||
return (SWAPBLK_NONE); | return (SWAPBLK_NONE); | ||||
r1 = sb->d[pindex % SWAP_META_PAGES]; | r1 = sb->d[pindex % SWAP_META_PAGES]; | ||||
if (r1 == SWAPBLK_NONE) | if (r1 == SWAPBLK_NONE) | ||||
return (SWAPBLK_NONE); | return (SWAPBLK_NONE); | ||||
if ((flags & SWM_POP) != 0) { | |||||
sb->d[pindex % SWAP_META_PAGES] = SWAPBLK_NONE; | sb->d[pindex % SWAP_META_PAGES] = SWAPBLK_NONE; | ||||
if (swp_pager_swblk_empty(sb, 0, SWAP_META_PAGES)) { | if (swp_pager_swblk_empty(sb, 0, SWAP_META_PAGES)) { | ||||
SWAP_PCTRIE_REMOVE(&object->un_pager.swp.swp_blks, | SWAP_PCTRIE_REMOVE(&object->un_pager.swp.swp_blks, | ||||
rounddown(pindex, SWAP_META_PAGES)); | rounddown(pindex, SWAP_META_PAGES)); | ||||
uma_zfree(swblk_zone, sb); | uma_zfree(swblk_zone, sb); | ||||
} | |||||
} | } | ||||
return (r1); | return (r1); | ||||
} | } | ||||
/* | /* | ||||
* Returns the least page index which is greater than or equal to the | * Returns the least page index which is greater than or equal to the | ||||
* parameter pindex and for which there is a swap block allocated. | * parameter pindex and for which there is a swap block allocated. | ||||
* Returns object's size if the object's type is not swap or if there | * Returns object's size if the object's type is not swap or if there | ||||
▲ Show 20 Lines • Show All 882 Lines • Show Last 20 Lines |
How the 'represented by a resident page' part is checked ?