summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian DeLeonardis <brian.deleonardis@mongodb.com>2020-10-13 18:07:59 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-10-15 18:34:32 +0000
commitbef72de45709f2e1e6874e9b5f29a01e3fa8c413 (patch)
treeaa5ee371861f2a64322ecfb8819030124919c316
parent81dabe92f33b3e109561aaa82d681316bb577813 (diff)
downloadmongo-bef72de45709f2e1e6874e9b5f29a01e3fa8c413.tar.gz
SERVER-47642 Ensure no active snapshot before acquiring collection X lock
-rw-r--r--src/mongo/db/catalog/drop_indexes.cpp8
-rw-r--r--src/mongo/db/catalog_raii.cpp13
-rw-r--r--src/mongo/dbtests/storage_timestamp_tests.cpp1
3 files changed, 17 insertions, 5 deletions
diff --git a/src/mongo/db/catalog/drop_indexes.cpp b/src/mongo/db/catalog/drop_indexes.cpp
index 98c2025918d..93bc44b3a0f 100644
--- a/src/mongo/db/catalog/drop_indexes.cpp
+++ b/src/mongo/db/catalog/drop_indexes.cpp
@@ -397,14 +397,14 @@ Status dropIndexes(OperationContext* opCtx,
hangAfterAbortingIndexes.pauseWhileSet();
}
- // Take an exclusive lock on the collection now to be able to perform index catalog writes
- // when removing ready indexes from disk.
- collection.emplace(opCtx, dbAndUUID, MODE_X);
-
// Abandon the snapshot as the index catalog will compare the in-memory state to the disk
// state, which may have changed when we released the lock temporarily.
opCtx->recoveryUnit()->abandonSnapshot();
+ // Take an exclusive lock on the collection now to be able to perform index catalog writes
+ // when removing ready indexes from disk.
+ collection.emplace(opCtx, dbAndUUID, MODE_X);
+
db = collection->getDb();
if (!*collection) {
return Status(ErrorCodes::NamespaceNotFound,
diff --git a/src/mongo/db/catalog_raii.cpp b/src/mongo/db/catalog_raii.cpp
index d0a91958cc3..0f29d258bcd 100644
--- a/src/mongo/db/catalog_raii.cpp
+++ b/src/mongo/db/catalog_raii.cpp
@@ -79,12 +79,23 @@ AutoGetCollection::AutoGetCollection(OperationContext* opCtx,
!nsOrUUID.dbname().empty() ? nsOrUUID.dbname() : nsOrUUID.nss()->db(),
isSharedLockMode(modeColl) ? MODE_IS : MODE_IX,
deadline) {
- if (auto& nss = nsOrUUID.nss()) {
+ auto& nss = nsOrUUID.nss();
+ if (nss) {
uassert(ErrorCodes::InvalidNamespace,
str::stream() << "Namespace " << *nss << " is not a valid collection name",
nss->isValid());
}
+ // Out of an abundance of caution, force operations to acquire new snapshots after
+ // acquiring exclusive collection locks. Operations that hold MODE_X locks make an
+ // assumption that all writes are visible in their snapshot and no new writes will commit.
+ // This may not be the case if an operation already has a snapshot open before acquiring an
+ // exclusive lock.
+ if (modeColl == MODE_X) {
+ invariant(!opCtx->recoveryUnit()->inActiveTxn(),
+ str::stream() << "Snapshot opened before acquiring X lock for " << *nss);
+ }
+
_collLock.emplace(opCtx, nsOrUUID, modeColl, deadline);
_resolvedNss = CollectionCatalog::get(opCtx).resolveNamespaceStringOrUUID(opCtx, nsOrUUID);
diff --git a/src/mongo/dbtests/storage_timestamp_tests.cpp b/src/mongo/dbtests/storage_timestamp_tests.cpp
index ab385218c86..05d87f448da 100644
--- a/src/mongo/dbtests/storage_timestamp_tests.cpp
+++ b/src/mongo/dbtests/storage_timestamp_tests.cpp
@@ -237,6 +237,7 @@ public:
void reset(NamespaceString nss) const {
::mongo::writeConflictRetry(_opCtx, "deleteAll", nss.ns(), [&] {
_opCtx->recoveryUnit()->setTimestampReadSource(RecoveryUnit::ReadSource::kNoTimestamp);
+ _opCtx->recoveryUnit()->abandonSnapshot();
AutoGetCollection collRaii(_opCtx, nss, LockMode::MODE_X);
if (collRaii) {