X86VMTranslationMap::UnmapArea(): Don't change the page state before

it has been unmapped. This way modified pages could end up in the "cached"
queue without having been written back. That would be a good explanation for
#5374 (partially wrong file contents) -- as soon as such a page was freed,
the invalid on-disk contents would become visible.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35477 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2010-02-15 19:36:17 +00:00
parent c1f3da7b5b
commit ba3d62b66f
@@ -800,23 +800,12 @@ X86VMTranslationMap::UnmapArea(VMArea* area, bool deletingAddressSpace,
VMCache* cache = page->Cache();
DEBUG_PAGE_ACCESS_START(page);
bool pageFullyUnmapped = false;
if (page->wired_count == 0 && page->mappings.IsEmpty()) {
atomic_add(&gMappedPagesCount, -1);
if (!ignoreTopCachePageFlags || cache != area->cache) {
if (cache->temporary)
vm_page_set_state(page, PAGE_STATE_INACTIVE);
else if (page->modified)
vm_page_set_state(page, PAGE_STATE_MODIFIED);
else
vm_page_set_state(page, PAGE_STATE_CACHED);
}
pageFullyUnmapped = true;
}
DEBUG_PAGE_ACCESS_END(page);
if (unmapPages || cache != area->cache) {
addr_t address = area->Base()
+ ((page->cache_offset * B_PAGE_SIZE) - area->cache_offset);
@@ -861,6 +850,19 @@ X86VMTranslationMap::UnmapArea(VMArea* area, bool deletingAddressSpace,
if ((oldEntry & X86_PTE_DIRTY) != 0)
page->modified = true;
if (pageFullyUnmapped) {
DEBUG_PAGE_ACCESS_START(page);
if (cache->temporary)
vm_page_set_state(page, PAGE_STATE_INACTIVE);
else if (page->modified)
vm_page_set_state(page, PAGE_STATE_MODIFIED);
else
vm_page_set_state(page, PAGE_STATE_CACHED);
DEBUG_PAGE_ACCESS_END(page);
}
}
fMapCount--;