From e0c55ab9ee5f431ca84bb3b6e40201ad009ac21e 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 (cherry picked from commit ac73df71584eb482e626f38e4a12f4c044db3231) --- 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 de2479a18b47b..34afd92c390e1 100644 --- a/src/os/bluestore/BlueStore.cc +++ b/src/os/bluestore/BlueStore.cc @@ -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() -- 2.39.5