From: Igor Fedotov Date: Sat, 16 Jan 2021 16:54:52 +0000 (+0300) Subject: os/bluestore: fix deferred_queue locking X-Git-Tag: v17.0.0~27^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=ac73df71584eb482e626f38e4a12f4c044db3231;p=ceph.git os/bluestore: fix deferred_queue locking 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 --- diff --git a/src/os/bluestore/BlueStore.cc b/src/os/bluestore/BlueStore.cc index adc16660e3868..3f1a6cebf32a2 100644 --- a/src/os/bluestore/BlueStore.cc +++ b/src/os/bluestore/BlueStore.cc @@ -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()