summaryrefslogtreecommitdiff
path: root/src/lsm/lsm_tree.c
diff options
context:
space:
mode:
authorAlex Gorrod <alexg@wiredtiger.com>2016-03-21 12:16:18 +1100
committerAlex Gorrod <alexg@wiredtiger.com>2016-03-21 12:16:18 +1100
commitb5a7e1742035dceeb842cd465fa09338e5a72cfa (patch)
tree0ce0e5beefd38af72ebbde28c4e5d6b1b1cbc856 /src/lsm/lsm_tree.c
parent4cc6155364ad81d45f17a16f21cb5cfda973a2cb (diff)
downloadmongo-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.c20
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.