]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
os/bluestore: fix deferred_queue locking 38934/head
authorIgor Fedotov <ifedotov@suse.com>
Sat, 16 Jan 2021 16:54:52 +0000 (19:54 +0300)
committerIgor Fedotov <ifedotov@suse.com>
Sat, 16 Jan 2021 16:54:52 +0000 (19:54 +0300)
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>
src/os/bluestore/BlueStore.cc

index adc16660e386895b6f481da5124bf618589aca09..3f1a6cebf32a267dcfe0a734c5ef6f85f392b002 100644 (file)
@@ -12240,15 +12240,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);
@@ -12263,7 +12264,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.
@@ -12281,7 +12284,6 @@ void BlueStore::_deferred_queue(TransContext *txc)
       txc->osr->deferred_lock.unlock();
     }
   }
-
  }
 
 void BlueStore::deferred_try_submit()