summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/concurrency/lock_state.cpp14
1 files changed, 12 insertions, 2 deletions
diff --git a/src/mongo/db/concurrency/lock_state.cpp b/src/mongo/db/concurrency/lock_state.cpp
index 8f60fec8c5a..8a0bf755d9e 100644
--- a/src/mongo/db/concurrency/lock_state.cpp
+++ b/src/mongo/db/concurrency/lock_state.cpp
@@ -839,13 +839,21 @@ void LockerImpl::restoreLockState(OperationContext* opCtx, const Locker::LockSna
getFlowControlTicket(opCtx, state.globalMode);
std::vector<OneLock>::const_iterator it = state.locks.begin();
- // If we locked the PBWM, it must be locked before the resourceIdGlobal and
- // resourceIdReplicationStateTransitionLock resources.
+ // If we locked the PBWM, it must be locked before the
+ // resourceIdFeatureCompatibilityVersion, resourceIdReplicationStateTransitionLock, and
+ // resourceIdGlobal resources.
if (it != state.locks.end() && it->resourceId == resourceIdParallelBatchWriterMode) {
lock(opCtx, it->resourceId, it->mode);
it++;
}
+ // If we locked the FCV lock, it must be locked before the
+ // resourceIdReplicationStateTransitionLock and resourceIdGlobal resources.
+ if (it != state.locks.end() && it->resourceId == resourceIdFeatureCompatibilityVersion) {
+ lock(opCtx, it->resourceId, it->mode);
+ it++;
+ }
+
// If we locked the RSTL, it must be locked before the resourceIdGlobal resource.
if (it != state.locks.end() && it->resourceId == resourceIdReplicationStateTransitionLock) {
lock(opCtx, it->resourceId, it->mode);
@@ -854,6 +862,8 @@ void LockerImpl::restoreLockState(OperationContext* opCtx, const Locker::LockSna
lockGlobal(opCtx, state.globalMode);
for (; it != state.locks.end(); it++) {
+ // Ensures we don't acquire locks out of order which can lead to deadlock.
+ invariant(it->resourceId.getType() != ResourceType::RESOURCE_GLOBAL);
lock(opCtx, it->resourceId, it->mode);
}
invariant(_modeForTicket != MODE_NONE);