summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@wiredtiger.com>2013-05-13 13:34:44 +1000
committerMichael Cahill <michael.cahill@wiredtiger.com>2013-05-13 13:34:44 +1000
commite4d5c1e98113599ba0de4876cadc4785d64f4921 (patch)
treed757045dac43e1447634f4ba12b37becf44860ae
parentb9a86b29f1d7723dd3bfc348302b6e0892363636 (diff)
downloadmongo-e4d5c1e98113599ba0de4876cadc4785d64f4921.tar.gz
Clear pages from the LRU queue as soon as they are locked. Threads getting pages to evict look inside the WT_PAGE structure before switching the WT_REF state, so it isn't safe to evict a page that is queued.
-rw-r--r--src/btree/rec_evict.c33
-rw-r--r--src/btree/rec_merge.c3
2 files changed, 14 insertions, 22 deletions
diff --git a/src/btree/rec_evict.c b/src/btree/rec_evict.c
index d9333694dfd..0e7a6478b44 100644
--- a/src/btree/rec_evict.c
+++ b/src/btree/rec_evict.c
@@ -8,7 +8,6 @@
#include "wt_internal.h"
static int __hazard_exclusive(WT_SESSION_IMPL *, WT_REF *, int);
-static void __rec_discard_page(WT_SESSION_IMPL *, WT_PAGE *, int);
static void __rec_discard_tree(WT_SESSION_IMPL *, WT_PAGE *, int);
static void __rec_excl_clear(WT_SESSION_IMPL *);
static void __rec_page_clean_update(WT_SESSION_IMPL *, WT_PAGE *);
@@ -88,7 +87,7 @@ __wt_rec_evict(WT_SESSION_IMPL *session, WT_PAGE *page, int exclusive)
__rec_page_clean_update(session, page);
/* Discard the page. */
- __rec_discard_page(session, page, exclusive);
+ __wt_page_out(session, &page);
WT_CSTAT_INCR(session, cache_eviction_clean);
WT_DSTAT_INCR(session, cache_eviction_clean);
@@ -258,27 +257,12 @@ __rec_discard_tree(WT_SESSION_IMPL *session, WT_PAGE *page, int exclusive)
}
/* FALLTHROUGH */
default:
- __rec_discard_page(session, page, exclusive);
+ __wt_page_out(session, &page);
break;
}
}
/*
- * __rec_discard_page --
- * Discard the page.
- */
-static void
-__rec_discard_page(WT_SESSION_IMPL *session, WT_PAGE *page, int exclusive)
-{
- /* Make sure a page is not in the eviction request list. */
- if (!exclusive)
- __wt_evict_list_clr_page(session, page);
-
- /* Discard the page. */
- __wt_page_out(session, &page);
-}
-
-/*
* __rec_review --
* Get exclusive access to the page and review the page and its subtree
* for conditions that would block its eviction.
@@ -305,9 +289,20 @@ __rec_review(WT_SESSION_IMPL *session,
* Get exclusive access to the page if our caller doesn't have the tree
* locked down.
*/
- if (!exclusive)
+ if (!exclusive) {
WT_RET(__hazard_exclusive(session, ref, top));
+ /*
+ * Now that the page is locked, remove it from the LRU eviction
+ * queue. We have to do this before freeing the page memory or
+ * otherwise touching the reference because eviction paths
+ * assume that a non-NULL page pointer on the queue is pointing
+ * at valid memory.
+ */
+ __wt_evict_list_clr_page(session, page);
+ }
+
+
/*
* Recurse through the page's subtree: this happens first because we
* have to write pages in depth-first order, otherwise we'll dirty
diff --git a/src/btree/rec_merge.c b/src/btree/rec_merge.c
index 9138c44e34e..528fba45885 100644
--- a/src/btree/rec_merge.c
+++ b/src/btree/rec_merge.c
@@ -84,9 +84,6 @@ __merge_count(WT_PAGE *parent, WT_REF *ref, WT_VISIT_STATE *state)
WT_UNUSED(parent);
if (ref->state == WT_REF_LOCKED) {
- /* Prevent eviction until it is hooked into the new tree. */
- __wt_evict_list_clr_page(state->session, ref->page);
-
if (!state->seen_live) {
state->first_live = state->refcnt;
state->seen_live = 1;