summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavithra Vetriselvan <pavithra.vetriselvan@mongodb.com>2019-10-18 15:23:50 +0000
committerevergreen <evergreen@mongodb.com>2019-10-18 15:23:50 +0000
commit186079301dc9de56313f5a8e84e6088fec289ded (patch)
tree573c7364f63d81ed3a160e2ac493818c8a5a6e8b
parented8a4f24d9d2816112054d28d48c69a0dc97fc00 (diff)
downloadmongo-186079301dc9de56313f5a8e84e6088fec289ded.tar.gz
SERVER-42312 disallow validate cmd during rollback and recovering states
(cherry picked from commit 1a3936b3ee365de5dde80e440c01fa6e868a1a54)
-rw-r--r--jstests/noPassthrough/standalone_replication_recovery.js6
-rw-r--r--jstests/replsets/validate_fails_during_rollback.js38
-rw-r--r--src/mongo/db/catalog/collection_validation.cpp6
-rw-r--r--src/mongo/db/commands/validate.cpp4
4 files changed, 54 insertions, 0 deletions
diff --git a/jstests/noPassthrough/standalone_replication_recovery.js b/jstests/noPassthrough/standalone_replication_recovery.js
index 6ee47fc9c20..55a6bb8e00c 100644
--- a/jstests/noPassthrough/standalone_replication_recovery.js
+++ b/jstests/noPassthrough/standalone_replication_recovery.js
@@ -79,6 +79,9 @@ node = rst.start(node, {noReplSet: true, setParameter: {logComponentVerbosity: l
reconnect(node);
assertDocsInColl(node, []);
+// Test that we can run the validate command on a standalone.
+assert.commandWorked(node.getDB(dbName).runCommand({"validate": collName}));
+
jsTestLog("Test that on restart with the flag set we play recovery.");
node = rst.restart(node, {
noReplSet: true,
@@ -87,6 +90,9 @@ node = rst.restart(node, {
reconnect(node);
assertDocsInColl(node, [3, 4, 5]);
+// Test that we can run the validate command on a standalone that recovered.
+assert.commandWorked(node.getDB(dbName).runCommand({"validate": collName}));
+
jsTestLog("Test that we go into read-only mode.");
assert.commandFailedWithCode(getColl(node).insert({_id: 1}), ErrorCodes.IllegalOperation);
diff --git a/jstests/replsets/validate_fails_during_rollback.js b/jstests/replsets/validate_fails_during_rollback.js
new file mode 100644
index 00000000000..8c67d33fd1a
--- /dev/null
+++ b/jstests/replsets/validate_fails_during_rollback.js
@@ -0,0 +1,38 @@
+/*
+ * This test makes sure the 'validate' command fails correctly during rollback.
+ */
+(function() {
+"use strict";
+
+load("jstests/replsets/libs/rollback_test.js");
+
+const dbName = "test";
+const collName = "coll";
+
+// Set up Rollback Test.
+let rollbackTest = new RollbackTest();
+
+let rollbackNode = rollbackTest.transitionToRollbackOperations();
+
+assert.commandWorked(rollbackNode.adminCommand(
+ {configureFailPoint: "rollbackHangAfterTransitionToRollback", mode: "alwaysOn"}));
+
+// Start rollback.
+rollbackTest.transitionToSyncSourceOperationsBeforeRollback();
+rollbackTest.transitionToSyncSourceOperationsDuringRollback();
+
+// Wait for rollback to hang.
+checkLog.contains(rollbackNode, "rollbackHangAfterTransitionToRollback fail point enabled.");
+
+// Try to run the validate command on the rollback node. This should fail with a NotMaster error.
+assert.commandFailedWithCode(rollbackNode.getDB(dbName).runCommand({"validate": collName}),
+ ErrorCodes.NotMasterOrSecondary);
+
+assert.commandWorked(rollbackNode.adminCommand(
+ {configureFailPoint: "rollbackHangAfterTransitionToRollback", mode: "off"}));
+
+rollbackTest.transitionToSteadyStateOperations();
+
+// Check the replica set.
+rollbackTest.stop();
+}());
diff --git a/src/mongo/db/catalog/collection_validation.cpp b/src/mongo/db/catalog/collection_validation.cpp
index bfd16f5e1a2..f39150516f8 100644
--- a/src/mongo/db/catalog/collection_validation.cpp
+++ b/src/mongo/db/catalog/collection_validation.cpp
@@ -472,6 +472,12 @@ Status validate(OperationContext* opCtx,
IndexConsistency indexConsistency(opCtx, collection);
ValidateAdaptor indexValidator = ValidateAdaptor(&indexConsistency, level, &indexNsResultsMap);
+ const auto replCoord = repl::ReplicationCoordinator::get(opCtx);
+ // Check whether we are allowed to read from this node after acquiring our locks. If we are
+ // in a state where we cannot read, we should not run validate.
+ uassertStatusOK(replCoord->checkCanServeReadsFor(
+ opCtx, nss, ReadPreferenceSetting::get(opCtx).canRunOnSecondary()));
+
try {
std::map<std::string, int64_t> numIndexKeysPerIndex;
diff --git a/src/mongo/db/commands/validate.cpp b/src/mongo/db/commands/validate.cpp
index 71c4ba0852f..fd0b37a8514 100644
--- a/src/mongo/db/commands/validate.cpp
+++ b/src/mongo/db/commands/validate.cpp
@@ -90,6 +90,10 @@ public:
return true;
}
+ bool maintenanceOk() const override {
+ return false;
+ }
+
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) const {