diff options
author | kib <kib@FreeBSD.org> | 2017-01-01 11:38:34 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2017-01-01 11:38:34 +0000 |
commit | 24fe758c527a68bf8d6a24d46467c589fefe7f13 (patch) | |
tree | 4809a85ea035a39aee559b8aa6503fe47eab4a9e /sys/vm | |
parent | 762d7722438ce9a7fb651868254beaeca46afceb (diff) | |
download | FreeBSD-src-24fe758c527a68bf8d6a24d46467c589fefe7f13.zip FreeBSD-src-24fe758c527a68bf8d6a24d46467c589fefe7f13.tar.gz |
MFC r310234:
Improve vm_object_scan_all_shadowed() to also check swap backing objects.
Diffstat (limited to 'sys/vm')
-rw-r--r-- | sys/vm/swap_pager.c | 38 | ||||
-rw-r--r-- | sys/vm/swap_pager.h | 1 | ||||
-rw-r--r-- | sys/vm/vm_object.c | 44 |
3 files changed, 63 insertions, 20 deletions
diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index f94a385..3402c0a 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -2010,6 +2010,44 @@ swp_pager_meta_ctl(vm_object_t object, vm_pindex_t pindex, int flags) } /* + * Returns the least page index which is greater than or equal to the + * 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 + * are no allocated swap blocks for the object after the requested + * pindex. + */ +vm_pindex_t +swap_pager_find_least(vm_object_t object, vm_pindex_t pindex) +{ + struct swblock **pswap, *swap; + vm_pindex_t i, j, lim; + int idx; + + VM_OBJECT_ASSERT_LOCKED(object); + if (object->type != OBJT_SWAP || object->un_pager.swp.swp_bcount == 0) + return (object->size); + + mtx_lock(&swhash_mtx); + for (j = pindex; j < object->size; j = lim) { + pswap = swp_pager_hash(object, j); + lim = rounddown2(j + SWAP_META_PAGES, SWAP_META_PAGES); + if (lim > object->size) + lim = object->size; + if ((swap = *pswap) != NULL) { + for (idx = j & SWAP_META_MASK, i = j; i < lim; + i++, idx++) { + if (swap->swb_pages[idx] != SWAPBLK_NONE) + goto found; + } + } + } + i = object->size; +found: + mtx_unlock(&swhash_mtx); + return (i); +} + +/* * System call swapon(name) enables swapping on device name, * which must be in the swdevsw. Return EBUSY * if already swapping on this device. diff --git a/sys/vm/swap_pager.h b/sys/vm/swap_pager.h index 79f8767..83567f4 100644 --- a/sys/vm/swap_pager.h +++ b/sys/vm/swap_pager.h @@ -79,6 +79,7 @@ extern int swap_pager_avail; struct xswdev; int swap_dev_info(int name, struct xswdev *xs, char *devname, size_t len); void swap_pager_copy(vm_object_t, vm_object_t, vm_pindex_t, int); +vm_pindex_t swap_pager_find_least(vm_object_t object, vm_pindex_t pindex); void swap_pager_freespace(vm_object_t, vm_pindex_t, vm_size_t); void swap_pager_swap_init(void); int swap_pager_isswapped(vm_object_t, struct swdevt *); diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 7321990..6536b9e 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -1464,36 +1464,40 @@ vm_object_scan_all_shadowed(vm_object_t object) { vm_object_t backing_object; vm_page_t p, pp; - vm_pindex_t backing_offset_index, new_pindex; + vm_pindex_t backing_offset_index, new_pindex, pi, ps; VM_OBJECT_ASSERT_WLOCKED(object); VM_OBJECT_ASSERT_WLOCKED(object->backing_object); backing_object = object->backing_object; - /* - * Initial conditions: - * - * We do not want to have to test for the existence of cache or swap - * pages in the backing object. XXX but with the new swapper this - * would be pretty easy to do. - */ - if (backing_object->type != OBJT_DEFAULT) + if (backing_object->type != OBJT_DEFAULT && + backing_object->type != OBJT_SWAP) return (false); - backing_offset_index = OFF_TO_IDX(object->backing_object_offset); + pi = backing_offset_index = OFF_TO_IDX(object->backing_object_offset); + p = vm_page_find_least(backing_object, pi); + ps = swap_pager_find_least(backing_object, pi); - for (p = TAILQ_FIRST(&backing_object->memq); p != NULL; - p = TAILQ_NEXT(p, listq)) { - new_pindex = p->pindex - backing_offset_index; + /* + * Only check pages inside the parent object's range and + * inside the parent object's mapping of the backing object. + */ + for (;; pi++) { + if (p != NULL && p->pindex < pi) + p = TAILQ_NEXT(p, listq); + if (ps < pi) + ps = swap_pager_find_least(backing_object, pi); + if (p == NULL && ps >= backing_object->size) + break; + else if (p == NULL) + pi = ps; + else + pi = MIN(p->pindex, ps); - /* - * Ignore pages outside the parent object's range and outside - * the parent object's mapping of the backing object. - */ - if (p->pindex < backing_offset_index || - new_pindex >= object->size) - continue; + new_pindex = pi - backing_offset_index; + if (new_pindex >= object->size) + break; /* * See if the parent has the page or if the parent's object |