@michaelcahill, I think I just saw the eviction attempt to discard modified pages core you reported in WT-932.
Here's the stack:
WT-6 0x00000000004abc2c in __wt_page_out (session=0x8024fe400, pagep=0x8065c7070) at ../src/btree/bt_discard.c:54 WT-7 0x00000000004abbc2 in __wt_ref_out (session=0x8024fe400, ref=0x8065c7070) at ../src/btree/bt_discard.c:32 WT-8 0x000000000045ce7e in __rec_page_dirty_update (session=0x8024fe400, ref=0x8065c7070, exclusive=0) at ../src/btree/rec_evict.c:178 WT-9 0x000000000045cb53 in __wt_rec_evict (session=0x8024fe400, ref=0x8065c7070, exclusive=0) at ../src/btree/rec_evict.c:77 WT-10 0x0000000000445e20 in __wt_evict_page (session=0x8024fe400, ref=0x8065c7070) at ../src/btree/bt_evict.c:393 WT-11 0x000000000044786e in __wt_evict_lru_page (session=0x8024fe400, is_app=1) at ../src/btree/bt_evict.c:1210 WT-12 0x00000000004a64eb in __wt_cache_full_check (session=0x8024fe400) at cache.i:93
It's a WT_PAGE_COL_VAR replacement page, page->modify->flags = 4, and it's dirty, page->modify->write_gen = 2.
I think this is a problem with the changes in __rec_review in new-split, but enough has changed that I'm not 100% sure of the details.
There are two interesting chunks of code. First, in __rec_review:
if (__wt_page_is_modified(page)) { flags = WT_EVICTION_LOCKED; if (exclusive) LF_SET(WT_SKIP_UPDATE_ERR); else if (top && !WT_PAGE_IS_INTERNAL(page) && page->memory_footprint > 10 * btree->maxleafpage) LF_SET(WT_SKIP_UPDATE_RESTORE); WT_RET(__wt_rec_write(session, ref, NULL, flags)); } else { /* * If the page was ever modified, make sure all of the updates * on the page are old enough they can be discarded from cache. */ if (!exclusive && mod != NULL && !__wt_txn_visible_all`(session, mod->rec_max_txn)) return (EBUSY); }
Notes:
- the develop branch applies the __wt_txn_visible_all test to all pages, including the ones "cleaned" by reconciliation, in new-split I changed it to apply only to pages on which we didn't call reconciliation, that is, clean pages we're evicting.
- the develop branch asserts the page is clean after writing it, so there must be conditions in new-split where a page can return success that it didn't before. (I removed that assertion for some reason, but I'll put it back shortly.)
- the develop branch had 2 flags, SERVER_LOCKED and UPDATE_QUIT; I got rid of UPDATE_QUIT because I thought it was the same as SERVER_LOCKED, that is, if you're reconciling for eviction, quit if you can't skip an update. That may have introduced a bug, but I don't see it – anyway, given how much __rec_txn_read has changed, it's hard to tell.
The second chunk of code is this one, in reconciliation wrapup:
/* * If no updates were skipped, we have a new maximum transaction written * for the page (used to decide if a clean page can be evicted). The * page only might be clean; if the write generation is unchanged since * reconciliation started, clear it and update cache dirty statistics, * if the write generation changed, then the page has been written since * we started reconciliation, it cannot be discarded. */ if (!r->leave_dirty) { mod->rec_max_txn = r->max_txn; if (WT_ATOMIC_CAS(mod->write_gen, r->orig_write_gen, 0)) __wt_cache_dirty_decr(session, page); }
Where we can return 0 even if the page will remain dirty.
- related to
-
WT-6 Complex schema example
- Closed
-
WT-7 Do we need the handle->err/errx methods?
- Closed
-
WT-8 Do we need table load, bulk-load and/or dump methods?
- Closed
-
WT-9 Does adding schema need to be transactional?
- Closed
-
WT-10 Basic "getting started" tutorial
- Closed
-
WT-11 placeholder #11
- Closed
-
WT-12 Write more examples
- Closed
-
WT-932 format infinite loop (new-split branch)
- Closed