diff options
author | Alex Gorrod <alexg@wiredtiger.com> | 2013-05-29 10:37:53 +1000 |
---|---|---|
committer | Alex Gorrod <alexg@wiredtiger.com> | 2013-05-29 10:37:53 +1000 |
commit | 5d6f13e0b69670a6fc39f1ed1a348a2eb1212231 (patch) | |
tree | 0c1514a300a1ada656b626bb2d2f34be6f15659f | |
parent | abd1970cb859af812f5e96ba96f6a404aed83055 (diff) | |
download | mongo-5d6f13e0b69670a6fc39f1ed1a348a2eb1212231.tar.gz |
Fix a bug where LSM would get the same lock twice during a drop.
-rw-r--r-- | src/lsm/lsm_worker.c | 32 |
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); } |