diff options
author | Esha Maharishi <esha.maharishi@mongodb.com> | 2017-09-26 12:26:07 -0400 |
---|---|---|
committer | Esha Maharishi <esha.maharishi@mongodb.com> | 2017-09-26 13:06:13 -0400 |
commit | 726e5544108d7ef417de351d103f52c028feae3b (patch) | |
tree | b72164766f99443e89061951864024bdb434a1dd /src/mongo/db | |
parent | dabde5a17356591ebcb465129bcd5ed5d9236b60 (diff) | |
download | mongo-726e5544108d7ef417de351d103f52c028feae3b.tar.gz |
SERVER-30344 prevent shards from implicitly creating a collection on createIndexes
Diffstat (limited to 'src/mongo/db')
-rw-r--r-- | src/mongo/db/catalog/database_impl.cpp | 5 | ||||
-rw-r--r-- | src/mongo/db/commands.h | 33 | ||||
-rw-r--r-- | src/mongo/db/s/operation_sharding_state.cpp | 9 | ||||
-rw-r--r-- | src/mongo/db/s/operation_sharding_state.h | 16 | ||||
-rw-r--r-- | src/mongo/db/service_entry_point_mongod.cpp | 8 |
5 files changed, 54 insertions, 17 deletions
diff --git a/src/mongo/db/catalog/database_impl.cpp b/src/mongo/db/catalog/database_impl.cpp index a379f96c516..5f6f7d61748 100644 --- a/src/mongo/db/catalog/database_impl.cpp +++ b/src/mongo/db/catalog/database_impl.cpp @@ -60,6 +60,7 @@ #include "mongo/db/repl/drop_pending_collection_reaper.h" #include "mongo/db/repl/oplog.h" #include "mongo/db/repl/replication_coordinator_global.h" +#include "mongo/db/s/operation_sharding_state.h" #include "mongo/db/server_options.h" #include "mongo/db/server_parameters.h" #include "mongo/db/service_context.h" @@ -756,6 +757,10 @@ Collection* DatabaseImpl::createCollection(OperationContext* opCtx, invariant(opCtx->lockState()->isDbLockedForMode(name(), MODE_X)); invariant(!options.isView()); + uassert(ErrorCodes::CannotImplicitlyCreateCollection, + "request was sent with 'disallowCollectionCreation' field", + OperationShardingState::get(opCtx).allowCollectionCreation()); + CollectionOptions optionsWithUUID = options; if (enableCollectionUUIDs && !optionsWithUUID.uuid && serverGlobalParams.featureCompatibility.isSchemaVersion36.load() == true) { diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h index 79641088af1..c2b91aa9b7a 100644 --- a/src/mongo/db/commands.h +++ b/src/mongo/db/commands.h @@ -459,22 +459,23 @@ public: // Not including "help" since we don't pass help requests through to the command parser. // If that changes, it should be added. When you add to this list, consider whether you // should also change the filterCommandRequestForPassthrough() function. - return arg == "$audit" || // - arg == "$client" || // - arg == "$configServerState" || // - arg == "$db" || // - arg == "$oplogQueryData" || // - arg == "$queryOptions" || // - arg == "$readPreference" || // - arg == "$replData" || // - arg == "$clusterTime" || // - arg == "maxTimeMS" || // - arg == "readConcern" || // - arg == "shardVersion" || // - arg == "tracking_info" || // - arg == "writeConcern" || // - arg == "lsid" || // - arg == "txnNumber" || // + return arg == "$audit" || // + arg == "$client" || // + arg == "$configServerState" || // + arg == "$db" || // + arg == "disallowCollectionCreation" || // + arg == "$oplogQueryData" || // + arg == "$queryOptions" || // + arg == "$readPreference" || // + arg == "$replData" || // + arg == "$clusterTime" || // + arg == "maxTimeMS" || // + arg == "readConcern" || // + arg == "shardVersion" || // + arg == "tracking_info" || // + arg == "writeConcern" || // + arg == "lsid" || // + arg == "txnNumber" || // false; // These comments tell clang-format to keep this line-oriented. } diff --git a/src/mongo/db/s/operation_sharding_state.cpp b/src/mongo/db/s/operation_sharding_state.cpp index f465cc22a24..88d18bae218 100644 --- a/src/mongo/db/s/operation_sharding_state.cpp +++ b/src/mongo/db/s/operation_sharding_state.cpp @@ -50,6 +50,15 @@ OperationShardingState& OperationShardingState::get(OperationContext* opCtx) { return shardingMetadataDecoration(opCtx); } +void OperationShardingState::setDisallowCollectionCreationIfNeeded( + const BSONElement& disallowCollectionCreationElt) { + _disallowCollectionCreation = disallowCollectionCreationElt.trueValue(); +} + +bool OperationShardingState::allowCollectionCreation() { + return !_disallowCollectionCreation; +} + void OperationShardingState::initializeShardVersion(NamespaceString nss, const BSONElement& shardVersionElt) { invariant(!hasShardVersion()); diff --git a/src/mongo/db/s/operation_sharding_state.h b/src/mongo/db/s/operation_sharding_state.h index 53ed73f89af..7c42e8840f3 100644 --- a/src/mongo/db/s/operation_sharding_state.h +++ b/src/mongo/db/s/operation_sharding_state.h @@ -59,6 +59,19 @@ public: static OperationShardingState& get(OperationContext* opCtx); /** + * Requests on a sharded collection that are broadcast without a shardVersion should not cause + * the collection to be created on a shard that does not know about the collection already, + * since the collection options will not be propagated. Such requests specify to disallow + * collection creation, which is saved here. + */ + void setDisallowCollectionCreationIfNeeded(const BSONElement& disallowCollectionCreationElt); + + /** + * Returns false if the request specified not to allow collection creation. + */ + bool allowCollectionCreation(); + + /** * Parses shard version from the command parameters 'cmdObj' and stores the results in this * object along with the give namespace that is associated with the version. Does nothing * if no shard version is attached to the command. @@ -118,6 +131,9 @@ private: */ void _clear(); + // This value is set if a request specifies not to allow collection creation. + bool _disallowCollectionCreation = false; + bool _hasVersion = false; ChunkVersion _shardVersion{ChunkVersion::UNSHARDED()}; NamespaceString _ns; diff --git a/src/mongo/db/service_entry_point_mongod.cpp b/src/mongo/db/service_entry_point_mongod.cpp index dfec6d0382b..3bd917f6d02 100644 --- a/src/mongo/db/service_entry_point_mongod.cpp +++ b/src/mongo/db/service_entry_point_mongod.cpp @@ -556,6 +556,7 @@ void execCommandDatabase(OperationContext* opCtx, std::unique_ptr<MaintenanceModeSetter> mmSetter; BSONElement cmdOptionMaxTimeMSField; + BSONElement disallowCollectionCreationField; BSONElement helpField; BSONElement shardVersionFieldIdx; BSONElement queryOptionMaxTimeMSField; @@ -565,6 +566,8 @@ void execCommandDatabase(OperationContext* opCtx, StringData fieldName = element.fieldNameStringData(); if (fieldName == QueryRequest::cmdOptionMaxTimeMS) { cmdOptionMaxTimeMSField = element; + } else if (fieldName == "disallowCollectionCreation") { + disallowCollectionCreationField = element; } else if (fieldName == Command::kHelpFieldName) { helpField = element; } else if (fieldName == ChunkVersion::kShardVersionField) { @@ -669,6 +672,8 @@ void execCommandDatabase(OperationContext* opCtx, request.body, command->supportsNonLocalReadConcern(request.getDatabase().toString(), request.body))); + auto& oss = OperationShardingState::get(opCtx); + // Don't handle the shard version that may have been sent along with the command iff // fcv==3.4: This is a secondary. // fcv==3.6: The 'available' rc-level is specified, or this is a secondary and neither the @@ -684,7 +689,6 @@ void execCommandDatabase(OperationContext* opCtx, ServerGlobalParams::FeatureCompatibility::Version::k34 || !repl::ReadConcernArgs::get(opCtx).isLevelAvailable())) { auto commandNS = NamespaceString(command->parseNs(dbname, request.body)); - auto& oss = OperationShardingState::get(opCtx); oss.initializeShardVersion(commandNS, shardVersionFieldIdx); auto shardingState = ShardingState::get(opCtx); if (oss.hasShardVersion()) { @@ -695,6 +699,8 @@ void execCommandDatabase(OperationContext* opCtx, uassertStatusOK(shardingState->updateConfigServerOpTimeFromMetadata(opCtx)); } + oss.setDisallowCollectionCreationIfNeeded(disallowCollectionCreationField); + // Can throw opCtx->checkForInterrupt(); // May trigger maxTimeAlwaysTimeOut fail point. |