]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: call wait_for_safe twice in command_flush_journal 4116/head
authorJohn Spray <john.spray@redhat.com>
Fri, 20 Mar 2015 17:11:39 +0000 (17:11 +0000)
committerJohn Spray <john.spray@redhat.com>
Fri, 20 Mar 2015 17:11:39 +0000 (17:11 +0000)
...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>
src/mds/MDS.cc

index 2b785c607a41a341d43136b24c6402a9d31e2335..a56d6ba177a1c78c64358c53059846415629ec2a 100644 (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
   // 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