diff options
author | Pavithra Vetriselvan <pavithra.vetriselvan@mongodb.com> | 2019-10-18 15:23:50 +0000 |
---|---|---|
committer | evergreen <evergreen@mongodb.com> | 2019-10-18 15:23:50 +0000 |
commit | 186079301dc9de56313f5a8e84e6088fec289ded (patch) | |
tree | 573c7364f63d81ed3a160e2ac493818c8a5a6e8b | |
parent | ed8a4f24d9d2816112054d28d48c69a0dc97fc00 (diff) | |
download | mongo-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.js | 6 | ||||
-rw-r--r-- | jstests/replsets/validate_fails_during_rollback.js | 38 | ||||
-rw-r--r-- | src/mongo/db/catalog/collection_validation.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/commands/validate.cpp | 4 |
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 { |