From 18c4cbd7b1cc122bfa40e26d8caed76bc09a2ca5 Mon Sep 17 00:00:00 2001 From: Samuel Just Date: Thu, 13 Jun 2024 00:41:55 +0000 Subject: [PATCH] crimson: fix ObjectContext::_with_lock to only unlock if lock is taken Fixes: https://tracker.ceph.com/issues/66461 Signed-off-by: Samuel Just (cherry picked from commit 9e0c518d37ce1ba17139629e75d780cc0f0f064f) --- src/crimson/osd/object_context.h | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/crimson/osd/object_context.h b/src/crimson/osd/object_context.h index 466f22b8372f3..b1a1e89382767 100644 --- a/src/crimson/osd/object_context.h +++ b/src/crimson/osd/object_context.h @@ -137,22 +137,34 @@ public: private: template auto _with_lock(Lock& lock, Func&& func) { - Ref obc = this; auto maybe_fut = lock.lock(); return seastar::futurize_invoke([ maybe_fut=std::move(maybe_fut), - func=std::forward(func)]() mutable { + func=std::forward(func), + obc=Ref(this), + &lock]() mutable { if (maybe_fut) { return std::move(*maybe_fut - ).then([func=std::forward(func)]() mutable { - return seastar::futurize_invoke(func); + ).then([func=std::forward(func), obc, &lock]() mutable { + return seastar::futurize_invoke( + func + ).finally([&lock, obc] { + /* We chain the finally block here because it's possible for + * *maybe_fut from lock.lock() above to fail due to a call to + * ObjectContext::interrupt, which calls tri_mutex::abort. + * In the event of such an error, the lock isn't actually taken + * and calling unlock() would be incorrect. */ + lock.unlock(); + }); }); } else { // atomically calling func upon locking - return seastar::futurize_invoke(func); + return seastar::futurize_invoke( + func + ).finally([&lock, obc] { + lock.unlock(); + }); } - }).finally([&lock, obc] { - lock.unlock(); }); } -- 2.39.5