From: John Spray Date: Fri, 20 Mar 2015 17:11:39 +0000 (+0000) Subject: mds: call wait_for_safe twice in command_flush_journal X-Git-Tag: v9.0.0~134^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F4116%2Fhead;p=ceph.git 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 --- diff --git a/src/mds/MDS.cc b/src/mds/MDS.cc index 2b785c607a41..a56d6ba177a1 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