Changeset View
Changeset View
Standalone View
Standalone View
sys/vm/vm_object.c
Show First 20 Lines • Show All 693 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* vm_object_terminate_pages removes any remaining pageable pages | * vm_object_terminate_pages removes any remaining pageable pages | ||||
* from the object and resets the object to an empty state. | * from the object and resets the object to an empty state. | ||||
*/ | */ | ||||
static void | static void | ||||
vm_object_terminate_pages(vm_object_t object) | vm_object_terminate_pages(vm_object_t object) | ||||
{ | { | ||||
vm_page_t p, p_next; | vm_page_t p, p_next; | ||||
struct mtx *mtx; | |||||
VM_OBJECT_ASSERT_WLOCKED(object); | VM_OBJECT_ASSERT_WLOCKED(object); | ||||
mtx = NULL; | |||||
/* | /* | ||||
* Free any remaining pageable pages. This also removes them from the | * Free any remaining pageable pages. This also removes them from the | ||||
* paging queues. However, don't free wired pages, just remove them | * paging queues. However, don't free wired pages, just remove them | ||||
* from the object. Rather than incrementally removing each page from | * from the object. Rather than incrementally removing each page from | ||||
* the object, the page and object are reset to any empty state. | * the object, the page and object are reset to any empty state. | ||||
*/ | */ | ||||
TAILQ_FOREACH_SAFE(p, &object->memq, listq, p_next) { | TAILQ_FOREACH_SAFE(p, &object->memq, listq, p_next) { | ||||
vm_page_assert_unbusied(p); | vm_page_assert_unbusied(p); | ||||
if ((object->flags & OBJ_UNMANAGED) == 0) | KASSERT(p->object == object && p->ref_count > 0, | ||||
/* | ("vm_object_terminate_pages: page %p is inconsistent", p)); | ||||
* vm_page_free_prep() only needs the page | |||||
* lock for managed pages. | |||||
*/ | |||||
vm_page_change_lock(p, &mtx); | |||||
p->object = NULL; | p->object = NULL; | ||||
if (vm_page_wired(p)) | if (vm_page_drop(p, -VPRC_OBJREF) == VPRC_OBJREF) { | ||||
continue; | |||||
VM_CNT_INC(v_pfree); | VM_CNT_INC(v_pfree); | ||||
vm_page_free(p); | vm_page_free(p); | ||||
} | } | ||||
if (mtx != NULL) | } | ||||
mtx_unlock(mtx); | |||||
/* | /* | ||||
* If the object contained any pages, then reset it to an empty state. | * If the object contained any pages, then reset it to an empty state. | ||||
* None of the object's fields, including "resident_page_count", were | * None of the object's fields, including "resident_page_count", were | ||||
* modified by the preceding loop. | * modified by the preceding loop. | ||||
*/ | */ | ||||
if (object->resident_page_count != 0) { | if (object->resident_page_count != 0) { | ||||
vm_radix_reclaim_allnodes(&object->rtree); | vm_radix_reclaim_allnodes(&object->rtree); | ||||
▲ Show 20 Lines • Show All 845 Lines • ▼ Show 20 Lines | KASSERT(p->object == backing_object, | ||||
("vm_object_collapse_scan: object mismatch")); | ("vm_object_collapse_scan: object mismatch")); | ||||
if (p->pindex < backing_offset_index || | if (p->pindex < backing_offset_index || | ||||
new_pindex >= object->size) { | new_pindex >= object->size) { | ||||
if (backing_object->type == OBJT_SWAP) | if (backing_object->type == OBJT_SWAP) | ||||
swap_pager_freespace(backing_object, p->pindex, | swap_pager_freespace(backing_object, p->pindex, | ||||
1); | 1); | ||||
/* | |||||
* Page is out of the parent object's range, we can | |||||
* simply destroy it. | |||||
*/ | |||||
vm_page_lock(p); | |||||
KASSERT(!pmap_page_is_mapped(p), | KASSERT(!pmap_page_is_mapped(p), | ||||
("freeing mapped page %p", p)); | ("freeing mapped page %p", p)); | ||||
if (!vm_page_wired(p)) | if (vm_page_remove(p)) | ||||
vm_page_free(p); | vm_page_free(p); | ||||
else | |||||
vm_page_remove(p); | |||||
vm_page_unlock(p); | |||||
continue; | continue; | ||||
} | } | ||||
pp = vm_page_lookup(object, new_pindex); | pp = vm_page_lookup(object, new_pindex); | ||||
if (pp != NULL && vm_page_busied(pp)) { | if (pp != NULL && vm_page_busied(pp)) { | ||||
/* | /* | ||||
* The page in the parent is busy and possibly not | * The page in the parent is busy and possibly not | ||||
* (yet) valid. Until its state is finalized by the | * (yet) valid. Until its state is finalized by the | ||||
Show All 20 Lines | if (pp != NULL || vm_pager_has_page(object, new_pindex, NULL, | ||||
* The page already exists in the parent OR swap exists | * The page already exists in the parent OR swap exists | ||||
* for this location in the parent. Leave the parent's | * for this location in the parent. Leave the parent's | ||||
* page alone. Destroy the original page from the | * page alone. Destroy the original page from the | ||||
* backing object. | * backing object. | ||||
*/ | */ | ||||
if (backing_object->type == OBJT_SWAP) | if (backing_object->type == OBJT_SWAP) | ||||
swap_pager_freespace(backing_object, p->pindex, | swap_pager_freespace(backing_object, p->pindex, | ||||
1); | 1); | ||||
vm_page_lock(p); | |||||
KASSERT(!pmap_page_is_mapped(p), | KASSERT(!pmap_page_is_mapped(p), | ||||
("freeing mapped page %p", p)); | ("freeing mapped page %p", p)); | ||||
if (!vm_page_wired(p)) | if (vm_page_remove(p)) | ||||
vm_page_free(p); | vm_page_free(p); | ||||
else | |||||
vm_page_remove(p); | |||||
vm_page_unlock(p); | |||||
continue; | continue; | ||||
} | } | ||||
/* | /* | ||||
* Page does not exist in parent, rename the page from the | * Page does not exist in parent, rename the page from the | ||||
* backing object to the main object. | * backing object to the main object. | ||||
* | * | ||||
* If the page was mapped to a process, it can remain mapped | * If the page was mapped to a process, it can remain mapped | ||||
▲ Show 20 Lines • Show All 284 Lines • ▼ Show 20 Lines | for (; p != NULL && (p->pindex < end || end == 0); p = next) { | ||||
*/ | */ | ||||
vm_page_change_lock(p, &mtx); | vm_page_change_lock(p, &mtx); | ||||
if (vm_page_xbusied(p)) { | if (vm_page_xbusied(p)) { | ||||
VM_OBJECT_WUNLOCK(object); | VM_OBJECT_WUNLOCK(object); | ||||
vm_page_busy_sleep(p, "vmopax", true); | vm_page_busy_sleep(p, "vmopax", true); | ||||
VM_OBJECT_WLOCK(object); | VM_OBJECT_WLOCK(object); | ||||
goto again; | goto again; | ||||
} | } | ||||
wired: | |||||
if (vm_page_wired(p)) { | if (vm_page_wired(p)) { | ||||
if ((options & OBJPR_NOTMAPPED) == 0 && | if ((options & OBJPR_NOTMAPPED) == 0 && | ||||
object->ref_count != 0) | object->ref_count != 0) | ||||
pmap_remove_all(p); | pmap_remove_all(p); | ||||
if ((options & OBJPR_CLEANONLY) == 0) { | if ((options & OBJPR_CLEANONLY) == 0) { | ||||
p->valid = 0; | p->valid = 0; | ||||
vm_page_undirty(p); | vm_page_undirty(p); | ||||
} | } | ||||
continue; | continue; | ||||
} | } | ||||
if (vm_page_busied(p)) { | if (vm_page_busied(p)) { | ||||
VM_OBJECT_WUNLOCK(object); | VM_OBJECT_WUNLOCK(object); | ||||
vm_page_busy_sleep(p, "vmopar", false); | vm_page_busy_sleep(p, "vmopar", false); | ||||
VM_OBJECT_WLOCK(object); | VM_OBJECT_WLOCK(object); | ||||
goto again; | goto again; | ||||
} | } | ||||
KASSERT((p->flags & PG_FICTITIOUS) == 0, | KASSERT((p->flags & PG_FICTITIOUS) == 0, | ||||
("vm_object_page_remove: page %p is fictitious", p)); | ("vm_object_page_remove: page %p is fictitious", p)); | ||||
if ((options & OBJPR_CLEANONLY) != 0 && p->valid != 0) { | if ((options & OBJPR_CLEANONLY) != 0 && p->valid != 0) { | ||||
if ((options & OBJPR_NOTMAPPED) == 0 && | if ((options & OBJPR_NOTMAPPED) == 0 && | ||||
object->ref_count != 0) | object->ref_count != 0 && | ||||
pmap_remove_write(p); | !vm_page_try_remove_write(p)) | ||||
goto wired; | |||||
if (p->dirty != 0) | if (p->dirty != 0) | ||||
continue; | continue; | ||||
} | } | ||||
if ((options & OBJPR_NOTMAPPED) == 0 && object->ref_count != 0) | if ((options & OBJPR_NOTMAPPED) == 0 && | ||||
pmap_remove_all(p); | object->ref_count != 0 && !vm_page_try_remove_all(p)) | ||||
goto wired; | |||||
if (vm_page_remove(p)) | |||||
vm_page_free(p); | vm_page_free(p); | ||||
} | } | ||||
if (mtx != NULL) | if (mtx != NULL) | ||||
mtx_unlock(mtx); | mtx_unlock(mtx); | ||||
vm_object_pip_wakeup(object); | vm_object_pip_wakeup(object); | ||||
} | } | ||||
/* | /* | ||||
* vm_object_page_noreuse: | * vm_object_page_noreuse: | ||||
▲ Show 20 Lines • Show All 709 Lines • Show Last 20 Lines |