diff options
author | Benety Goh <benety@mongodb.com> | 2019-06-03 22:28:22 -0400 |
---|---|---|
committer | Benety Goh <benety@mongodb.com> | 2019-06-29 16:29:19 -0400 |
commit | 2ab86773334aa6cedbe9609c06a0f538cd39cede (patch) | |
tree | 62fc6ac7c3782361f7dd52872ff9d66c581da14b /src/mongo | |
parent | 498b7851cfa4d4860fd6d865647c24f680b32bbd (diff) | |
download | mongo-2ab86773334aa6cedbe9609c06a0f538cd39cede.tar.gz |
SERVER-41014 fix deadlock in runCreateIndexesWithCoordinator()
(cherry picked from commit f6e5ad7fe565d291f7333966b5f0355e7c06650a)
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/commands/create_indexes.cpp | 42 |
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(); } |