summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorEsha Maharishi <esha.maharishi@mongodb.com>2017-09-26 12:26:07 -0400
committerEsha Maharishi <esha.maharishi@mongodb.com>2017-09-26 13:06:13 -0400
commit726e5544108d7ef417de351d103f52c028feae3b (patch)
treeb72164766f99443e89061951864024bdb434a1dd /src/mongo/db
parentdabde5a17356591ebcb465129bcd5ed5d9236b60 (diff)
downloadmongo-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.cpp5
-rw-r--r--src/mongo/db/commands.h33
-rw-r--r--src/mongo/db/s/operation_sharding_state.cpp9
-rw-r--r--src/mongo/db/s/operation_sharding_state.h16
-rw-r--r--src/mongo/db/service_entry_point_mongod.cpp8
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.