diff options
author | Keith Bostic <keith@wiredtiger.com> | 2012-08-06 09:51:42 +0000 |
---|---|---|
committer | Keith Bostic <keith@wiredtiger.com> | 2012-08-06 09:53:08 +0000 |
commit | 7933a39e61489a918998dfa0b14af8855dc713c7 (patch) | |
tree | dc602e964ed8ecf1a67af2c18f1f3c1cf7b07805 /src | |
parent | d217b2c6758c37fb06dc08d5b4b127ec572452ae (diff) | |
download | mongo-7933a39e61489a918998dfa0b14af8855dc713c7.tar.gz |
Michael's fix for a hazard reference race, where page eviction races with the
creation of the hazard reference, we have to check the pointer itself as well
as the state of the pointer. Close #284.
the creation of the hazard reference and the actua
Diffstat (limited to 'src')
-rw-r--r-- | src/support/hazard.c | 30 |
1 files changed, 18 insertions, 12 deletions
diff --git a/src/support/hazard.c b/src/support/hazard.c index 71060a08f19..c713f9a5ee9 100644 --- a/src/support/hazard.c +++ b/src/support/hazard.c @@ -42,11 +42,11 @@ __wt_hazard_set(WT_SESSION_IMPL *session, WT_REF *ref, int *busyp * page eviction server. * * Add the WT_REF reference to the session's hazard list and flush the - * write, then see if the state field is still WT_REF_MEM. If it's - * still WT_REF_MEM, we can use the page because the page eviction - * server will see our hazard reference before it discards the buffer - * (the eviction server sets the state to WT_REF_LOCKED, then flushes - * memory and checks the hazard references). + * write, then see if the page's state is still valid. If so, we can + * use the page because the page eviction server will see our hazard + * reference before it discards the page (the eviction server sets the + * state to WT_REF_LOCKED, then flushes memory and checks the hazard + * references). */ for (hp = session->hazard; hp < session->hazard + conn->hazard_size; ++hp) { @@ -62,11 +62,19 @@ __wt_hazard_set(WT_SESSION_IMPL *session, WT_REF *ref, int *busyp WT_FULL_BARRIER(); /* - * Check to see if the page state is still valid (where valid - * means a state of WT_REF_MEM or WT_REF_EVICT_WALK). + * Check if the page state is still valid, where valid means a + * state of WT_REF_MEM or WT_REF_EVICT_WALK and the pointer is + * unchanged. (The pointer can change, it means the page was + * evicted between the time we set our hazard reference and the + * publication. It would theoretically be possible for the + * page to be evicted and a different page read into the same + * memory, so the pointer hasn't changed but the contents have. + * That's OK, we found this page in tree's key space, whatever + * page we find here is the page page for us to use.) */ - if (ref->state == WT_REF_MEM || - ref->state == WT_REF_EVICT_WALK) { + if (ref->page == hp->page && + (ref->state == WT_REF_MEM || + ref->state == WT_REF_EVICT_WALK)) { WT_VERBOSE_RET(session, hazard, "session %p hazard %p: set", session, ref->page); @@ -88,9 +96,7 @@ __wt_hazard_set(WT_SESSION_IMPL *session, WT_REF *ref, int *busyp * go ahead and complete the eviction. * * We don't bother publishing this update: the worst case is we - * prevent the page from being evicted, but that's not going to - * happen repeatedly, the eviction thread gives up and won't try - * again until it loops around through the tree. + * prevent some random page from being evicted. */ hp->page = NULL; *busyp = 1; |