summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Gorrod <alexg@wiredtiger.com>2013-05-29 10:37:53 +1000
committerAlex Gorrod <alexg@wiredtiger.com>2013-05-29 10:37:53 +1000
commit5d6f13e0b69670a6fc39f1ed1a348a2eb1212231 (patch)
tree0c1514a300a1ada656b626bb2d2f34be6f15659f
parentabd1970cb859af812f5e96ba96f6a404aed83055 (diff)
downloadmongo-5d6f13e0b69670a6fc39f1ed1a348a2eb1212231.tar.gz
Fix a bug where LSM would get the same lock twice during a drop.
-rw-r--r--src/lsm/lsm_worker.c32
1 files changed, 22 insertions, 10 deletions
diff --git a/src/lsm/lsm_worker.c b/src/lsm/lsm_worker.c
index e29607f9901..cc38f80e746 100644
--- a/src/lsm/lsm_worker.c
+++ b/src/lsm/lsm_worker.c
@@ -434,14 +434,12 @@ __lsm_drop_file(WT_SESSION_IMPL *session, const char *uri)
{
WT_CONNECTION_IMPL *conn;
WT_DECL_RET;
- int hot_backup_locked;
const char *drop_cfg[] = {
WT_CONFIG_BASE(session, session_drop), "remove_files=false", NULL
};
conn = S2C(session);
- hot_backup_locked = 0;
- /* Give up if a hot backup is in progress. */
+ /* Give up early if a hot backup is in progress. */
if (conn->hot_backup != 0)
return (EBUSY);
@@ -453,18 +451,32 @@ __lsm_drop_file(WT_SESSION_IMPL *session, const char *uri)
WT_RET(__lsm_discard_handle(session, uri, NULL));
WT_RET(__lsm_discard_handle(session, uri, "WiredTigerCheckpoint"));
+ /*
+ * Take the hot backup lock to prevent new backups starting. Don't
+ * proceed if a backup has started since we first checked.
+ */
__wt_spin_lock(session, &conn->hot_backup_lock);
- hot_backup_locked = 1;
- if (conn->hot_backup != 0)
- goto done;
- WT_WITH_SCHEMA_LOCK(session,
- ret = __wt_schema_drop(session, uri, drop_cfg));
+ if (conn->hot_backup != 0) {
+ __wt_spin_unlock(session, &conn->hot_backup_lock);
+ return (EBUSY);
+ }
+
+ /*
+ * Take the schema lock for the drop operation. Play games with the
+ * hot backup lock. Since __wt_schema_drop results in the hot backup
+ * lock being taken when it updates the metadata (which would be too
+ * late to prevent our drop).
+ */
+ __wt_spin_lock(session, &S2C(session)->schema_lock);
+ F_SET(session, WT_SESSION_SCHEMA_LOCKED);
+ __wt_spin_unlock(session, &conn->hot_backup_lock);
+ ret = __wt_schema_drop(session, uri, drop_cfg);
+ F_CLR(session, WT_SESSION_SCHEMA_LOCKED);
+ __wt_spin_unlock(session, &S2C(session)->schema_lock);
if (ret == 0)
ret = __wt_remove(session, uri + strlen("file:"));
-done: if (hot_backup_locked)
- __wt_spin_unlock(session, &conn->hot_backup_lock);
return (ret);
}