From 62488ce91951aaf0ac35df145779778219261c0a Mon Sep 17 00:00:00 2001 From: Matt Kneiser Date: Wed, 29 Mar 2023 00:06:27 +0000 Subject: SERVER-75205 Fix deadlock involving FCV lock With minor jstest amendments. (cherry picked from commit e74f9c2fdf73ad707419fa4a8ae57aec70423ca6) --- src/mongo/db/concurrency/lock_state.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src') 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::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); -- cgit v1.2.1