summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@wiredtiger.com>2013-01-08 00:35:34 +1100
committerMichael Cahill <michael.cahill@wiredtiger.com>2013-01-08 00:35:34 +1100
commit1a52f63a8d06060c98ef299e958850c8ec528f77 (patch)
tree9a8bf09fd2ed3b32afdc6eeebaa840718af1fe68
parentbb550b2b748c77e3abee02d8b2e5465df89521e8 (diff)
downloadmongo-1a52f63a8d06060c98ef299e958850c8ec528f77.tar.gz
Skip eviction of dirty pages when a checkpoint is in progress. There are cases where transactinal reads are not sufficient to guarantee that no page referenced from the checkpoint will be overwritten.
closes #425
-rw-r--r--src/btree/rec_evict.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/src/btree/rec_evict.c b/src/btree/rec_evict.c
index e61f8c890cb..b739e644099 100644
--- a/src/btree/rec_evict.c
+++ b/src/btree/rec_evict.c
@@ -279,8 +279,17 @@ __rec_review(WT_SESSION_IMPL *session,
}
/*
- * If the file is being checkpointed, the checkpoint's reconciliation of
- * an internal page might race with us as we evict a child in the page's
+ * If the file is being checkpointed, we cannot evict dirty pages,
+ * because that may free a page that appears on an internal page in the
+ * checkpoint. Don't rely on new updates being skipped by the
+ * transaction used for transaction reads: (1) there are paths that
+ * dirty pages for artificial reasons; (2) internal pages aren't
+ * transactional; and (3) if an update was skipped during the
+ * checkpoint (leaving the page dirty), then rolled back, we could
+ * still successfully overwrite a page and corrupt the checkpoint.
+ *
+ * Further, even for clean pages, the checkpoint's reconciliation of an
+ * internal page might race with us as we evict a child in the page's
* subtree.
*
* One half of that test is in the reconciliation code: the checkpoint
@@ -311,6 +320,9 @@ __rec_review(WT_SESSION_IMPL *session,
* we find a page which can't be merged into its parent, and failing if
* we never find such a page.
*/
+ if (btree->checkpointing && __wt_page_is_modified(page))
+ return (EBUSY);
+
if (btree->checkpointing && top)
for (t = page->parent;; t = t->parent) {
if (t == NULL || t->ref == NULL) /* root */