Changeset View
Changeset View
Standalone View
Standalone View
sys/vm/vm_pageout.c
Show First 20 Lines • Show All 327 Lines • ▼ Show 20 Lines | vm_pageout_cluster(vm_page_t m) | ||||
int ib, is, page_base, pageout_count; | int ib, is, page_base, pageout_count; | ||||
vm_page_assert_locked(m); | vm_page_assert_locked(m); | ||||
object = m->object; | object = m->object; | ||||
VM_OBJECT_ASSERT_WLOCKED(object); | VM_OBJECT_ASSERT_WLOCKED(object); | ||||
pindex = m->pindex; | pindex = m->pindex; | ||||
vm_page_assert_unbusied(m); | vm_page_assert_unbusied(m); | ||||
KASSERT(!vm_page_held(m), ("page %p is held", m)); | KASSERT(!vm_page_wired(m), ("page %p is wired", m)); | ||||
pmap_remove_write(m); | pmap_remove_write(m); | ||||
vm_page_unlock(m); | vm_page_unlock(m); | ||||
mc[vm_pageout_page_count] = pb = ps = m; | mc[vm_pageout_page_count] = pb = ps = m; | ||||
pageout_count = 1; | pageout_count = 1; | ||||
page_base = vm_pageout_page_count; | page_base = vm_pageout_page_count; | ||||
ib = 1; | ib = 1; | ||||
Show All 22 Lines | if ((p = vm_page_prev(pb)) == NULL || vm_page_busied(p)) { | ||||
break; | break; | ||||
} | } | ||||
vm_page_test_dirty(p); | vm_page_test_dirty(p); | ||||
if (p->dirty == 0) { | if (p->dirty == 0) { | ||||
ib = 0; | ib = 0; | ||||
break; | break; | ||||
} | } | ||||
vm_page_lock(p); | vm_page_lock(p); | ||||
if (vm_page_held(p) || !vm_page_in_laundry(p)) { | if (vm_page_wired(p) || !vm_page_in_laundry(p)) { | ||||
vm_page_unlock(p); | vm_page_unlock(p); | ||||
ib = 0; | ib = 0; | ||||
break; | break; | ||||
} | } | ||||
pmap_remove_write(p); | pmap_remove_write(p); | ||||
vm_page_unlock(p); | vm_page_unlock(p); | ||||
mc[--page_base] = pb = p; | mc[--page_base] = pb = p; | ||||
++pageout_count; | ++pageout_count; | ||||
Show All 9 Lines | more: | ||||
while (pageout_count < vm_pageout_page_count && | while (pageout_count < vm_pageout_page_count && | ||||
pindex + is < object->size) { | pindex + is < object->size) { | ||||
if ((p = vm_page_next(ps)) == NULL || vm_page_busied(p)) | if ((p = vm_page_next(ps)) == NULL || vm_page_busied(p)) | ||||
break; | break; | ||||
vm_page_test_dirty(p); | vm_page_test_dirty(p); | ||||
if (p->dirty == 0) | if (p->dirty == 0) | ||||
break; | break; | ||||
vm_page_lock(p); | vm_page_lock(p); | ||||
if (vm_page_held(p) || !vm_page_in_laundry(p)) { | if (vm_page_wired(p) || !vm_page_in_laundry(p)) { | ||||
vm_page_unlock(p); | vm_page_unlock(p); | ||||
break; | break; | ||||
} | } | ||||
pmap_remove_write(p); | pmap_remove_write(p); | ||||
vm_page_unlock(p); | vm_page_unlock(p); | ||||
mc[page_base + pageout_count] = ps = p; | mc[page_base + pageout_count] = ps = p; | ||||
++pageout_count; | ++pageout_count; | ||||
++is; | ++is; | ||||
▲ Show 20 Lines • Show All 235 Lines • ▼ Show 20 Lines | if (!vm_page_in_laundry(m) || m->object != object || | ||||
error = ENXIO; | error = ENXIO; | ||||
goto unlock_all; | goto unlock_all; | ||||
} | } | ||||
/* | /* | ||||
* The page may have been busied or referenced while the object | * The page may have been busied or referenced while the object | ||||
* and page locks were released. | * and page locks were released. | ||||
*/ | */ | ||||
if (vm_page_busied(m) || vm_page_held(m)) { | if (vm_page_busied(m) || vm_page_wired(m)) { | ||||
vm_page_unlock(m); | vm_page_unlock(m); | ||||
error = EBUSY; | error = EBUSY; | ||||
goto unlock_all; | goto unlock_all; | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* If a page is dirty, then it is either being washed | * If a page is dirty, then it is either being washed | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | recheck: | ||||
* chance. | * chance. | ||||
*/ | */ | ||||
if ((m->aflags & PGA_REQUEUE) != 0) { | if ((m->aflags & PGA_REQUEUE) != 0) { | ||||
vm_page_requeue(m); | vm_page_requeue(m); | ||||
continue; | continue; | ||||
} | } | ||||
/* | /* | ||||
* Held pages are essentially stuck in the queue. | |||||
* | |||||
* Wired pages may not be freed. Complete their removal | * Wired pages may not be freed. Complete their removal | ||||
* from the queue now to avoid needless revisits during | * from the queue now to avoid needless revisits during | ||||
* future scans. | * future scans. | ||||
*/ | */ | ||||
if (m->hold_count != 0) | |||||
continue; | |||||
if (m->wire_count != 0) { | if (m->wire_count != 0) { | ||||
vm_page_dequeue_deferred(m); | vm_page_dequeue_deferred(m); | ||||
continue; | continue; | ||||
} | } | ||||
if (object != m->object) { | if (object != m->object) { | ||||
if (object != NULL) | if (object != NULL) | ||||
VM_OBJECT_WUNLOCK(object); | VM_OBJECT_WUNLOCK(object); | ||||
▲ Show 20 Lines • Show All 648 Lines • ▼ Show 20 Lines | recheck: | ||||
* dropped, or a requeue was requested. This page gets a second | * dropped, or a requeue was requested. This page gets a second | ||||
* chance. | * chance. | ||||
*/ | */ | ||||
if ((m->aflags & (PGA_ENQUEUED | PGA_REQUEUE | | if ((m->aflags & (PGA_ENQUEUED | PGA_REQUEUE | | ||||
PGA_REQUEUE_HEAD)) != 0) | PGA_REQUEUE_HEAD)) != 0) | ||||
goto reinsert; | goto reinsert; | ||||
/* | /* | ||||
* Held pages are essentially stuck in the queue. So, | |||||
* they ought to be discounted from the inactive count. | |||||
* See the description of addl_page_shortage above. | |||||
* | |||||
* Wired pages may not be freed. Complete their removal | * Wired pages may not be freed. Complete their removal | ||||
* from the queue now to avoid needless revisits during | * from the queue now to avoid needless revisits during | ||||
* future scans. | * future scans. | ||||
*/ | */ | ||||
if (m->hold_count != 0) { | |||||
addl_page_shortage++; | |||||
goto reinsert; | |||||
} | |||||
if (m->wire_count != 0) { | if (m->wire_count != 0) { | ||||
vm_page_dequeue_deferred(m); | vm_page_dequeue_deferred(m); | ||||
continue; | continue; | ||||
} | } | ||||
if (object != m->object) { | if (object != m->object) { | ||||
if (object != NULL) | if (object != NULL) | ||||
VM_OBJECT_WUNLOCK(object); | VM_OBJECT_WUNLOCK(object); | ||||
▲ Show 20 Lines • Show All 671 Lines • Show Last 20 Lines |