Commit 8bb7f2f2 authored by Kirill Smelkov's avatar Kirill Smelkov

bigfile/virtmem: Maintain dirty pages list for a fileh

This allows writeout code not to scan whole pagemap to find dirty pages
to write out, which should be faster.

But more importantly iterating whole pagemap on writeout would become
unsafe, when in upcoming patch storeblk() will be called with virt_lock
released: because there pagemap could be modified e.g. due to processing
other read accesses.

So maintain fileh->dirty_pages list and use it when we need to go
through dirtied pages.

Updates: nexedi/wendelin.core#6
parent 43b6fdbc
......@@ -319,8 +319,8 @@ PyFunc(pyfileh_isdirty, "isdirty() - are there any changes to fileh memory at al
if (!PyArg_ParseTuple(args, ""))
return NULL;
/* NOTE not strictly neccessary to virt_lock() for reading ->dirty */
return PyBool_FromLong(pyfileh->dirty);
/* NOTE not strictly neccessary to virt_lock() for checking ->dirty_pages not empty */
return PyBool_FromLong(!list_empty(&pyfileh->dirty_pages));
}
......
......@@ -51,6 +51,7 @@ Page *ramh_alloc_page(RAMH *ramh, pgoff_t pgoffset_hint)
page->ramh = ramh;
page->ramh_pgoffset = ramh_pgoffset;
INIT_LIST_HEAD(&page->lru); /* NOTE ->lru left unlinked */
INIT_LIST_HEAD(&page->in_dirty); /* initially not in dirty list */
page->refcnt = 0;
return page;
......
......@@ -325,13 +325,13 @@ void test_file_access_synthetic(void)
ok1(!M(vma, 2)); MUST_FAULT( B(vma, 2*PSb) ); MUST_FAULT( B(vma, 2*PSb) = 12 );
ok1(!M(vma, 3)); MUST_FAULT( B(vma, 3*PSb) ); MUST_FAULT( B(vma, 3*PSb) = 13 );
ok1(!fh->dirty);
CHECK_NOPAGE( 100 );
CHECK_NOPAGE( 101 );
CHECK_NOPAGE( 102 );
CHECK_NOPAGE( 103 );
ok1(list_empty(&ram->lru_list));
ok1(list_empty(&fh->dirty_pages));
/* simulate read access to page[0] - it should load it */
......@@ -343,7 +343,6 @@ void test_file_access_synthetic(void)
ok1(!M(vma, 2)); MUST_FAULT( B(vma, 2*PSb) ); MUST_FAULT( B(vma, 2*PSb) = 12 );
ok1(!M(vma, 3)); MUST_FAULT( B(vma, 3*PSb) ); MUST_FAULT( B(vma, 3*PSb) = 13 );
ok1(!fh->dirty);
page0 = pagemap_get(&fh->pagemap, 100);
CHECK_PAGE (page0, 100, PAGE_LOADED, 1);
CHECK_NOPAGE( 101 );
......@@ -357,6 +356,8 @@ void test_file_access_synthetic(void)
ok1(ram->lru_list.prev == &page0->lru);
ok1(page0->lru.prev == &ram->lru_list);
ok1(list_empty(&fh->dirty_pages));
/* simulate write access to page[2] - it should load it and mark page dirty */
diag("write page[2]");
......@@ -367,7 +368,6 @@ void test_file_access_synthetic(void)
ok1( M(vma, 2)); B(vma, 2*PSb); B(vma, 2*PSb) = 12;
ok1(!M(vma, 3)); MUST_FAULT( B(vma, 3*PSb) ); MUST_FAULT( B(vma, 3*PSb) = 13 );
ok1( fh->dirty);
page2 = pagemap_get(&fh->pagemap, 102);
CHECK_PAGE (page0, 100, PAGE_LOADED, 1);
CHECK_NOPAGE( 101 );
......@@ -385,6 +385,9 @@ void test_file_access_synthetic(void)
ok1(page2->lru.prev == &page0->lru);
ok1(page0->lru.prev == &ram->lru_list);
ok1(fh->dirty_pages.prev == &page2->in_dirty);
ok1(page2->in_dirty.prev == &fh->dirty_pages);
/* read access to page[3] - load */
diag("read page[3]");
......@@ -395,7 +398,6 @@ void test_file_access_synthetic(void)
ok1( M(vma, 2)); B(vma, 2*PSb); B(vma, 2*PSb) = 12;
ok1( M(vma, 3)); B(vma, 3*PSb); MUST_FAULT( B(vma, 3*PSb) = 13 );
ok1( fh->dirty);
page3 = pagemap_get(&fh->pagemap, 103);
CHECK_PAGE (page0, 100, PAGE_LOADED, 1);
CHECK_NOPAGE( 101 );
......@@ -417,6 +419,9 @@ void test_file_access_synthetic(void)
ok1(page2->lru.prev == &page0->lru);
ok1(page0->lru.prev == &ram->lru_list);
ok1(fh->dirty_pages.prev == &page2->in_dirty);
ok1(page2->in_dirty.prev == &fh->dirty_pages);
/* write access to page[0] - upgrade loaded -> dirty */
diag("write page[0]");
......@@ -427,7 +432,6 @@ void test_file_access_synthetic(void)
ok1( M(vma, 2)); B(vma, 2*PSb); B(vma, 2*PSb) = 12;
ok1( M(vma, 3)); B(vma, 3*PSb); MUST_FAULT( B(vma, 3*PSb) = 13 );
ok1( fh->dirty);
CHECK_PAGE (page0, 100, PAGE_DIRTY, 1);
CHECK_NOPAGE( 101 );
CHECK_PAGE (page2, 102, PAGE_DIRTY, 1);
......@@ -448,6 +452,10 @@ void test_file_access_synthetic(void)
ok1(page3->lru.prev == &page2->lru);
ok1(page2->lru.prev == &ram->lru_list);
ok1(fh->dirty_pages.prev == &page0->in_dirty);
ok1(page0->in_dirty.prev == &page2->in_dirty);
ok1(page2->in_dirty.prev == &fh->dirty_pages);
/* read page[1]
*
......@@ -462,7 +470,6 @@ void test_file_access_synthetic(void)
ok1( M(vma, 2)); B(vma, 2*PSb); B(vma, 2*PSb) = 12;
ok1(!M(vma, 3)); MUST_FAULT( B(vma, 3*PSb) ); MUST_FAULT( B(vma, 3*PSb) = 13 );
ok1( fh->dirty);
page1 = pagemap_get(&fh->pagemap, 101);
page3 = pagemap_get(&fh->pagemap, 103);
ok1(!page3);
......@@ -486,6 +493,10 @@ void test_file_access_synthetic(void)
ok1(page0->lru.prev == &page2->lru);
ok1(page2->lru.prev == &ram->lru_list);
ok1(fh->dirty_pages.prev == &page0->in_dirty);
ok1(page0->in_dirty.prev == &page2->in_dirty);
ok1(page2->in_dirty.prev == &fh->dirty_pages);
/* now explicit reclaim - should evict page[1] (the only PAGE_LOADED page) */
diag("reclaim");
......@@ -496,7 +507,6 @@ void test_file_access_synthetic(void)
ok1( M(vma, 2)); B(vma, 2*PSb); B(vma, 2*PSb) = 12;
ok1(!M(vma, 3)); MUST_FAULT( B(vma, 3*PSb) ); MUST_FAULT( B(vma, 3*PSb) = 13 );
ok1( fh->dirty);
page1 = pagemap_get(&fh->pagemap, 101);
ok1(!page1);
CHECK_PAGE (page0, 100, PAGE_DIRTY, 1);
......@@ -516,6 +526,10 @@ void test_file_access_synthetic(void)
ok1(page0->lru.prev == &page2->lru);
ok1(page2->lru.prev == &ram->lru_list);
ok1(fh->dirty_pages.prev == &page0->in_dirty);
ok1(page0->in_dirty.prev == &page2->in_dirty);
ok1(page2->in_dirty.prev == &fh->dirty_pages);
/* unmap vma - dirty pages should stay in fh->pagemap and memory should
* not be forgotten */
......@@ -524,7 +538,6 @@ void test_file_access_synthetic(void)
ok1(list_empty(&fh->mmaps));
ok1( fh->dirty);
CHECK_PAGE (page0, 100, PAGE_DIRTY, 0);
CHECK_NOPAGE( 101 );
CHECK_PAGE (page2, 102, PAGE_DIRTY, 0);
......@@ -534,6 +547,10 @@ void test_file_access_synthetic(void)
ok1(page0->lru.prev == &page2->lru);
ok1(page2->lru.prev == &ram->lru_list);
ok1(fh->dirty_pages.prev == &page0->in_dirty);
ok1(page0->in_dirty.prev == &page2->in_dirty);
ok1(page2->in_dirty.prev == &fh->dirty_pages);
b0 = page_mmap(page0, NULL, PROT_READ);
ok1(b0);
b2 = page_mmap(page2, NULL, PROT_READ);
......@@ -563,7 +580,6 @@ void test_file_access_synthetic(void)
ok1(!M(vma, 2)); MUST_FAULT( B(vma, 2*PSb) ); MUST_FAULT( B(vma, 2*PSb) = 12 );
ok1(!M(vma, 3)); MUST_FAULT( B(vma, 3*PSb) ); MUST_FAULT( B(vma, 3*PSb) = 13 );
ok1( fh->dirty);
CHECK_PAGE (page0, 100, PAGE_DIRTY, 0);
CHECK_NOPAGE( 101 );
CHECK_PAGE (page2, 102, PAGE_DIRTY, 0);
......@@ -573,6 +589,10 @@ void test_file_access_synthetic(void)
ok1(page0->lru.prev == &page2->lru);
ok1(page2->lru.prev == &ram->lru_list);
ok1(fh->dirty_pages.prev == &page0->in_dirty);
ok1(page0->in_dirty.prev == &page2->in_dirty);
ok1(page2->in_dirty.prev == &fh->dirty_pages);
/* read access to page[2] - should map it R/W - the page is in PAGE_DIRTY state */
diag("read page[2]");
......@@ -583,7 +603,6 @@ void test_file_access_synthetic(void)
ok1( M(vma, 2)); B(vma, 2*PSb); B(vma, 2*PSb) = 12;
ok1(!M(vma, 3)); MUST_FAULT( B(vma, 3*PSb) ); MUST_FAULT( B(vma, 3*PSb) = 13 );
ok1( fh->dirty);
CHECK_PAGE (page0, 100, PAGE_DIRTY, 0);
CHECK_NOPAGE( 101 );
CHECK_PAGE (page2, 102, PAGE_DIRTY, 1);
......@@ -593,6 +612,10 @@ void test_file_access_synthetic(void)
ok1(page2->lru.prev == &page0->lru);
ok1(page0->lru.prev == &ram->lru_list);
ok1(fh->dirty_pages.prev == &page0->in_dirty);
ok1(page0->in_dirty.prev == &page2->in_dirty);
ok1(page2->in_dirty.prev == &fh->dirty_pages);
/* discard - changes should go away */
diag("discard");
......@@ -603,7 +626,6 @@ void test_file_access_synthetic(void)
ok1(!M(vma, 2)); MUST_FAULT( B(vma, 2*PSb) ); MUST_FAULT( B(vma, 2*PSb) = 12 );
ok1(!M(vma, 3)); MUST_FAULT( B(vma, 3*PSb) ); MUST_FAULT( B(vma, 3*PSb) = 13 );
ok1(!fh->dirty);
CHECK_PAGE (page0, 100, PAGE_EMPTY, 0);
CHECK_NOPAGE( 101 );
CHECK_PAGE (page2, 102, PAGE_EMPTY, 0);
......@@ -613,6 +635,8 @@ void test_file_access_synthetic(void)
ok1(page2->lru.prev == &page0->lru);
ok1(page0->lru.prev == &ram->lru_list);
ok1(list_empty(&fh->dirty_pages));
/* writeout in 3 variants - STORE, MARK, STORE+MARK */
diag("writeout");
......@@ -640,7 +664,6 @@ void test_file_access_synthetic(void)
ok1(!M(vma, 2)); MUST_FAULT( B(vma, 2*PSb) ); MUST_FAULT( B(vma, 2*PSb) = 12 );
ok1( M(vma, 3)); B(vma, 3*PSb); MUST_FAULT( B(vma, 3*PSb) = 13 );
ok1(!fh->dirty);
CHECK_PAGE (page0, 100, PAGE_EMPTY, 0);
CHECK_NOPAGE( 101 );
CHECK_PAGE (page2, 102, PAGE_EMPTY, 0);
......@@ -651,6 +674,8 @@ void test_file_access_synthetic(void)
ok1(page2->lru.prev == &page0->lru);
ok1(page0->lru.prev == &ram->lru_list);
ok1(list_empty(&fh->dirty_pages));
/* prepare state (2 dirty pages, only 1 mapped) */
void mkdirty2() {
......@@ -666,7 +691,6 @@ void test_file_access_synthetic(void)
ok1( M(vma, 2)); B(vma, 2*PSb); B(vma, 2*PSb) = 12;
ok1(!M(vma, 3)); MUST_FAULT( B(vma, 3*PSb) ); MUST_FAULT( B(vma, 3*PSb) = 13 );
ok1( fh->dirty);
CHECK_PAGE (page0, 100, PAGE_DIRTY, 0);
CHECK_NOPAGE( 101 );
CHECK_PAGE (page2, 102, PAGE_DIRTY, 1);
......@@ -676,6 +700,10 @@ void test_file_access_synthetic(void)
ok1(page2->lru.prev == &page0->lru);
ok1(page0->lru.prev == &page3->lru);
ok1(page3->lru.prev == &ram->lru_list);
ok1(fh->dirty_pages.prev == &page0->in_dirty);
ok1(page0->in_dirty.prev == &page2->in_dirty);
ok1(page2->in_dirty.prev == &fh->dirty_pages);
}
diag("writeout (store)");
......@@ -692,12 +720,15 @@ void test_file_access_synthetic(void)
ok1( M(vma, 2)); B(vma, 2*PSb); B(vma, 2*PSb) = 12;
ok1(!M(vma, 3)); MUST_FAULT( B(vma, 3*PSb) ); MUST_FAULT( B(vma, 3*PSb) = 13 );
ok1( fh->dirty);
CHECK_PAGE (page0, 100, PAGE_DIRTY, 0);
CHECK_NOPAGE( 101 );
CHECK_PAGE (page2, 102, PAGE_DIRTY, 1);
CHECK_PAGE (page3, 103, PAGE_LOADED, 0);
/* NOTE - becomes sorted by ->f_pgoffset */
ok1(fh->dirty_pages.next == &page0->in_dirty);
ok1(page0->in_dirty.next == &page2->in_dirty);
ok1(page2->in_dirty.next == &fh->dirty_pages);
diag("writeout (mark)");
blkv_len = 0;
......@@ -710,7 +741,6 @@ void test_file_access_synthetic(void)
ok1( M(vma, 2)); B(vma, 2*PSb); MUST_FAULT( B(vma, 2*PSb) = 12 );
ok1(!M(vma, 3)); MUST_FAULT( B(vma, 3*PSb) ); MUST_FAULT( B(vma, 3*PSb) = 13 );
ok1(!fh->dirty);
CHECK_PAGE (page0, 100, PAGE_LOADED, 0);
CHECK_NOPAGE( 101 );
CHECK_PAGE (page2, 102, PAGE_LOADED, 1);
......@@ -721,6 +751,7 @@ void test_file_access_synthetic(void)
ok1(page0->lru.prev == &page3->lru);
ok1(page3->lru.prev == &ram->lru_list);
ok1(list_empty(&fh->dirty_pages));
diag("writeout (store+mark)");
mkdirty2();
......@@ -736,7 +767,6 @@ void test_file_access_synthetic(void)
ok1( M(vma, 2)); B(vma, 2*PSb); MUST_FAULT( B(vma, 2*PSb) = 12 );
ok1(!M(vma, 3)); MUST_FAULT( B(vma, 3*PSb) ); MUST_FAULT( B(vma, 3*PSb) = 13 );
ok1(!fh->dirty);
CHECK_PAGE (page0, 100, PAGE_LOADED, 0);
CHECK_NOPAGE( 101 );
CHECK_PAGE (page2, 102, PAGE_LOADED, 1);
......@@ -747,6 +777,7 @@ void test_file_access_synthetic(void)
ok1(page0->lru.prev == &page3->lru);
ok1(page3->lru.prev == &ram->lru_list);
ok1(list_empty(&fh->dirty_pages));
diag("invalidate");
mkdirty2();
......@@ -758,7 +789,6 @@ void test_file_access_synthetic(void)
ok1( M(vma, 2)); B(vma, 2*PSb); B(vma, 2*PSb) = 12;
ok1(!M(vma, 3)); MUST_FAULT( B(vma, 3*PSb) ); MUST_FAULT( B(vma, 3*PSb) = 13 );
ok1( fh->dirty);
CHECK_PAGE (page0, 100, PAGE_DIRTY, 0);
CHECK_NOPAGE( 101 );
CHECK_PAGE (page2, 102, PAGE_DIRTY, 1);
......@@ -769,6 +799,10 @@ void test_file_access_synthetic(void)
ok1(page0->lru.prev == &page3->lru);
ok1(page3->lru.prev == &ram->lru_list);
ok1(fh->dirty_pages.prev == &page0->in_dirty);
ok1(page0->in_dirty.prev == &page2->in_dirty);
ok1(page2->in_dirty.prev == &fh->dirty_pages);
fileh_invalidate_page(fh, 103);
......@@ -777,7 +811,6 @@ void test_file_access_synthetic(void)
ok1( M(vma, 2)); B(vma, 2*PSb); B(vma, 2*PSb) = 12;
ok1(!M(vma, 3)); MUST_FAULT( B(vma, 3*PSb) ); MUST_FAULT( B(vma, 3*PSb) = 13 );
ok1( fh->dirty);
CHECK_PAGE (page0, 100, PAGE_DIRTY, 0);
CHECK_NOPAGE( 101 );
CHECK_PAGE (page2, 102, PAGE_DIRTY, 1);
......@@ -788,6 +821,10 @@ void test_file_access_synthetic(void)
ok1(page0->lru.prev == &page3->lru);
ok1(page3->lru.prev == &ram->lru_list);
ok1(fh->dirty_pages.prev == &page0->in_dirty);
ok1(page0->in_dirty.prev == &page2->in_dirty);
ok1(page2->in_dirty.prev == &fh->dirty_pages);
fileh_invalidate_page(fh, 102);
......@@ -796,7 +833,6 @@ void test_file_access_synthetic(void)
ok1(!M(vma, 2)); MUST_FAULT( B(vma, 2*PSb) ); MUST_FAULT( B(vma, 2*PSb) = 12 );
ok1(!M(vma, 3)); MUST_FAULT( B(vma, 3*PSb) ); MUST_FAULT( B(vma, 3*PSb) = 13 );
ok1( fh->dirty);
CHECK_PAGE (page0, 100, PAGE_DIRTY, 0);
CHECK_NOPAGE( 101 );
CHECK_PAGE (page2, 102, PAGE_EMPTY, 0);
......@@ -807,6 +843,9 @@ void test_file_access_synthetic(void)
ok1(page0->lru.prev == &page3->lru);
ok1(page3->lru.prev == &ram->lru_list);
ok1(fh->dirty_pages.prev == &page0->in_dirty);
ok1(page0->in_dirty.prev == &fh->dirty_pages);
fileh_invalidate_page(fh, 100);
......@@ -815,7 +854,6 @@ void test_file_access_synthetic(void)
ok1(!M(vma, 2)); MUST_FAULT( B(vma, 2*PSb) ); MUST_FAULT( B(vma, 2*PSb) = 12 );
ok1(!M(vma, 3)); MUST_FAULT( B(vma, 3*PSb) ); MUST_FAULT( B(vma, 3*PSb) = 13 );
ok1(!fh->dirty);
CHECK_PAGE (page0, 100, PAGE_EMPTY, 0);
CHECK_NOPAGE( 101 );
CHECK_PAGE (page2, 102, PAGE_EMPTY, 0);
......@@ -826,6 +864,8 @@ void test_file_access_synthetic(void)
ok1(page0->lru.prev == &page3->lru);
ok1(page3->lru.prev == &ram->lru_list);
ok1(list_empty(&fh->dirty_pages));
/* read page[3] back */
xvma_on_pagefault(vma, vma->addr_start + 3*PS, 0);
......@@ -834,7 +874,6 @@ void test_file_access_synthetic(void)
ok1(!M(vma, 2)); MUST_FAULT( B(vma, 2*PSb) ); MUST_FAULT( B(vma, 2*PSb) = 12 );
ok1( M(vma, 3)); B(vma, 3*PSb); MUST_FAULT( B(vma, 3*PSb) = 13 );
ok1(!fh->dirty);
CHECK_PAGE (page0, 100, PAGE_EMPTY, 0);
CHECK_NOPAGE( 101 );
CHECK_PAGE (page2, 102, PAGE_EMPTY, 0);
......@@ -845,6 +884,8 @@ void test_file_access_synthetic(void)
ok1(page2->lru.prev == &page0->lru);
ok1(page0->lru.prev == &ram->lru_list);
ok1(list_empty(&fh->dirty_pages));
diag("fileh_close");
/* dirty some pages again - so that test fileh_close with not all pages being non-dirty */
......
......@@ -149,6 +149,7 @@ int fileh_open(BigFileH *fileh, BigFile *file, RAM *ram)
fileh->file = file;
INIT_LIST_HEAD(&fileh->mmaps);
INIT_LIST_HEAD(&fileh->dirty_pages);
pagemap_init(&fileh->pagemap, ilog2_exact(ram->pagesize));
out:
......@@ -182,6 +183,8 @@ void fileh_close(BigFileH *fileh)
free(page);
}
BUG_ON(!list_empty(&fileh->dirty_pages));
/* and clear pagemap */
pagemap_clear(&fileh->pagemap);
......@@ -296,11 +299,24 @@ void vma_unmap(VMA *vma)
* WRITEOUT / DISCARD *
**********************/
/* helper for sorting dirty pages by ->f_pgoffset */
static int hpage_indirty_cmp_bypgoffset(struct list_head *hpage1, struct list_head *hpage2, void *_)
{
Page *page1 = list_entry(hpage1, typeof(*page1), in_dirty);
Page *page2 = list_entry(hpage2, typeof(*page2), in_dirty);
if (page1->f_pgoffset < page2->f_pgoffset)
return -1;
if (page1->f_pgoffset > page2->f_pgoffset)
return +1;
return 0;
}
int fileh_dirty_writeout(BigFileH *fileh, enum WriteoutFlags flags)
{
Page *page;
BigFile *file = fileh->file;
struct list_head *hmmap;
struct list_head *hpage, *hpage_next, *hmmap;
sigset_t save_sigset;
int err = 0;
......@@ -312,12 +328,14 @@ int fileh_dirty_writeout(BigFileH *fileh, enum WriteoutFlags flags)
sigsegv_block(&save_sigset);
virt_lock();
/* pages are stored (if stored) in sorted order */
if (flags & WRITEOUT_STORE)
list_sort(&fileh->dirty_pages, hpage_indirty_cmp_bypgoffset, NULL);
/* write out dirty pages */
pagemap_for_each(page, &fileh->pagemap) {
/* XXX we scan whole file pages which could be slow
* TODO -> maintain something like separate dirty_list ? */
if (page->state != PAGE_DIRTY)
continue;
list_for_each_safe(hpage, hpage_next, &fileh->dirty_pages) {
page = list_entry(hpage, typeof(*page), in_dirty);
BUG_ON(page->state != PAGE_DIRTY);
/* ->storeblk() */
if (flags & WRITEOUT_STORE) {
......@@ -362,7 +380,7 @@ int fileh_dirty_writeout(BigFileH *fileh, enum WriteoutFlags flags)
/* page.state -> PAGE_LOADED and correct mappings RW -> R */
if (flags & WRITEOUT_MARKSTORED) {
page->state = PAGE_LOADED;
fileh->dirty--;
list_del_init(&page->in_dirty);
list_for_each(hmmap, &fileh->mmaps) {
VMA *vma = list_entry(hmmap, typeof(*vma), same_fileh);
......@@ -375,7 +393,7 @@ int fileh_dirty_writeout(BigFileH *fileh, enum WriteoutFlags flags)
/* if we successfully finished with markstored flag set - all dirty pages
* should become non-dirty */
if (flags & WRITEOUT_MARKSTORED)
BUG_ON(fileh->dirty);
BUG_ON(!list_empty(&fileh->dirty_pages));
out:
virt_unlock();
......@@ -387,18 +405,21 @@ out:
void fileh_dirty_discard(BigFileH *fileh)
{
Page *page;
struct list_head *hpage, *hpage_next;
sigset_t save_sigset;
sigsegv_block(&save_sigset);
virt_lock();
/* XXX we scan whole file pages which could be slow
* TODO -> maintain something like separate dirty_list ? */
pagemap_for_each(page, &fileh->pagemap)
if (page->state == PAGE_DIRTY)
list_for_each_safe(hpage, hpage_next, &fileh->dirty_pages) {
page = list_entry(hpage, typeof(*page), in_dirty);
BUG_ON(page->state != PAGE_DIRTY);
page_drop_memory(page);
}
BUG_ON(fileh->dirty);
BUG_ON(!list_empty(&fileh->dirty_pages));
virt_unlock();
sigsegv_restore(&save_sigset);
......@@ -722,7 +743,7 @@ VMFaultResult vma_on_pagefault(VMA *vma, uintptr_t addr, int write)
// XXX also call page->markdirty() ?
if (newstate == PAGE_DIRTY && newstate != page->state)
fileh->dirty++;
list_add_tail(&page->in_dirty, &fileh->dirty_pages);
page->state = max(page->state, newstate);
/* mark page as used recently */
......@@ -850,7 +871,7 @@ static void page_drop_memory(Page *page)
/* 2) release memory to ram */
ramh_drop_memory(page->ramh, page->ramh_pgoffset);
if (page->state == PAGE_DIRTY)
page->fileh->dirty--;
list_del_init(&page->in_dirty);
page->state = PAGE_EMPTY;
// XXX touch lru?
......
......@@ -65,10 +65,8 @@ struct BigFileH {
PageMap pagemap;
// XXX not sure we need this
// -> currently is used to know whether to join ZODB DataManager serving ZBigFile
// XXX maybe change into dirty_list in the future?
unsigned dirty;
/* fileh dirty pages */
struct list_head dirty_pages; /* _ -> page->in_dirty */
};
typedef struct BigFileH BigFileH;
......@@ -99,6 +97,9 @@ struct Page {
/* in recently-used pages for ramh->ram (ram->lru_list -> _) */
struct list_head lru;
/* in dirty pages for fileh (fileh->dirty_pages -> _) */
struct list_head in_dirty;
int refcnt; /* each mapping in a vma counts here */
};
typedef struct Page Page;
......
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