diff options
author | Dianna Hohensee <dianna.hohensee@mongodb.com> | 2021-12-01 00:04:35 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-01-04 22:38:23 +0000 |
commit | 60af56dfe1a17c60bbd628163fda0a161105b6c0 (patch) | |
tree | a0c535b188f4e7ac6baa6dead874909e71ea0ac1 | |
parent | 2e3933d29e692c50d04b02a240b4b75a124d564e (diff) | |
download | mongo-60af56dfe1a17c60bbd628163fda0a161105b6c0.tar.gz |
SERVER-61201 Prevent deadlock when user tries to create a view on the database system.views collectionr5.0.6-rc0
(cherry picked from commit dfce26e49c0c124db64cab66036bfd92388fc31d)
-rw-r--r-- | jstests/core/views/views_creation.js | 17 | ||||
-rw-r--r-- | src/mongo/db/catalog/create_collection.cpp | 8 |
2 files changed, 24 insertions, 1 deletions
diff --git a/jstests/core/views/views_creation.js b/jstests/core/views/views_creation.js index 2b5316ad400..9af06a3bc4e 100644 --- a/jstests/core/views/views_creation.js +++ b/jstests/core/views/views_creation.js @@ -13,6 +13,8 @@ (function() { "use strict"; +load('jstests/multiVersion/libs/verify_versions.js'); // for getBinVersion() + // For arrayEq. load("jstests/aggregation/extras/utils.js"); @@ -27,7 +29,7 @@ assert.eq(0, collNames.length, tojson(collNames)); // You cannot create a view that starts with 'system.'. assert.commandFailedWithCode(viewsDB.runCommand({create: "system.special", viewOn: "collection"}), ErrorCodes.InvalidNamespace, - "Created an illegal view named 'system.views'"); + "Created an illegal view named 'system.special'"); // Collections that start with 'system.' that are not special to MongoDB fail with a different // error code. @@ -35,6 +37,19 @@ assert.commandFailedWithCode(viewsDB.runCommand({create: "system.foo", viewOn: " ErrorCodes.InvalidNamespace, "Created an illegal view named 'system.foo'"); +const mongodBinVersion = viewsDB.getMongo().getBinVersion(); +if (MongoRunner.areBinVersionsTheSame(mongodBinVersion, "latest")) { + // Attempting to create a view on a database's views collection namespace is specially handled + // because it can deadlock. Only running on v5.0 b/c v4.4 doesn't fail user creation of the + // system.views namespace. + const errRes = assert.commandFailedWithCode( + viewsDB.runCommand({create: "system.views", viewOn: "collection"}), + ErrorCodes.InvalidNamespace, + "Created an illegal view named <db>.system.views"); + assert((errRes.errmsg.indexOf("Cannot create a view called") > -1), + "Unexpected errmsg: " + tojson(errRes)); +} + // Create a collection for test purposes. assert.commandWorked(viewsDB.runCommand({create: "collection"})); diff --git a/src/mongo/db/catalog/create_collection.cpp b/src/mongo/db/catalog/create_collection.cpp index 50a746a5003..461efd0bcb6 100644 --- a/src/mongo/db/catalog/create_collection.cpp +++ b/src/mongo/db/catalog/create_collection.cpp @@ -76,6 +76,14 @@ void _createSystemDotViewsIfNecessary(OperationContext* opCtx, const Database* d Status _createView(OperationContext* opCtx, const NamespaceString& nss, CollectionOptions&& collectionOptions) { + // This must be checked before we take locks in order to avoid attempting to take multiple locks + // on the <db>.system.views namespace: first a IX lock on 'ns' and then a X lock on the database + // system.views collection. + uassert(ErrorCodes::InvalidNamespace, + str::stream() << "Cannot create a view called '" << nss.coll() + << "': this is a reserved system namespace", + !nss.isSystemDotViews()); + return writeConflictRetry(opCtx, "create", nss.ns(), [&] { AutoGetDb autoDb(opCtx, nss.db(), MODE_IX); Lock::CollectionLock collLock(opCtx, nss, MODE_IX); |