From ac73df71584eb482e626f38e4a12f4c044db3231 Mon Sep 17 00:00:00 2001 From: Igor Fedotov Date: Sat, 16 Jan 2021 19:54:52 +0300 Subject: [PATCH] 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 --- src/os/bluestore/BlueStore.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/os/bluestore/BlueStore.cc b/src/os/bluestore/BlueStore.cc index adc16660e386..3f1a6cebf32a 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() -- 2.47.3