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 <john.spray@redhat.com>
This commit is contained in:
John Spray 2015-03-20 17:11:39 +00:00
parent b94189f9c0
commit 035ab3c0e3

View File

@ -438,15 +438,34 @@ int MDS::_command_flush_journal(std::stringstream *ss)
// Flush initially so that all the segments older than our new one // Flush initially so that all the segments older than our new one
// will be elegible for expiry // will be elegible for expiry
C_SaferCond mdlog_flushed; {
mdlog->flush(); C_SaferCond mdlog_flushed;
mdlog->wait_for_safe(new MDSInternalContextWrapper(this, &mdlog_flushed)); mdlog->flush();
mds_lock.Unlock(); mdlog->wait_for_safe(new MDSInternalContextWrapper(this, &mdlog_flushed));
r = mdlog_flushed.wait(); mds_lock.Unlock();
mds_lock.Lock(); r = mdlog_flushed.wait();
if (r != 0) { mds_lock.Lock();
*ss << "Error " << r << " (" << cpp_strerror(r) << ") while flushing journal"; if (r != 0) {
return r; *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 // Put all the old log segments into expiring or expired state