From 035ab3c0e3a4a21c2fe6459a29642fc8856096cb Mon Sep 17 00:00:00 2001 From: John Spray Date: Fri, 20 Mar 2015 17:11:39 +0000 Subject: [PATCH] mds: call wait_for_safe twice in command_flush_journal ...so that we wait until everyone who was waiting for the first wait_for_safe has run their completion before we proceed, thus avoiding the possibility that those completions will execute during our trimming and cause problems. Fixes: #10368 Signed-off-by: John Spray --- src/mds/MDS.cc | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/src/mds/MDS.cc b/src/mds/MDS.cc index 2b785c607a4..a56d6ba177a 100644 --- a/src/mds/MDS.cc +++ b/src/mds/MDS.cc @@ -438,15 +438,34 @@ int MDS::_command_flush_journal(std::stringstream *ss) // Flush initially so that all the segments older than our new one // will be elegible for expiry - C_SaferCond mdlog_flushed; - mdlog->flush(); - mdlog->wait_for_safe(new MDSInternalContextWrapper(this, &mdlog_flushed)); - mds_lock.Unlock(); - r = mdlog_flushed.wait(); - mds_lock.Lock(); - if (r != 0) { - *ss << "Error " << r << " (" << cpp_strerror(r) << ") while flushing journal"; - return r; + { + C_SaferCond mdlog_flushed; + mdlog->flush(); + mdlog->wait_for_safe(new MDSInternalContextWrapper(this, &mdlog_flushed)); + mds_lock.Unlock(); + r = mdlog_flushed.wait(); + mds_lock.Lock(); + if (r != 0) { + *ss << "Error " << r << " (" << cpp_strerror(r) << ") while flushing journal"; + return r; + } + } + + // Because we may not be the last wait_for_safe context on MDLog, and + // subsequent contexts might wake up in the middle of our later trim_all + // and interfere with expiry (by e.g. marking dirs/dentries dirty + // on previous log segments), we run a second wait_for_safe here. + // See #10368 + { + C_SaferCond mdlog_cleared; + mdlog->wait_for_safe(new MDSInternalContextWrapper(this, &mdlog_cleared)); + mds_lock.Unlock(); + r = mdlog_cleared.wait(); + mds_lock.Lock(); + if (r != 0) { + *ss << "Error " << r << " (" << cpp_strerror(r) << ") while flushing journal"; + return r; + } } // Put all the old log segments into expiring or expired state