diff options
author | Alex Gorrod <alexg@wiredtiger.com> | 2016-03-21 12:16:18 +1100 |
---|---|---|
committer | Alex Gorrod <alexg@wiredtiger.com> | 2016-03-21 12:16:18 +1100 |
commit | b5a7e1742035dceeb842cd465fa09338e5a72cfa (patch) | |
tree | 0ce0e5beefd38af72ebbde28c4e5d6b1b1cbc856 /src/lsm/lsm_tree.c | |
parent | 4cc6155364ad81d45f17a16f21cb5cfda973a2cb (diff) | |
download | mongo-b5a7e1742035dceeb842cd465fa09338e5a72cfa.tar.gz |
WT-2499 Fix a race in LSM between setting and checking WT_LSM_TREE_ACTIVE.
Tree close relies on any state change being visible immediately. Found
by inspection, but could cause the symptom seen in this ticket.
Diffstat (limited to 'src/lsm/lsm_tree.c')
-rw-r--r-- | src/lsm/lsm_tree.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/src/lsm/lsm_tree.c b/src/lsm/lsm_tree.c index b64b72256cc..73466a53215 100644 --- a/src/lsm/lsm_tree.c +++ b/src/lsm/lsm_tree.c @@ -90,8 +90,13 @@ __lsm_tree_close(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree, bool wait) WT_DECL_RET; int i; - /* Stop any active merges. */ - F_CLR(lsm_tree, WT_LSM_TREE_ACTIVE); + /* + * Stop any new work units being added. The barrier is necessary + * because we rely on the state change being visible before checking + * the tree queue state. + */ + lsm_tree->active = false; + WT_READ_BARRIER(); /* * Wait for all LSM operations to drain. If WiredTiger is shutting @@ -123,7 +128,7 @@ __lsm_tree_close(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree, bool wait) } return (0); -err: F_SET(lsm_tree, WT_LSM_TREE_ACTIVE); +err: lsm_tree->active = true; return (ret); } @@ -389,7 +394,7 @@ __lsm_tree_find(WT_SESSION_IMPL *session, lsm_tree->refcnt != 1) { (void)__wt_atomic_sub32( &lsm_tree->refcnt, 1); - F_SET(lsm_tree, WT_LSM_TREE_ACTIVE); + lsm_tree->active = true; lsm_tree->excl_session = NULL; return (EBUSY); } @@ -504,7 +509,8 @@ __lsm_tree_open(WT_SESSION_IMPL *session, /* Now the tree is setup, make it visible to others. */ TAILQ_INSERT_HEAD(&S2C(session)->lsmqh, lsm_tree, q); - F_SET(lsm_tree, WT_LSM_TREE_ACTIVE | WT_LSM_TREE_OPEN); + lsm_tree->active = true; + F_SET(lsm_tree, WT_LSM_TREE_OPEN); *treep = lsm_tree; @@ -545,7 +551,7 @@ __wt_lsm_tree_release(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree) WT_ASSERT(session, lsm_tree->refcnt > 0); if (lsm_tree->excl_session == session) { /* We cleared the active flag when getting exclusive access. */ - F_SET(lsm_tree, WT_LSM_TREE_ACTIVE); + lsm_tree->active = true; lsm_tree->excl_session = NULL; } (void)__wt_atomic_sub32(&lsm_tree->refcnt, 1); @@ -1218,7 +1224,7 @@ __wt_lsm_compact(WT_SESSION_IMPL *session, const char *name, bool *skipp) } /* Wait for the work unit queues to drain. */ - while (F_ISSET(lsm_tree, WT_LSM_TREE_ACTIVE)) { + while (lsm_tree->active) { /* * The flush flag is cleared when the chunk has been flushed. * Continue to push forced flushes until the chunk is on disk. |