]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: place the journaler pointer under the mds_lock 41332/head
authorXiubo Li <xiubli@redhat.com>
Fri, 14 May 2021 02:38:49 +0000 (10:38 +0800)
committerXiubo Li <xiubli@redhat.com>
Fri, 14 May 2021 02:45:25 +0000 (10:45 +0800)
When the _recovery_thread is trying to reformat the journal, it
will delete the old journal pointer and assign with a new one,
during this the mds_lock is unlocked. That means in other threads,
such as when 'flush journal', who are using the MDSLog::journaler
pointer will potentially hit use-after-free bug.

Fixes: https://tracker.ceph.com/issues/50807
Signed-off-by: Xiubo Li <xiubli@redhat.com>
src/mds/MDLog.cc

index 1fc4b58f17e8281ffab939f88a67a55be5b06576..f438d6ba7ed638ed0ef1d6d46831a2d87db58365 100644 (file)
@@ -1086,9 +1086,9 @@ void MDLog::_recovery_thread(MDSContext *completion)
      * tolerate replaying old journals until we have to go active. Use front_journal as
      * our journaler attribute and complete */
     dout(4) << "Recovered journal " << jp.front << " in format " << front_journal->get_stream_format() << dendl;
-    journaler->set_write_error_handler(new C_MDL_WriteError(this));
     {
       std::lock_guard l(mds->mds_lock);
+      journaler->set_write_error_handler(new C_MDL_WriteError(this));
       if (mds->is_daemon_stopping()) {
         return;
       }
@@ -1271,17 +1271,14 @@ void MDLog::_reformat_journal(JournalPointer const &jp_in, Journaler *old_journa
     ceph_assert(journaler == old_journal);
     journaler = NULL;
     delete old_journal;
-  }
 
-  /* Update the pointer to reflect we're back in clean single journal state. */
-  jp.back = 0;
-  write_result = jp.save(mds->objecter);
-  ceph_assert(write_result == 0);
+    /* Update the pointer to reflect we're back in clean single journal state. */
+    jp.back = 0;
+    write_result = jp.save(mds->objecter);
+    ceph_assert(write_result == 0);
 
-  /* Reset the Journaler object to its default state */
-  dout(1) << "Journal rewrite complete, continuing with normal startup" << dendl;
-  {
-    std::lock_guard l(mds->mds_lock);
+    /* Reset the Journaler object to its default state */
+    dout(1) << "Journal rewrite complete, continuing with normal startup" << dendl;
     if (mds->is_daemon_stopping()) {
       delete new_journal;
       return;
@@ -1289,11 +1286,8 @@ void MDLog::_reformat_journal(JournalPointer const &jp_in, Journaler *old_journa
     journaler = new_journal;
     journaler->set_readonly();
     journaler->set_write_error_handler(new C_MDL_WriteError(this));
-  }
 
-  /* Trigger completion */
-  {
-    std::lock_guard l(mds->mds_lock);
+    /* Trigger completion */
     if (mds->is_daemon_stopping()) {
       return;
     }