kernel/cache: Use vm_page::busy_io in the file_cache.
This allows the VMCache to remove these pages pending the I/O completion. Combined with the following commits, confirmed to fix #18390. Change-Id: I9630a00d70a9d6ac5b36e6de70475a6032390806 Reviewed-on: https://review.haiku-os.org/c/haiku/+/10591 Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
2b9d1bb9c2
commit
5eaf967479
+33
-3
@@ -161,6 +161,7 @@ PrecacheIO::Prepare(vm_page_reservation* reservation)
|
|||||||
for (generic_size_t pos = 0; pos < fSize; pos += B_PAGE_SIZE) {
|
for (generic_size_t pos = 0; pos < fSize; pos += B_PAGE_SIZE) {
|
||||||
vm_page* page = vm_page_allocate_page(reservation,
|
vm_page* page = vm_page_allocate_page(reservation,
|
||||||
PAGE_STATE_CACHED | VM_PAGE_ALLOC_BUSY);
|
PAGE_STATE_CACHED | VM_PAGE_ALLOC_BUSY);
|
||||||
|
page->busy_io = true;
|
||||||
|
|
||||||
fCache->InsertPage(page, fOffset + pos);
|
fCache->InsertPage(page, fOffset + pos);
|
||||||
|
|
||||||
@@ -214,14 +215,25 @@ PrecacheIO::IOFinished(status_t status, bool partialTransfer,
|
|||||||
|
|
||||||
DEBUG_PAGE_ACCESS_TRANSFER(fPages[i], fAllocatingThread);
|
DEBUG_PAGE_ACCESS_TRANSFER(fPages[i], fAllocatingThread);
|
||||||
|
|
||||||
fCache->MarkPageUnbusy(fPages[i]);
|
if (!fPages[i]->busy_io) {
|
||||||
|
// The busy_io flag was cleared. Let the cache handle the rest.
|
||||||
|
fCache->FreeRemovedPage(fPages[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
fPages[i]->busy_io = false;
|
||||||
|
fCache->MarkPageUnbusy(fPages[i]);
|
||||||
DEBUG_PAGE_ACCESS_END(fPages[i]);
|
DEBUG_PAGE_ACCESS_END(fPages[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free pages after failed I/O
|
// Free pages after failed I/O
|
||||||
for (uint32 i = pagesTransferred; i < fPageCount; i++) {
|
for (uint32 i = pagesTransferred; i < fPageCount; i++) {
|
||||||
DEBUG_PAGE_ACCESS_TRANSFER(fPages[i], fAllocatingThread);
|
DEBUG_PAGE_ACCESS_TRANSFER(fPages[i], fAllocatingThread);
|
||||||
|
if (!fPages[i]->busy_io) {
|
||||||
|
fCache->FreeRemovedPage(fPages[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
fCache->NotifyPageEvents(fPages[i], PAGE_EVENT_NOT_BUSY);
|
fCache->NotifyPageEvents(fPages[i], PAGE_EVENT_NOT_BUSY);
|
||||||
fCache->RemovePage(fPages[i]);
|
fCache->RemovePage(fPages[i]);
|
||||||
vm_page_free(fCache, fPages[i]);
|
vm_page_free(fCache, fPages[i]);
|
||||||
@@ -398,6 +410,7 @@ read_into_cache(file_cache_ref* ref, void* cookie, off_t offset,
|
|||||||
for (generic_size_t pos = 0; pos < numBytes; pos += B_PAGE_SIZE) {
|
for (generic_size_t pos = 0; pos < numBytes; pos += B_PAGE_SIZE) {
|
||||||
vm_page* page = pages[pageIndex++] = vm_page_allocate_page(
|
vm_page* page = pages[pageIndex++] = vm_page_allocate_page(
|
||||||
reservation, PAGE_STATE_CACHED | VM_PAGE_ALLOC_BUSY);
|
reservation, PAGE_STATE_CACHED | VM_PAGE_ALLOC_BUSY);
|
||||||
|
page->busy_io = true;
|
||||||
|
|
||||||
cache->InsertPage(page, offset + pos);
|
cache->InsertPage(page, offset + pos);
|
||||||
|
|
||||||
@@ -421,6 +434,11 @@ read_into_cache(file_cache_ref* ref, void* cookie, off_t offset,
|
|||||||
cache->Lock();
|
cache->Lock();
|
||||||
|
|
||||||
for (int32 i = 0; i < pageIndex; i++) {
|
for (int32 i = 0; i < pageIndex; i++) {
|
||||||
|
if (!pages[i]->busy_io) {
|
||||||
|
cache->FreeRemovedPage(pages[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
cache->NotifyPageEvents(pages[i], PAGE_EVENT_NOT_BUSY);
|
cache->NotifyPageEvents(pages[i], PAGE_EVENT_NOT_BUSY);
|
||||||
cache->RemovePage(pages[i]);
|
cache->RemovePage(pages[i]);
|
||||||
vm_page_free(cache, pages[i]);
|
vm_page_free(cache, pages[i]);
|
||||||
@@ -450,8 +468,14 @@ read_into_cache(file_cache_ref* ref, void* cookie, off_t offset,
|
|||||||
|
|
||||||
// make the pages accessible in the cache
|
// make the pages accessible in the cache
|
||||||
for (int32 i = pageIndex; i-- > 0;) {
|
for (int32 i = pageIndex; i-- > 0;) {
|
||||||
DEBUG_PAGE_ACCESS_END(pages[i]);
|
if (!pages[i]->busy_io) {
|
||||||
|
cache->FreeRemovedPage(pages[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pages[i]->busy_io = false;
|
||||||
cache->MarkPageUnbusy(pages[i]);
|
cache->MarkPageUnbusy(pages[i]);
|
||||||
|
DEBUG_PAGE_ACCESS_END(pages[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -523,6 +547,7 @@ write_to_cache(file_cache_ref* ref, void* cookie, off_t offset,
|
|||||||
reservation,
|
reservation,
|
||||||
(writeThrough ? PAGE_STATE_CACHED : PAGE_STATE_MODIFIED)
|
(writeThrough ? PAGE_STATE_CACHED : PAGE_STATE_MODIFIED)
|
||||||
| VM_PAGE_ALLOC_BUSY);
|
| VM_PAGE_ALLOC_BUSY);
|
||||||
|
page->busy_io = true;
|
||||||
|
|
||||||
page->modified = !writeThrough;
|
page->modified = !writeThrough;
|
||||||
|
|
||||||
@@ -622,8 +647,13 @@ write_to_cache(file_cache_ref* ref, void* cookie, off_t offset,
|
|||||||
|
|
||||||
// make the pages accessible in the cache
|
// make the pages accessible in the cache
|
||||||
for (int32 i = pageIndex; i-- > 0;) {
|
for (int32 i = pageIndex; i-- > 0;) {
|
||||||
ref->cache->MarkPageUnbusy(pages[i]);
|
if (!pages[i]->busy_io) {
|
||||||
|
ref->cache->FreeRemovedPage(pages[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pages[i]->busy_io = false;
|
||||||
|
ref->cache->MarkPageUnbusy(pages[i]);
|
||||||
DEBUG_PAGE_ACCESS_END(pages[i]);
|
DEBUG_PAGE_ACCESS_END(pages[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user