vm_cache_resize() could remove one page too many, and thus eventually free
a modified page that mustn't be removed. This fixes bug #110. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16613 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -348,6 +348,8 @@ vm_cache_set_minimal_commitment(vm_cache_ref *ref, off_t commitment)
|
|||||||
/** This function updates the size field of the vm_cache structure.
|
/** This function updates the size field of the vm_cache structure.
|
||||||
* If needed, it will free up all pages that don't belong to the cache anymore.
|
* If needed, it will free up all pages that don't belong to the cache anymore.
|
||||||
* The vm_cache_ref lock must be held when you call it.
|
* The vm_cache_ref lock must be held when you call it.
|
||||||
|
* Since removed pages don't belong to the cache any longer, they are not
|
||||||
|
* written back before they will be removed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
@@ -355,7 +357,7 @@ vm_cache_resize(vm_cache_ref *cacheRef, off_t newSize)
|
|||||||
{
|
{
|
||||||
vm_cache *cache = cacheRef->cache;
|
vm_cache *cache = cacheRef->cache;
|
||||||
status_t status;
|
status_t status;
|
||||||
off_t oldSize;
|
uint32 oldPageCount, newPageCount;
|
||||||
|
|
||||||
ASSERT_LOCKED_MUTEX(&cacheRef->lock);
|
ASSERT_LOCKED_MUTEX(&cacheRef->lock);
|
||||||
|
|
||||||
@@ -363,16 +365,17 @@ vm_cache_resize(vm_cache_ref *cacheRef, off_t newSize)
|
|||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
oldSize = cache->virtual_size;
|
oldPageCount = (uint32)((cache->virtual_size + B_PAGE_SIZE - 1) >> PAGE_SHIFT);
|
||||||
if (newSize < oldSize) {
|
newPageCount = (uint32)((newSize + B_PAGE_SIZE - 1) >> PAGE_SHIFT);
|
||||||
|
|
||||||
|
if (newPageCount < oldPageCount) {
|
||||||
// we need to remove all pages in the cache outside of the new virtual size
|
// we need to remove all pages in the cache outside of the new virtual size
|
||||||
uint32 lastOffset = (uint32)(newSize >> PAGE_SHIFT);
|
|
||||||
vm_page *page, *next;
|
vm_page *page, *next;
|
||||||
|
|
||||||
for (page = cache->page_list; page; page = next) {
|
for (page = cache->page_list; page; page = next) {
|
||||||
next = page->cache_next;
|
next = page->cache_next;
|
||||||
|
|
||||||
if (page->cache_offset >= lastOffset) {
|
if (page->cache_offset >= newPageCount) {
|
||||||
// remove the page and put it into the free queue
|
// remove the page and put it into the free queue
|
||||||
vm_cache_remove_page(cacheRef, page);
|
vm_cache_remove_page(cacheRef, page);
|
||||||
vm_page_set_state(page, PAGE_STATE_FREE);
|
vm_page_set_state(page, PAGE_STATE_FREE);
|
||||||
|
|||||||
Reference in New Issue
Block a user