]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
os/bluestore: fix deferred_queue locking
authorIgor Fedotov <ifedotov@suse.com>
Sat, 16 Jan 2021 16:54:52 +0000 (19:54 +0300)
committerNeha Ojha <nojha@redhat.com>
Wed, 20 Jan 2021 17:14:48 +0000 (17:14 +0000)
https://github.com/ceph/ceph/pull/30027 introduced a gap in osr
protection (in _deferred_queue()) which could cause improper deferred_pending value while
processing osr from _deferred_aio_finish().
As a result both segmentation fault in _deferred_aio_finish() or deadlock could occur.

Fixes: https://tracker.ceph.com/issues/48776
Signed-off-by: Igor Fedotov <ifedotov@suse.com>
(cherry picked from commit ac73df71584eb482e626f38e4a12f4c044db3231)

src/os/bluestore/BlueStore.cc

index de2479a18b47b3025825a747f79e31e14a290362..34afd92c390e1558b304b8592c2ed968ac2611ed 100644 (file)
@@ -12268,15 +12268,16 @@ void BlueStore::_deferred_queue(TransContext *txc)
   dout(20) << __func__ << " txc " << txc << " osr " << txc->osr << dendl;
 
   DeferredBatch *tmp;
+  bool need_lock_again = false;
+  txc->osr->deferred_lock.lock();
   {
-    txc->osr->deferred_lock.lock();
     if (!txc->osr->deferred_pending) {
       tmp = new DeferredBatch(cct, txc->osr.get());
+      txc->osr->deferred_lock.unlock();
+      need_lock_again = true;
     } else {
       tmp  = txc->osr->deferred_pending;
-      txc->osr->deferred_pending = nullptr;
     }
-    txc->osr->deferred_lock.unlock();
   }
 
   tmp->txcs.push_back(*txc);
@@ -12291,7 +12292,9 @@ void BlueStore::_deferred_queue(TransContext *txc)
   }
 
   {
-    txc->osr->deferred_lock.lock();
+    if (need_lock_again) {
+      txc->osr->deferred_lock.lock();
+    }
     ++deferred_queue_size;
     txc->osr->deferred_pending = tmp;
     // condition "tmp->txcs.size() == 1" mean deferred_pending was originally empty.
@@ -12309,7 +12312,6 @@ void BlueStore::_deferred_queue(TransContext *txc)
       txc->osr->deferred_lock.unlock();
     }
   }
-
  }
 
 void BlueStore::deferred_try_submit()