@@ -112,6 +112,18 @@ void abortIndexBuild(WithLock lk,
112
112
replIndexBuildState->abortReason = reason;
113
113
}
114
114
115
+ /* *
116
+ * We do not need synchronization with step up and step down. Dropping the RSTL is important because
117
+ * otherwise if we held the RSTL it would create deadlocks with prepared transactions on step up and
118
+ * step down. A deadlock could result if the index build was attempting to acquire a Collection S
119
+ * or X lock while a prepared transaction held a Collection IX lock, and a step down was waiting to
120
+ * acquire the RSTL in mode X.
121
+ */
122
+ void unlockRSTLForIndexCleanup (OperationContext* opCtx) {
123
+ opCtx->lockState ()->unlockRSTLforPrepare ();
124
+ invariant (!opCtx->lockState ()->isRSTLLocked ());
125
+ }
126
+
115
127
/* *
116
128
* Logs the index build failure error in a standard format.
117
129
*/
@@ -899,11 +911,7 @@ void IndexBuildsCoordinator::_runIndexBuildInner(OperationContext* opCtx,
899
911
900
912
Lock::DBLock dbLock (opCtx, nss.db (), MODE_IX);
901
913
902
- // Since DBLock implicitly acquires RSTL, we release the RSTL after acquiring the
903
- // database lock. Additionally, the RSTL has to be released before acquiring a strong
904
- // lock (MODE_X) on the collection to avoid potential deadlocks.
905
- opCtx->lockState ()->unlockRSTLforPrepare ();
906
- invariant (!opCtx->lockState ()->isRSTLLocked ());
914
+ unlockRSTLForIndexCleanup (opCtx);
907
915
908
916
Lock::CollectionLock collLock (opCtx, nss, MODE_X);
909
917
0 commit comments