summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/btree/bt_handle.c37
1 files changed, 23 insertions, 14 deletions
diff --git a/src/btree/bt_handle.c b/src/btree/bt_handle.c
index a970b656cf5..2da886b4423 100644
--- a/src/btree/bt_handle.c
+++ b/src/btree/bt_handle.c
@@ -11,7 +11,7 @@ static int __btree_conf(WT_SESSION_IMPL *, WT_CKPT *ckpt);
static int __btree_get_last_recno(WT_SESSION_IMPL *);
static int __btree_page_sizes(WT_SESSION_IMPL *);
static int __btree_preload(WT_SESSION_IMPL *);
-static int __btree_tree_open_empty(WT_SESSION_IMPL *, int);
+static int __btree_tree_open_empty(WT_SESSION_IMPL *, int, int);
static int pse1(WT_SESSION_IMPL *, const char *, uint32_t, uint32_t);
static int pse2(WT_SESSION_IMPL *, const char *, uint32_t, uint32_t, int);
@@ -102,7 +102,8 @@ __wt_btree_open(WT_SESSION_IMPL *session, const char *op_cfg[])
ckpt.raw.data, ckpt.raw.size,
root_addr, &root_addr_size, readonly));
if (creation || root_addr_size == 0)
- WT_ERR(__btree_tree_open_empty(session, creation));
+ WT_ERR(__btree_tree_open_empty(
+ session, creation, readonly));
else {
WT_ERR(__wt_btree_tree_open(
session, root_addr, root_addr_size));
@@ -355,7 +356,7 @@ err: __wt_buf_free(session, &dsk);
* Create an empty in-memory tree.
*/
static int
-__btree_tree_open_empty(WT_SESSION_IMPL *session, int creation)
+__btree_tree_open_empty(WT_SESSION_IMPL *session, int creation, int readonly)
{
WT_BTREE *btree;
WT_DECL_RET;
@@ -423,23 +424,31 @@ __btree_tree_open_empty(WT_SESSION_IMPL *session, int creation)
* the root page dirty to force a write, and without reconciling the
* leaf page we won't realize there's no records to write, we'll write
* a root page, which isn't correct for an empty tree.
- * Earlier versions of this code kept the leaf page clean, but with
- * the "empty" flag set in the leaf page's modification structure; in
- * that case, checkpoints works (forced reconciliation of a root with
- * a single "empty" page wouldn't write any blocks). That version had
+ *
+ * Earlier versions of this code kept the leaf page clean, but with the
+ * "empty" flag set in the leaf page's modification structure; in that
+ * case, checkpoints works (forced reconciliation of a root with a
+ * single "empty" page wouldn't write any blocks). That version had
* memory leaks because the eviction code didn't correctly handle pages
* that were "clean" (and so never reconciled), yet "modified" with an
* "empty" flag. The goal of this code is to mimic a real tree that
* simply has no records, for whatever reason, and trust reconciliation
* to figure out it's empty and not write any blocks.
- * We do not set the tree's modified flag because the checkpoint code
- * skips unmodified files in closing checkpoints (checkpoints that don't
- * require a write unless the file is actually dirty). There's no need
- * to reconcile this file unless the application does a real checkpoint
- * or it's actually modified.
+ *
+ * We do not set the tree's modified flag because the checkpoint code
+ * skips unmodified files in closing checkpoints (checkpoints that
+ * don't require a write unless the file is actually dirty). There's
+ * no need to reconcile this file unless the application does a real
+ * checkpoint or it's actually modified.
+ *
+ * Only do this for a live tree, not for checkpoints. If we open an
+ * empty checkpoint, the leaf page cannot be dirty or eviction may try
+ * to write it, which will fail because checkpoints are read-only.
*/
- WT_ERR(__wt_page_modify_init(session, leaf));
- __wt_page_only_modify_set(session, leaf);
+ if (!readonly) {
+ WT_ERR(__wt_page_modify_init(session, leaf));
+ __wt_page_only_modify_set(session, leaf);
+ }
btree->root_page = root;