Commit fb6932a2 authored by Kirill Smelkov's avatar Kirill Smelkov

X Split PAGE_LOADED -> PAGE_LOADED, PAGE_LOADED_FOR_WRITE

The latter state is the only valid state in wcfs mode when pagefault
handler sees already loaded page in fileh->pagemap.
parent 4d18f19b
......@@ -1282,7 +1282,7 @@ int main()
{
tap_fail_callback = abort; // XXX to catch failure immediately
if (0) {
if (1) {
test_vmamap();
test_file_access_synthetic();
test_file_access_pagefault();
......
......@@ -479,6 +479,7 @@ void fileh_invalidate_page(BigFileH *fileh, pgoff_t pgoffset)
BUG_ON(fileh->writeout_inprogress);
// XXX wcfs: invalidate_page must not be called (wcfs handles invalidations itself)
// XXX or allow invalidate anyway (e.g. DIRTY -> base) ?
// XXX yes -> allow invalidate for wcfs too - means forget in-ram page and mmap to base memory
page = pagemap_get(&fileh->pagemap, pgoffset);
if (page) {
......@@ -630,12 +631,17 @@ VMFaultResult vma_on_pagefault(VMA *vma, uintptr_t addr, int write)
/* (3) fileh, pagen -> page (via pagemap) */
page = pagemap_get(&fileh->pagemap, pagen);
/* wcfs: all dirty pages are mmapped when vma is created */
// FIXME no: it could be in PAGE_LOADING state
// XXX and after VM_RETRY it could be in PAGE_LOADED state
// XXX ----//---- even for write
if (vma->mmap_overlay)
BUG_ON(page);
/* wcfs: all dirty pages are mmapped when vma is created.
* thus here, if page is present in pagemap, it can be only either
* - a page we just loaded for dirtying, or
* - a page that is in progress of being loaded.
*
* ( PAGE_LOADED_FOR_WRITE is used only to verify that in wcfs mode we
* always keep all dirty pages mmapped on fileh_open and so pagefault
* handler must not see a PAGE_LOADED page. )
*/
if (vma->mmap_overlay && page)
ASSERT(page->state == PAGE_LOADED_FOR_WRITE || page->state == PAGE_LOADING);
/* (4) no page found - allocate new from ram */
while (!page) {
......@@ -705,9 +711,6 @@ VMFaultResult vma_on_pagefault(VMA *vma, uintptr_t addr, int write)
pageram = page_mmap(page, NULL, PROT_READ | PROT_WRITE);
TODO(!pageram); // XXX err
// XXX overlay: copy data from base image, page.state=DIRTY
// XXX overlay: goto inject_page
/* load block -> pageram memory */
blk = page->f_pgoffset; // NOTE because blksize = pagesize
......@@ -755,7 +758,7 @@ VMFaultResult vma_on_pagefault(VMA *vma, uintptr_t addr, int write)
/* else just mark the page as loaded ok */
else
page->state = PAGE_LOADED;
page->state = (write ? PAGE_LOADED_FOR_WRITE : PAGE_LOADED);
/* we have to retry the whole fault, because the vma could have been
* changed while we were loading page with virtmem lock released */
......@@ -785,7 +788,6 @@ VMFaultResult vma_on_pagefault(VMA *vma, uintptr_t addr, int write)
return VM_RETRY;
}
//inject_page:
/* (6) page data ready. Mmap it atomically into vma address space, or mprotect
* appropriately if it was already mmaped. */
int prot = PROT_READ;
......@@ -853,7 +855,7 @@ static int __ram_reclaim(RAM *ram)
/* can release ram only from loaded non-dirty pages
* NOTE PAGE_LOADING pages are not dropped - they just continue to load */
if (page->state == PAGE_LOADED) {
if (page->state == PAGE_LOADED || page->state == PAGE_LOADED_FOR_WRITE) {
page_drop_memory(page);
batch--;
}
......
......@@ -84,7 +84,9 @@ enum PageState {
= 2, /* file content loading was in progress
while request to invalidate the page came in */
PAGE_LOADED = 3, /* file content has been loaded and was not modified */
PAGE_DIRTY = 4, /* file content has been loaded and was modified */
PAGE_LOADED_FOR_WRITE
= 4, /* file content has been loaded and is going to be modified */
PAGE_DIRTY = 5, /* file content has been loaded and was modified */
};
typedef enum PageState PageState;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment