Changeset View
Changeset View
Standalone View
Standalone View
sys/vm/vm_object.c
Show First 20 Lines • Show All 835 Lines • ▼ Show 20 Lines | |||||
rescan: | rescan: | ||||
curgeneration = object->generation; | curgeneration = object->generation; | ||||
for (p = vm_page_find_least(object, tstart); p != NULL; p = np) { | for (p = vm_page_find_least(object, tstart); p != NULL; p = np) { | ||||
pi = p->pindex; | pi = p->pindex; | ||||
if (pi >= tend) | if (pi >= tend) | ||||
break; | break; | ||||
np = TAILQ_NEXT(p, listq); | np = TAILQ_NEXT(p, listq); | ||||
if (p->valid == 0) | if (vm_page_none_valid(p)) | ||||
continue; | continue; | ||||
if (vm_page_busy_acquire(p, VM_ALLOC_WAITFAIL) == 0) { | if (vm_page_busy_acquire(p, VM_ALLOC_WAITFAIL) == 0) { | ||||
if (object->generation != curgeneration) { | if (object->generation != curgeneration) { | ||||
if ((flags & OBJPC_SYNC) != 0) | if ((flags & OBJPC_SYNC) != 0) | ||||
goto rescan; | goto rescan; | ||||
else | else | ||||
clearobjflags = FALSE; | clearobjflags = FALSE; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 303 Lines • ▼ Show 20 Lines | if (m == NULL || pindex < m->pindex) { | ||||
NULL); | NULL); | ||||
} else { | } else { | ||||
next_page: | next_page: | ||||
tm = m; | tm = m; | ||||
m = TAILQ_NEXT(m, listq); | m = TAILQ_NEXT(m, listq); | ||||
} | } | ||||
/* | /* | ||||
* If the page is not in a normal state, skip it. | * If the page is not in a normal state, skip it. The page | ||||
* can not be invalidated while the object lock is held. | |||||
*/ | */ | ||||
if (tm->valid != VM_PAGE_BITS_ALL || | if (!vm_page_all_valid(tm) || vm_page_wired(tm)) | ||||
vm_page_wired(tm)) | |||||
goto next_pindex; | goto next_pindex; | ||||
KASSERT((tm->flags & PG_FICTITIOUS) == 0, | KASSERT((tm->flags & PG_FICTITIOUS) == 0, | ||||
("vm_object_madvise: page %p is fictitious", tm)); | ("vm_object_madvise: page %p is fictitious", tm)); | ||||
KASSERT((tm->oflags & VPO_UNMANAGED) == 0, | KASSERT((tm->oflags & VPO_UNMANAGED) == 0, | ||||
("vm_object_madvise: page %p is not managed", tm)); | ("vm_object_madvise: page %p is not managed", tm)); | ||||
if (vm_page_tryxbusy(tm) == 0) { | if (vm_page_tryxbusy(tm) == 0) { | ||||
if (object != tobject) | if (object != tobject) | ||||
VM_OBJECT_WUNLOCK(object); | VM_OBJECT_WUNLOCK(object); | ||||
▲ Show 20 Lines • Show All 307 Lines • ▼ Show 20 Lines | for (;; pi++) { | ||||
* See if the parent has the page or if the parent's object | * See if the parent has the page or if the parent's object | ||||
* pager has the page. If the parent has the page but the page | * pager has the page. If the parent has the page but the page | ||||
* is not valid, the parent's object pager must have the page. | * is not valid, the parent's object pager must have the page. | ||||
* | * | ||||
* If this fails, the parent does not completely shadow the | * If this fails, the parent does not completely shadow the | ||||
* object and we might as well give up now. | * object and we might as well give up now. | ||||
*/ | */ | ||||
pp = vm_page_lookup(object, new_pindex); | pp = vm_page_lookup(object, new_pindex); | ||||
if ((pp == NULL || pp->valid == 0) && | /* | ||||
* The valid check here is stable due to object lock being | |||||
* required to clear valid and initiate paging. | |||||
*/ | |||||
if ((pp == NULL || vm_page_none_valid(pp)) && | |||||
!vm_pager_has_page(object, new_pindex, NULL, NULL)) | !vm_pager_has_page(object, new_pindex, NULL, NULL)) | ||||
return (false); | return (false); | ||||
} | } | ||||
return (true); | return (true); | ||||
} | } | ||||
static bool | static bool | ||||
vm_object_collapse_scan(vm_object_t object, int op) | vm_object_collapse_scan(vm_object_t object, int op) | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | if (pp != NULL && vm_page_tryxbusy(pp) == 0) { | ||||
* unbusy the original (backing_obj) page before we can | * unbusy the original (backing_obj) page before we can | ||||
* (re)lock the parent. Hence we can get here. | * (re)lock the parent. Hence we can get here. | ||||
*/ | */ | ||||
next = vm_object_collapse_scan_wait(object, pp, next, | next = vm_object_collapse_scan_wait(object, pp, next, | ||||
op); | op); | ||||
continue; | continue; | ||||
} | } | ||||
KASSERT(pp == NULL || pp->valid != 0, | KASSERT(pp == NULL || !vm_page_none_valid(pp), | ||||
("unbusy invalid page %p", pp)); | ("unbusy invalid page %p", pp)); | ||||
if (pp != NULL || vm_pager_has_page(object, new_pindex, NULL, | if (pp != NULL || vm_pager_has_page(object, new_pindex, NULL, | ||||
NULL)) { | 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 | ||||
▲ Show 20 Lines • Show All 310 Lines • ▼ Show 20 Lines | if (vm_page_tryxbusy(p) == 0) { | ||||
goto again; | goto again; | ||||
} | } | ||||
if (vm_page_wired(p)) { | if (vm_page_wired(p)) { | ||||
wired: | wired: | ||||
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; | vm_page_invalid(p); | ||||
vm_page_undirty(p); | vm_page_undirty(p); | ||||
} | } | ||||
vm_page_xunbusy(p); | vm_page_xunbusy(p); | ||||
continue; | continue; | ||||
} | } | ||||
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 && | ||||
!vm_page_none_valid(p)) { | |||||
if ((options & OBJPR_NOTMAPPED) == 0 && | if ((options & OBJPR_NOTMAPPED) == 0 && | ||||
object->ref_count != 0 && | object->ref_count != 0 && | ||||
!vm_page_try_remove_write(p)) | !vm_page_try_remove_write(p)) | ||||
goto wired; | goto wired; | ||||
if (p->dirty != 0) { | if (p->dirty != 0) { | ||||
vm_page_xunbusy(p); | vm_page_xunbusy(p); | ||||
continue; | continue; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 750 Lines • Show Last 20 Lines |