summaryrefslogtreecommitdiff
path: root/src/mongo/db/repl
diff options
context:
space:
mode:
authorSpencer T Brody <spencer@mongodb.com>2017-10-05 18:57:19 -0400
committerSpencer T Brody <spencer@mongodb.com>2017-10-16 18:05:08 -0400
commitae9262c5c48b378216f276ca150204dff63f04b4 (patch)
tree5ed77d9babd0ab4be195db05013c232012178f9c /src/mongo/db/repl
parentd8279111b61afac242ddbb9f6d9697bbd14ed9d4 (diff)
downloadmongo-ae9262c5c48b378216f276ca150204dff63f04b4.tar.gz
SERVER-31431 Ensure that all state transitions in or out of SECONDARY occur with the global X lock held
Diffstat (limited to 'src/mongo/db/repl')
-rw-r--r--src/mongo/db/repl/bgsync.cpp4
-rw-r--r--src/mongo/db/repl/resync.cpp39
-rw-r--r--src/mongo/db/repl/sync_tail.cpp4
3 files changed, 28 insertions, 19 deletions
diff --git a/src/mongo/db/repl/bgsync.cpp b/src/mongo/db/repl/bgsync.cpp
index 1ae84415b4a..f2c369ea0bd 100644
--- a/src/mongo/db/repl/bgsync.cpp
+++ b/src/mongo/db/repl/bgsync.cpp
@@ -364,6 +364,10 @@ void BackgroundSync::_produce() {
// Mark yourself as too stale.
_tooStale = true;
+ // Need to take global X lock to transition out of SECONDARY.
+ auto opCtx = cc().makeOperationContext();
+ Lock::GlobalWrite globalWriteLock(opCtx.get());
+
error() << "too stale to catch up -- entering maintenance mode";
log() << "Our newest OpTime : " << lastOpTimeFetched;
log() << "Earliest OpTime available is " << syncSourceResp.earliestOpTimeSeen;
diff --git a/src/mongo/db/repl/resync.cpp b/src/mongo/db/repl/resync.cpp
index c18c26bfd46..a1e60050652 100644
--- a/src/mongo/db/repl/resync.cpp
+++ b/src/mongo/db/repl/resync.cpp
@@ -90,23 +90,28 @@ public:
"Replica sets do not support the resync command"));
}
- const MemberState memberState = replCoord->getMemberState();
- if (memberState.startup()) {
- return appendCommandStatus(
- result, Status(ErrorCodes::NotYetInitialized, "no replication yet active"));
- }
- if (memberState.primary()) {
- return appendCommandStatus(
- result, Status(ErrorCodes::NotSecondary, "primaries cannot resync"));
- }
- auto status = replCoord->setFollowerMode(MemberState::RS_STARTUP2);
- if (!status.isOK()) {
- return appendCommandStatus(
- result,
- Status(status.code(),
- str::stream()
- << "Failed to transition to STARTUP2 state to perform resync: "
- << status.reason()));
+ {
+ // Need global write lock to transition out of SECONDARY
+ Lock::GlobalWrite globalWriteLock(opCtx);
+
+ const MemberState memberState = replCoord->getMemberState();
+ if (memberState.startup()) {
+ return appendCommandStatus(
+ result, Status(ErrorCodes::NotYetInitialized, "no replication yet active"));
+ }
+ if (memberState.primary()) {
+ return appendCommandStatus(
+ result, Status(ErrorCodes::NotSecondary, "primaries cannot resync"));
+ }
+ auto status = replCoord->setFollowerMode(MemberState::RS_STARTUP2);
+ if (!status.isOK()) {
+ return appendCommandStatus(
+ result,
+ Status(status.code(),
+ str::stream()
+ << "Failed to transition to STARTUP2 state to perform resync: "
+ << status.reason()));
+ }
}
uassertStatusOKWithLocation(replCoord->resyncData(opCtx, waitForResync), "resync", 0);
return true;
diff --git a/src/mongo/db/repl/sync_tail.cpp b/src/mongo/db/repl/sync_tail.cpp
index 15e6fabb856..15185abaf73 100644
--- a/src/mongo/db/repl/sync_tail.cpp
+++ b/src/mongo/db/repl/sync_tail.cpp
@@ -691,8 +691,8 @@ void tryToGoLiveAsASecondary(OperationContext* opCtx, ReplicationCoordinator* re
// This needs to happen after the attempt so readers can be sure we've already tried.
ON_BLOCK_EXIT([] { attemptsToBecomeSecondary.increment(); });
- // TODO(SERVER-27892): Change to GlobalWrite
- Lock::GlobalRead readLock(opCtx);
+ // Need global X lock to transition to SECONDARY
+ Lock::GlobalWrite readLock(opCtx);
if (replCoord->getMaintenanceMode()) {
LOG(1) << "Can't go live (tryToGoLiveAsASecondary) as maintenance mode is active.";