From 19cce9a57310677693d1b0cbc5255b22c520f442 Mon Sep 17 00:00:00 2001 From: Matan Breizman Date: Tue, 28 May 2024 13:23:10 +0000 Subject: [PATCH] crimson/osd/object_context: await in-progress loading (per-obc) ``` // obc loading is a concurrent phase. In case this obc is being loaded, // make other useres of this obc to await for the loading to complete. ``` Since we now await for loading to finish (in-case in progress), we can also assert is_loaded(). Fixes: https://tracker.ceph.com/issues/65451 Co-authored-by: Xuehan Xu Signed-off-by: Matan Breizman (cherry picked from commit e456bd7cdd1ad1cd68026cebedd5b1d9d01001f7) --- src/crimson/common/interruptible_future.h | 11 ++++++++ src/crimson/osd/object_context.h | 4 +++ src/crimson/osd/object_context_loader.cc | 31 +++++++++++++---------- src/crimson/osd/object_context_loader.h | 3 +++ 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/crimson/common/interruptible_future.h b/src/crimson/common/interruptible_future.h index 27467f2396265..0e2a238edd08f 100644 --- a/src/crimson/common/interruptible_future.h +++ b/src/crimson/common/interruptible_future.h @@ -1218,6 +1218,17 @@ public: }; } + template + [[gnu::always_inline]] + static auto with_lock(Lock& lock, Func&& func) { + return seastar::with_lock( + lock, + [func=std::move(func), + interrupt_condition=interrupt_cond.interrupt_cond]() mutable { + return call_with_interruption(interrupt_condition, func); + }); + } + template AsyncAction> [[gnu::always_inline]] diff --git a/src/crimson/osd/object_context.h b/src/crimson/osd/object_context.h index d651dc912fd52..9aa5d60a80039 100644 --- a/src/crimson/osd/object_context.h +++ b/src/crimson/osd/object_context.h @@ -70,6 +70,10 @@ public: using watch_key_t = std::pair; std::map> watchers; + // obc loading is a concurrent phase. In case this obc is being loaded, + // make other users of this obc to await for the loading to complete. + seastar::shared_mutex loading_mutex; + ObjectContext(hobject_t hoid) : obs(std::move(hoid)) {} const hobject_t &get_oid() const { diff --git a/src/crimson/osd/object_context_loader.cc b/src/crimson/osd/object_context_loader.cc index d8035b440ea1f..9af927806d568 100644 --- a/src/crimson/osd/object_context_loader.cc +++ b/src/crimson/osd/object_context_loader.cc @@ -149,20 +149,23 @@ using crimson::common::local_conf; dpp, obc->get_oid(), obc->fully_loaded, obc->invalidated_by_interval_change); - auto loaded = - load_obc_iertr::make_ready_future(obc); - if (existed && obc->is_loaded()) { - ceph_assert(obc->is_valid()); - DEBUGDPP("cache hit on {}", dpp, obc->get_oid()); - } else { - DEBUGDPP("cache miss on {}", dpp, obc->get_oid()); - loaded = - obc->template with_promoted_lock( - [obc, this] { - return load_obc(obc); - }); - } - return loaded; + return interruptor::with_lock(obc->loading_mutex, + [this, obc, existed, FNAME] { + auto loaded = + load_obc_iertr::make_ready_future(obc); + if (existed) { + ceph_assert(obc->is_valid() && obc->is_loaded()); + DEBUGDPP("cache hit on {}", dpp, obc->get_oid()); + } else { + DEBUGDPP("cache miss on {}", dpp, obc->get_oid()); + loaded = + obc->template with_promoted_lock( + [obc, this] { + return load_obc(obc); + }); + } + return loaded; + }); } ObjectContextLoader::load_obc_iertr::future<> diff --git a/src/crimson/osd/object_context_loader.h b/src/crimson/osd/object_context_loader.h index 77805e11bc167..b51e10caf77e8 100644 --- a/src/crimson/osd/object_context_loader.h +++ b/src/crimson/osd/object_context_loader.h @@ -29,6 +29,9 @@ public: ::crimson::osd::IOInterruptCondition, load_obc_ertr>; + using interruptor = ::crimson::interruptible::interruptor< + ::crimson::osd::IOInterruptCondition>; + using with_obc_func_t = std::function (ObjectContextRef, ObjectContextRef)>; -- 2.39.5