summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2015-01-16 17:08:13 -0500
committerMark Benvenuto <mark.benvenuto@mongodb.com>2015-01-20 11:17:35 -0500
commit7221fd14ea822cf380e53ec89f5848fb5295163b (patch)
treecb2ded662f22a7f1914603caaaa37695bfa0457b
parentf8c0611e742c07a293da9cb49baac211fe1d8874 (diff)
downloadmongo-7221fd14ea822cf380e53ec89f5848fb5295163b.tar.gz
SERVER-16092: Serialize writes to admin db for auth collections
-rw-r--r--src/mongo/db/concurrency/d_concurrency.cpp8
-rw-r--r--src/mongo/db/concurrency/d_concurrency_test.cpp32
-rw-r--r--src/mongo/db/concurrency/lock_manager_defs.h3
-rw-r--r--src/mongo/db/concurrency/lock_state.cpp1
4 files changed, 44 insertions, 0 deletions
diff --git a/src/mongo/db/concurrency/d_concurrency.cpp b/src/mongo/db/concurrency/d_concurrency.cpp
index a596c70c69c..55a32193a10 100644
--- a/src/mongo/db/concurrency/d_concurrency.cpp
+++ b/src/mongo/db/concurrency/d_concurrency.cpp
@@ -160,7 +160,15 @@ namespace mongo {
const bool isRead = (_mode == MODE_S || _mode == MODE_IS);
_lockState->lockGlobal(isRead ? MODE_IS : MODE_IX);
+
if (supportsDocLocking() || enableCollectionLocking) {
+
+ // The check for the admin db is to ensure direct writes to auth collections
+ // are serialized (see SERVER-16092).
+ if (_id == resourceIdAdminDB && !isRead) {
+ _mode = MODE_X;
+ }
+
_lockState->lock(_id, _mode);
}
else {
diff --git a/src/mongo/db/concurrency/d_concurrency_test.cpp b/src/mongo/db/concurrency/d_concurrency_test.cpp
index e449f3c88cd..8ca594a21e6 100644
--- a/src/mongo/db/concurrency/d_concurrency_test.cpp
+++ b/src/mongo/db/concurrency/d_concurrency_test.cpp
@@ -172,6 +172,38 @@ namespace mongo {
ASSERT(ls.getLockMode(resIdDb) == MODE_X);
}
+ TEST(DConcurrency, DBLockTakesISForAdminIS) {
+ DefaultLockerImpl ls;
+
+ Lock::DBLock dbRead(&ls, "admin", MODE_IS);
+
+ ASSERT(ls.getLockMode(resourceIdAdminDB) == MODE_IS);
+ }
+
+ TEST(DConcurrency, DBLockTakesSForAdminS) {
+ DefaultLockerImpl ls;
+
+ Lock::DBLock dbRead(&ls, "admin", MODE_S);
+
+ ASSERT(ls.getLockMode(resourceIdAdminDB) == MODE_S);
+ }
+
+ TEST(DConcurrency, DBLockTakesXForAdminIX) {
+ DefaultLockerImpl ls;
+
+ Lock::DBLock dbWrite(&ls, "admin", MODE_IX);
+
+ ASSERT(ls.getLockMode(resourceIdAdminDB) == MODE_X);
+ }
+
+ TEST(DConcurrency, DBLockTakesXForAdminX) {
+ DefaultLockerImpl ls;
+
+ Lock::DBLock dbWrite(&ls, "admin", MODE_X);
+
+ ASSERT(ls.getLockMode(resourceIdAdminDB) == MODE_X);
+ }
+
TEST(DConcurrency, MultipleWriteDBLocksOnSameThread) {
MMAPV1LockerImpl ls;
diff --git a/src/mongo/db/concurrency/lock_manager_defs.h b/src/mongo/db/concurrency/lock_manager_defs.h
index 77bec0d433f..7759ab193d7 100644
--- a/src/mongo/db/concurrency/lock_manager_defs.h
+++ b/src/mongo/db/concurrency/lock_manager_defs.h
@@ -217,6 +217,9 @@ namespace mongo {
extern const ResourceId resourceIdLocalDB;
extern const ResourceId resourceIdOplog;
+ // Hardcoded resource id for admin db. This is to ensure direct writes to auth collections
+ // are serialized (see SERVER-16092)
+ extern const ResourceId resourceIdAdminDB;
/**
* Interface on which granted lock requests will be notified. See the contract for the notify
diff --git a/src/mongo/db/concurrency/lock_state.cpp b/src/mongo/db/concurrency/lock_state.cpp
index 1b9c3218db5..a37ddc2d8fe 100644
--- a/src/mongo/db/concurrency/lock_state.cpp
+++ b/src/mongo/db/concurrency/lock_state.cpp
@@ -868,5 +868,6 @@ namespace {
const ResourceId resourceIdLocalDB = ResourceId(RESOURCE_DATABASE, StringData("local"));
const ResourceId resourceIdOplog =
ResourceId(RESOURCE_COLLECTION, StringData("local.oplog.rs"));
+ const ResourceId resourceIdAdminDB = ResourceId(RESOURCE_DATABASE, StringData("admin"));
} // namespace mongo