diff options
author | Spencer T Brody <spencer@mongodb.com> | 2018-09-07 13:24:55 -0400 |
---|---|---|
committer | Spencer T Brody <spencer@mongodb.com> | 2018-09-10 16:55:41 -0400 |
commit | d60fb7f0d2093519d9939aed3486fea3f9ab3228 (patch) | |
tree | 2cbadc05b79d599024ccb2296cb5b176ff3a61a0 /src/mongo | |
parent | ce32b09281eb8b661f4440e12fe72371d49fc2c1 (diff) | |
download | mongo-d60fb7f0d2093519d9939aed3486fea3f9ab3228.tar.gz |
SERVER-37048 Hold global intent lock whenever accessing the oplog collection pointer
(cherry picked from commit 976b19732685d132e636c34a5b2fe7462def0818)
Diffstat (limited to 'src/mongo')
8 files changed, 7 insertions, 33 deletions
diff --git a/src/mongo/db/repl/replication_coordinator_external_state.h b/src/mongo/db/repl/replication_coordinator_external_state.h index 58536d534c4..979ead025d1 100644 --- a/src/mongo/db/repl/replication_coordinator_external_state.h +++ b/src/mongo/db/repl/replication_coordinator_external_state.h @@ -121,13 +121,6 @@ public: virtual Status initializeReplSetStorage(OperationContext* opCtx, const BSONObj& config) = 0; /** - * Waits for all committed writes to be visible in the oplog. Committed writes will be hidden - * if there are uncommitted writes ahead of them, and some operations require that all committed - * writes are visible before proceeding. Throws if the oplog does not exist. - */ - virtual void waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx) = 0; - - /** * Called when a node on way to becoming a primary is ready to leave drain mode. It is called * outside of the global X lock and the replication coordinator mutex. * diff --git a/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp b/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp index e88fd127d56..543ac0108e8 100644 --- a/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp @@ -423,7 +423,7 @@ Status ReplicationCoordinatorExternalStateImpl::initializeReplSetStorage(Operati // retries and they will succeed. Unfortunately, initial sync will // fail if it finds its sync source has an empty oplog. Thus, we // need to wait here until the seed document is visible in our oplog. - waitForAllEarlierOplogWritesToBeVisible(opCtx); + _storageInterface->waitForAllEarlierOplogWritesToBeVisible(opCtx); }); // Update unique index format version for all non-replicated collections. It is possible @@ -457,22 +457,6 @@ Status ReplicationCoordinatorExternalStateImpl::initializeReplSetStorage(Operati return Status::OK(); } -void ReplicationCoordinatorExternalStateImpl::waitForAllEarlierOplogWritesToBeVisible( - OperationContext* opCtx) { - Collection* oplog; - { - // We don't want to be holding the collection lock while blocking, to avoid deadlocks. - // It is safe to store and access the oplog's Collection object after dropping the lock - // because the oplog is special and cannot be deleted on a running process. - // TODO(spencer): It should be possible to get the pointer to the oplog Collection object - // without ever having to take the collection lock. - AutoGetCollection oplogLock(opCtx, NamespaceString::kRsOplogNamespace, MODE_IS); - oplog = oplogLock.getCollection(); - } - uassert(ErrorCodes::NotYetInitialized, "The oplog does not exist", oplog); - oplog->getRecordStore()->waitForAllEarlierOplogWritesToBeVisible(opCtx); -} - void ReplicationCoordinatorExternalStateImpl::onDrainComplete(OperationContext* opCtx) { invariant(!opCtx->lockState()->isLocked()); diff --git a/src/mongo/db/repl/replication_coordinator_external_state_impl.h b/src/mongo/db/repl/replication_coordinator_external_state_impl.h index 8607be1af20..78ed36f1a8e 100644 --- a/src/mongo/db/repl/replication_coordinator_external_state_impl.h +++ b/src/mongo/db/repl/replication_coordinator_external_state_impl.h @@ -78,7 +78,6 @@ public: virtual ThreadPool* getDbWorkThreadPool() const override; virtual Status runRepairOnLocalDB(OperationContext* opCtx) override; virtual Status initializeReplSetStorage(OperationContext* opCtx, const BSONObj& config); - virtual void waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx); void onDrainComplete(OperationContext* opCtx) override; OpTime onTransitionToPrimary(OperationContext* opCtx, bool isV1ElectionProtocol) override; virtual void forwardSlaveProgress(); diff --git a/src/mongo/db/repl/replication_coordinator_external_state_mock.cpp b/src/mongo/db/repl/replication_coordinator_external_state_mock.cpp index 5a4ab25d6e4..c168ab668df 100644 --- a/src/mongo/db/repl/replication_coordinator_external_state_mock.cpp +++ b/src/mongo/db/repl/replication_coordinator_external_state_mock.cpp @@ -81,9 +81,6 @@ Status ReplicationCoordinatorExternalStateMock::initializeReplSetStorage(Operati return storeLocalConfigDocument(opCtx, config); } -void ReplicationCoordinatorExternalStateMock::waitForAllEarlierOplogWritesToBeVisible( - OperationContext* opCtx) {} - void ReplicationCoordinatorExternalStateMock::shutdown(OperationContext*) {} executor::TaskExecutor* ReplicationCoordinatorExternalStateMock::getTaskExecutor() const { diff --git a/src/mongo/db/repl/replication_coordinator_external_state_mock.h b/src/mongo/db/repl/replication_coordinator_external_state_mock.h index e8169616079..dfff768c1fb 100644 --- a/src/mongo/db/repl/replication_coordinator_external_state_mock.h +++ b/src/mongo/db/repl/replication_coordinator_external_state_mock.h @@ -67,7 +67,6 @@ public: virtual ThreadPool* getDbWorkThreadPool() const override; virtual Status runRepairOnLocalDB(OperationContext* opCtx) override; virtual Status initializeReplSetStorage(OperationContext* opCtx, const BSONObj& config); - virtual void waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx); void onDrainComplete(OperationContext* opCtx) override; OpTime onTransitionToPrimary(OperationContext* opCtx, bool isV1ElectionProtocol) override; virtual void forwardSlaveProgress(); diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp index 271f5f64195..b6d1a634a9f 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl.cpp @@ -1272,7 +1272,7 @@ Status ReplicationCoordinatorImpl::_waitUntilOpTime(OperationContext* opCtx, // This assumes the read concern is "local" level. // We need to wait for all committed writes to be visible, even in the oplog (which uses // special visibility rules). - _externalState->waitForAllEarlierOplogWritesToBeVisible(opCtx); + _storage->waitForAllEarlierOplogWritesToBeVisible(opCtx); } stdx::unique_lock<stdx::mutex> lock(_mutex); diff --git a/src/mongo/db/repl/storage_interface_impl.cpp b/src/mongo/db/repl/storage_interface_impl.cpp index 927d57b8f61..735ee035376 100644 --- a/src/mongo/db/repl/storage_interface_impl.cpp +++ b/src/mongo/db/repl/storage_interface_impl.cpp @@ -1125,16 +1125,18 @@ Status StorageInterfaceImpl::isAdminDbValid(OperationContext* opCtx) { } void StorageInterfaceImpl::waitForAllEarlierOplogWritesToBeVisible(OperationContext* opCtx) { + Lock::GlobalLock lk(opCtx, MODE_IS); Collection* oplog; { // We don't want to be holding the collection lock while blocking, to avoid deadlocks. - // It is safe to store and access the oplog's Collection object after dropping the lock - // because the oplog is special and cannot be deleted on a running process. + // It is safe to store and access the oplog's Collection object with just the global IS + // lock because of the special concurrency rules for the oplog. // TODO(spencer): It should be possible to get the pointer to the oplog Collection object // without ever having to take the collection lock. AutoGetCollection oplogLock(opCtx, NamespaceString::kRsOplogNamespace, MODE_IS); oplog = oplogLock.getCollection(); } + uassert(ErrorCodes::NotYetInitialized, "The oplog does not exist", oplog); oplog->getRecordStore()->waitForAllEarlierOplogWritesToBeVisible(opCtx); } diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp index 07e1e0e8088..b08716f7a32 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp @@ -2015,7 +2015,7 @@ void StandardWiredTigerRecordStore::setKey(WT_CURSOR* cursor, RecordId id) const std::unique_ptr<SeekableRecordCursor> StandardWiredTigerRecordStore::getCursor( OperationContext* opCtx, bool forward) const { - dassert(opCtx->lockState()->isReadLocked() || _isOplog); + dassert(opCtx->lockState()->isReadLocked()); if (_isOplog && forward) { WiredTigerRecoveryUnit* wru = WiredTigerRecoveryUnit::get(opCtx); |