Commit f084ff9b authored by Kirill Smelkov's avatar Kirill Smelkov

X Transition to all VMA under 1 fileh to be either all based on wcfs or all based on !wcfs

This allows to make decision to drop a page right after writeout for
wcfs case. If vmas for one fileh were allowed to be mixed - we could not
know whether to drop the page & its memory from RAM or not - even if
there is no vma mapped in !wcfs mode, it could be created later, and by
dropping RAM cahce we hit severe slowness. NOTE: in between transactions
there is usually no vmas mapped, so this case is not artificial.

By requiring that all VMAs are of the same kind under one fileh we avoid
this ambiguity.
parent 4a88c96a
...@@ -167,6 +167,9 @@ int fileh_open(BigFileH *fileh, BigFile *file, RAM *ram) ...@@ -167,6 +167,9 @@ int fileh_open(BigFileH *fileh, BigFile *file, RAM *ram)
fileh->writeout_inprogress = 0; fileh->writeout_inprogress = 0;
pagemap_init(&fileh->pagemap, ilog2_exact(ram->pagesize)); pagemap_init(&fileh->pagemap, ilog2_exact(ram->pagesize));
// XXX hardcoded - allow user choice?
fileh->mmap_overlay = (file->file_ops->mmap_setup_read != NULL);
out: out:
virt_unlock(); virt_unlock();
sigsegv_restore(&save_sigset); sigsegv_restore(&save_sigset);
...@@ -243,10 +246,7 @@ int fileh_mmap(VMA *vma, BigFileH *fileh, pgoff_t pgoffset, pgoff_t pglen) ...@@ -243,10 +246,7 @@ int fileh_mmap(VMA *vma, BigFileH *fileh, pgoff_t pgoffset, pgoff_t pglen)
if (!vma->page_ismappedv) if (!vma->page_ismappedv)
goto fail; goto fail;
// XXX hardcoded - allow user choice? if (fileh->mmap_overlay) {
vma->mmap_overlay = (fops->mmap_setup_read != NULL);
if (vma->mmap_overlay) {
/* wcfs: mmap(base, READ) */ /* wcfs: mmap(base, READ) */
TODO (file->blksize != fileh->ramh->ram->pagesize); TODO (file->blksize != fileh->ramh->ram->pagesize);
addr = fops->mmap_setup_read(file, pgoffset, pglen, vma); addr = fops->mmap_setup_read(file, pgoffset, pglen, vma);
...@@ -262,7 +262,7 @@ int fileh_mmap(VMA *vma, BigFileH *fileh, pgoff_t pgoffset, pgoff_t pglen) ...@@ -262,7 +262,7 @@ int fileh_mmap(VMA *vma, BigFileH *fileh, pgoff_t pgoffset, pgoff_t pglen)
vma->addr_stop = vma->addr_start + len; vma->addr_stop = vma->addr_start + len;
/* wcfs: mmap(fileh->dirty_pages) over base */ /* wcfs: mmap(fileh->dirty_pages) over base */
if (vma->mmap_overlay) { if (fileh->mmap_overlay) {
Page* page; Page* page;
struct list_head *hpage; struct list_head *hpage;
...@@ -448,7 +448,7 @@ int fileh_dirty_writeout(BigFileH *fileh, enum WriteoutFlags flags) ...@@ -448,7 +448,7 @@ int fileh_dirty_writeout(BigFileH *fileh, enum WriteoutFlags flags)
list_for_each(hmmap, &fileh->mmaps) { list_for_each(hmmap, &fileh->mmaps) {
VMA *vma = list_entry(hmmap, typeof(*vma), same_fileh); VMA *vma = list_entry(hmmap, typeof(*vma), same_fileh);
if (vma->mmap_overlay) { if (fileh->mmap_overlay) {
/* wcfs: RW -> base layer */ /* wcfs: RW -> base layer */
vma_page_ensure_unmapped(vma, page); vma_page_ensure_unmapped(vma, page);
} else { } else {
...@@ -457,20 +457,16 @@ int fileh_dirty_writeout(BigFileH *fileh, enum WriteoutFlags flags) ...@@ -457,20 +457,16 @@ int fileh_dirty_writeout(BigFileH *fileh, enum WriteoutFlags flags)
} }
} }
// XXX just relying on page->refcnt==0 is wrong - for !wcfs case /* wcfs: all vmas are using base layer now - drop page completely
// when there are no mappings it will unnecessarily drop fileh cache. * without unnecessarily growing RSS and relying on reclaim.
// -> move mmap_overlay from vma to fileh and check: * !wcfs: keep the page in RAM cache, even if it is not mapped anywhere */
// if (fileh->mmap_overlay) { if (fileh->mmap_overlay) {
// ASSERT(page->refcnt == 0); ASSERT(page->refcnt == 0);
// page_drop(page); // XXX -> page_drop(page)
// } pagemap_del(&fileh->pagemap, page->f_pgoffset);
#if 0 page_drop_memory(page);
/* if noone is using the page (ex all vmas use base layer) - drop page_del(page);
* it completely without unnecessarily growing RSS and relying on reclaim. */
if (page->refcnt == 0) {
} }
#endif
} }
} }
...@@ -678,14 +674,14 @@ VMFaultResult vma_on_pagefault(VMA *vma, uintptr_t addr, int write) ...@@ -678,14 +674,14 @@ VMFaultResult vma_on_pagefault(VMA *vma, uintptr_t addr, int write)
/* continuing on_pagefault() - see (1) there ... */ /* continuing on_pagefault() - see (1) there ... */
/* wcfs: we should get into SIGSEGV handler only on write access */
if (vma->mmap_overlay)
BUG_ON(!write);
/* (2) vma, addr -> fileh, pagen ;idx of fileh page covering addr */ /* (2) vma, addr -> fileh, pagen ;idx of fileh page covering addr */
fileh = vma->fileh; fileh = vma->fileh;
pagen = vma_addr_fpgoffset(vma, addr); pagen = vma_addr_fpgoffset(vma, addr);
/* wcfs: we should get into SIGSEGV handler only on write access */
if (fileh->mmap_overlay)
BUG_ON(!write);
/* (3) fileh, pagen -> page (via pagemap) */ /* (3) fileh, pagen -> page (via pagemap) */
page = pagemap_get(&fileh->pagemap, pagen); page = pagemap_get(&fileh->pagemap, pagen);
...@@ -698,7 +694,7 @@ VMFaultResult vma_on_pagefault(VMA *vma, uintptr_t addr, int write) ...@@ -698,7 +694,7 @@ VMFaultResult vma_on_pagefault(VMA *vma, uintptr_t addr, int write)
* always keep all dirty pages mmapped on fileh_open and so pagefault * always keep all dirty pages mmapped on fileh_open and so pagefault
* handler must not see a PAGE_LOADED page. ) * handler must not see a PAGE_LOADED page. )
*/ */
if (vma->mmap_overlay && page) if (fileh->mmap_overlay && page)
ASSERT(page->state == PAGE_LOADED_FOR_WRITE || page->state == PAGE_LOADING); ASSERT(page->state == PAGE_LOADED_FOR_WRITE || page->state == PAGE_LOADING);
/* (4) no page found - allocate new from ram */ /* (4) no page found - allocate new from ram */
...@@ -781,7 +777,7 @@ VMFaultResult vma_on_pagefault(VMA *vma, uintptr_t addr, int write) ...@@ -781,7 +777,7 @@ VMFaultResult vma_on_pagefault(VMA *vma, uintptr_t addr, int write)
page->state = PAGE_LOADING; page->state = PAGE_LOADING;
virt_unlock(); virt_unlock();
if (vma->mmap_overlay) { if (fileh->mmap_overlay) {
/* wcfs: copy block data from read-only base mmap. /* wcfs: copy block data from read-only base mmap.
* NOTE we'll get SIGBUG here if wcfs returns EIO when loading block data */ * NOTE we'll get SIGBUG here if wcfs returns EIO when loading block data */
memcpy(pageram, vma_page_addr(vma, page), page_size(page)); memcpy(pageram, vma_page_addr(vma, page), page_size(page));
...@@ -868,13 +864,15 @@ VMFaultResult vma_on_pagefault(VMA *vma, uintptr_t addr, int write) ...@@ -868,13 +864,15 @@ VMFaultResult vma_on_pagefault(VMA *vma, uintptr_t addr, int write)
// XXX mmap page to all vma with .mmap_overlay=1 of this fileh. // XXX mmap page to all vma with .mmap_overlay=1 of this fileh.
vma_mmap_page(vma, page); vma_mmap_page(vma, page);
/* wcfs: mmap the page to all wcfs-backed vmas. If we don't the memory on /* wcfs: mmap the page to all wcfs-backed vmas. If we don't, the memory on
* those vmas will read with stale data */ * those vmas will read with stale data */
if (fileh->mmap_overlay) {
list_for_each(hmmap, &fileh->mmaps) { list_for_each(hmmap, &fileh->mmaps) {
VMA *vma2 = list_entry(hmmap, typeof(*vma2), same_fileh); VMA *vma2 = list_entry(hmmap, typeof(*vma2), same_fileh);
if (vma2 != vma && vma2->mmap_overlay) if (vma2 != vma)
vma_mmap_page(vma2, page); vma_mmap_page(vma2, page);
} }
}
/* mark page as used recently */ /* mark page as used recently */
// XXX = list_move_tail() // XXX = list_move_tail()
...@@ -1097,7 +1095,7 @@ static void vma_page_ensure_unmapped(VMA *vma, Page *page) ...@@ -1097,7 +1095,7 @@ static void vma_page_ensure_unmapped(VMA *vma, Page *page)
if (!vma_page_ismapped(vma, page)) if (!vma_page_ismapped(vma, page))
return; return;
if (vma->mmap_overlay) { if (vma->fileh->mmap_overlay) {
/* wcfs: remmap readonly to base image */ /* wcfs: remmap readonly to base image */
BigFile *file = vma->fileh->file; BigFile *file = vma->fileh->file;
int err; int err;
......
...@@ -74,6 +74,10 @@ struct BigFileH { ...@@ -74,6 +74,10 @@ struct BigFileH {
/* whether writeout is currently in progress */ /* whether writeout is currently in progress */
int writeout_inprogress; int writeout_inprogress;
/* whether base data for all VMAs of this fileh are taken as base-layer mmap XXX */
// XXX name
unsigned mmap_overlay : 1;
}; };
typedef struct BigFileH BigFileH; typedef struct BigFileH BigFileH;
...@@ -142,8 +146,8 @@ struct VMA { ...@@ -142,8 +146,8 @@ struct VMA {
/* whether corresponding to pgoffset-f_offset page is mapped in this VMA */ /* whether corresponding to pgoffset-f_offset page is mapped in this VMA */
bitmap *page_ismappedv; /* len ~ Δaddr / pagesize */ bitmap *page_ismappedv; /* len ~ Δaddr / pagesize */
// XXX name // // XXX name
unsigned mmap_overlay : 1; /* whether base data are taken as file mmap XXX */ // unsigned mmap_overlay : 1; /* whether base data are taken as file mmap XXX */
}; };
......
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