diff options
author | Geert Bosch <geert@mongodb.com> | 2017-02-07 09:46:50 -0500 |
---|---|---|
committer | Geert Bosch <geert@mongodb.com> | 2017-03-03 12:45:42 -0500 |
commit | 872db0ea7eaa70a1d323b02343a1872d633196be (patch) | |
tree | 574513183d8aeb1115dbfb8c59a03673e09f3c5a | |
parent | 603c4c2e4d588daeedb4c258d3dec88bad7cec31 (diff) | |
download | mongo-872db0ea7eaa70a1d323b02343a1872d633196be.tar.gz |
SERVER-27935 Fix serialization of concurrent fsyncLock executions
(cherry picked from commit e02c45b789458bb5bb3ba8350f4fd91305933deb)
-rw-r--r-- | src/mongo/db/commands/fsync.cpp | 91 |
1 files changed, 47 insertions, 44 deletions
diff --git a/src/mongo/db/commands/fsync.cpp b/src/mongo/db/commands/fsync.cpp index cecf3975f17..17a2b0668dd 100644 --- a/src/mongo/db/commands/fsync.cpp +++ b/src/mongo/db/commands/fsync.cpp @@ -128,55 +128,13 @@ public: return false; } - Lock::ExclusiveLock(txn->lockState(), commandMutex); const bool sync = !cmdObj["async"].trueValue(); // async means do an fsync, but return immediately const bool lock = cmdObj["lock"].trueValue(); log() << "CMD fsync: sync:" << sync << " lock:" << lock; - if (lock) { - if (!sync) { - errmsg = "fsync: sync option must be true when using lock"; - return false; - } - - const auto lockCountAtStart = getLockCount(); - invariant(lockCountAtStart > 0 || !_lockThread); - - acquireLock(); - - if (lockCountAtStart == 0) { - - Status status = Status::OK(); - { - stdx::unique_lock<stdx::mutex> lk(lockStateMutex); - threadStatus = Status::OK(); - threadStarted = false; - _lockThread = stdx::make_unique<FSyncLockThread>(); - _lockThread->go(); - - while (!threadStarted && threadStatus.isOK()) { - acquireFsyncLockSyncCV.wait(lk); - } - - // 'threadStatus' must be copied while 'lockStateMutex' is held. - status = threadStatus; - } - if (!status.isOK()) { - releaseLock(); - warning() << "fsyncLock failed. Lock count reset to 0. Status: " << status; - return appendCommandStatus(result, status); - } - } - - log() << "mongod is locked and no writes are allowed. db.fsyncUnlock() to unlock"; - log() << "Lock count is " << getLockCount(); - log() << " For more info see " << FSyncCommand::url(); - result.append("info", "now locked against writes, use db.fsyncUnlock() to unlock"); - result.append("lockCount", getLockCount()); - result.append("seeAlso", FSyncCommand::url()); - } else { + if (!lock) { // the simple fsync command case if (sync) { // can this be GlobalRead? and if it can, it should be nongreedy. @@ -193,7 +151,52 @@ public: Lock::GlobalLock global(txn->lockState(), MODE_IS, UINT_MAX); StorageEngine* storageEngine = getGlobalServiceContext()->getGlobalStorageEngine(); result.append("numFiles", storageEngine->flushAllFiles(sync)); + return true; } + + Lock::ExclusiveLock lk(txn->lockState(), commandMutex); + if (!sync) { + errmsg = "fsync: sync option must be true when using lock"; + return false; + } + + const auto lockCountAtStart = getLockCount(); + invariant(lockCountAtStart > 0 || !_lockThread); + + acquireLock(); + + if (lockCountAtStart == 0) { + + Status status = Status::OK(); + { + stdx::unique_lock<stdx::mutex> lk(lockStateMutex); + threadStatus = Status::OK(); + threadStarted = false; + _lockThread = stdx::make_unique<FSyncLockThread>(); + _lockThread->go(); + + while (!threadStarted && threadStatus.isOK()) { + acquireFsyncLockSyncCV.wait(lk); + } + + // 'threadStatus' must be copied while 'lockStateMutex' is held. + status = threadStatus; + } + + if (!status.isOK()) { + releaseLock(); + warning() << "fsyncLock failed. Lock count reset to 0. Status: " << status; + return appendCommandStatus(result, status); + } + } + + log() << "mongod is locked and no writes are allowed. db.fsyncUnlock() to unlock"; + log() << "Lock count is " << getLockCount(); + log() << " For more info see " << FSyncCommand::url(); + result.append("info", "now locked against writes, use db.fsyncUnlock() to unlock"); + result.append("lockCount", getLockCount()); + result.append("seeAlso", FSyncCommand::url()); + return true; } @@ -297,7 +300,7 @@ public: BSONObjBuilder& result) override { log() << "command: unlock requested"; - Lock::ExclusiveLock(txn->lockState(), commandMutex); + Lock::ExclusiveLock lk(txn->lockState(), commandMutex); if (unlockFsync()) { const auto lockCount = fsyncCmd.getLockCount(); |