summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@mongodb.com>2016-11-14 09:39:08 +1100
committerGitHub <noreply@github.com>2016-11-14 09:39:08 +1100
commit370154159bc7e3b06488cbdf7deb0585baf841b6 (patch)
tree0778da3f34238bd5d23e9c827fdf6d89e6d38b96
parent05e9389be80f28a63327d62d3d2e2eb1ecc3e14b (diff)
downloadmongo-370154159bc7e3b06488cbdf7deb0585baf841b6.tar.gz
WT-3017 Don't set NULL hazard pointers. (#3141)
-rw-r--r--src/support/hazard.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/src/support/hazard.c b/src/support/hazard.c
index b1978dbe97a..27508bbdece 100644
--- a/src/support/hazard.c
+++ b/src/support/hazard.c
@@ -26,6 +26,7 @@ __wt_hazard_set(WT_SESSION_IMPL *session, WT_REF *ref, bool *busyp
WT_BTREE *btree;
WT_CONNECTION_IMPL *conn;
WT_HAZARD *hp;
+ WT_PAGE *page;
int restarts = 0;
btree = S2BT(session);
@@ -37,6 +38,16 @@ __wt_hazard_set(WT_SESSION_IMPL *session, WT_REF *ref, bool *busyp
return (0);
/*
+ * If there isn't a valid page pointer, we're done. This read can race
+ * with eviction and splits, we re-check it after a barrier to make
+ * sure we have a valid pointer.
+ */
+ if (ref->state != WT_REF_MEM || (page = ref->page) == NULL) {
+ *busyp = true;
+ return (0);
+ }
+
+ /*
* Do the dance:
*
* The memory location which makes a page "real" is the WT_REF's state
@@ -82,7 +93,7 @@ __wt_hazard_set(WT_SESSION_IMPL *session, WT_REF *ref, bool *busyp
if (hp->page != NULL)
continue;
- hp->page = ref->page;
+ hp->page = page;
#ifdef HAVE_DIAGNOSTIC
hp->file = file;
hp->line = line;
@@ -101,9 +112,12 @@ __wt_hazard_set(WT_SESSION_IMPL *session, WT_REF *ref, bool *busyp
* found this page using the tree's key space, whatever page we
* find here is the page for us to use.)
*/
- if (ref->page == hp->page && ref->state == WT_REF_MEM) {
- ++session->nhazard;
- return (0);
+ if (ref->state == WT_REF_MEM) {
+ WT_READ_BARRIER();
+ if (ref->page == page) {
+ ++session->nhazard;
+ return (0);
+ }
}
/*