summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2019-06-03 22:28:22 -0400
committerBenety Goh <benety@mongodb.com>2019-06-29 16:29:19 -0400
commit2ab86773334aa6cedbe9609c06a0f538cd39cede (patch)
tree62fc6ac7c3782361f7dd52872ff9d66c581da14b /src/mongo/db
parent498b7851cfa4d4860fd6d865647c24f680b32bbd (diff)
downloadmongo-2ab86773334aa6cedbe9609c06a0f538cd39cede.tar.gz
SERVER-41014 fix deadlock in runCreateIndexesWithCoordinator()
(cherry picked from commit f6e5ad7fe565d291f7333966b5f0355e7c06650a)
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/commands/create_indexes.cpp42
1 files changed, 9 insertions, 33 deletions
diff --git a/src/mongo/db/commands/create_indexes.cpp b/src/mongo/db/commands/create_indexes.cpp
index 1cbeca16773..5bc8dc8d00a 100644
--- a/src/mongo/db/commands/create_indexes.cpp
+++ b/src/mongo/db/commands/create_indexes.cpp
@@ -623,42 +623,18 @@ bool runCreateIndexesWithCoordinator(OperationContext* opCtx,
str::stream() << "Not primary while creating indexes in " << ns.ns());
}
- // Before potentially taking an exclusive database lock, check if all indexes already exist
- // while holding an intent lock. Only continue if new indexes need to be built and the
- // database should be re-locked in exclusive mode.
- AutoGetCollection autoColl(opCtx, ns, MODE_IX);
- auto db = autoColl.getDb();
- auto collection = autoColl.getCollection();
- if (collection) {
- invariant(db, str::stream() << "Database missing for index build: " << ns);
-
- checkDatabaseShardingState(opCtx, db);
-
- result.appendBool(kCreateCollectionAutomaticallyFieldName, false);
- auto specsCopy = resolveDefaultsAndRemoveExistingIndexes(opCtx, collection, specs);
- // Return from command invocation early if we are not adding any new indexes.
- if (specsCopy.size() == 0) {
- auto numIndexes = collection->getIndexCatalog()->numIndexesTotal(opCtx);
- fillCommandResultWithIndexesAlreadyExistInfo(numIndexes, &result);
- return true;
- }
- } else {
- // Relocking temporarily releases the Database lock while holding a Global IX lock. This
- // prevents the replication state from changing, but requires abandoning the current
- // snapshot in case indexes change during the period of time where no database lock is
- // held.
- opCtx->recoveryUnit()->abandonSnapshot();
- dbLock.relockWithMode(MODE_X);
+ if (indexesAlreadyExist(opCtx, ns, specs, &result)) {
+ return true;
+ }
- auto db = getOrCreateDatabase(opCtx, ns.db(), &dbLock);
+ auto db = getOrCreateDatabase(opCtx, ns.db(), &dbLock);
- checkDatabaseShardingState(opCtx, db);
+ checkDatabaseShardingState(opCtx, db);
- // We would not reach this point if we were able to check existing indexes on the
- // collection.
- invariant(!collection);
- collection = getOrCreateCollection(opCtx, db, ns, cmdObj, &errmsg, &result);
- }
+ opCtx->recoveryUnit()->abandonSnapshot();
+ Lock::CollectionLock collLock(opCtx, ns, MODE_X);
+
+ auto collection = getOrCreateCollection(opCtx, db, ns, cmdObj, &errmsg, &result);
collectionUUID = collection->uuid();
}