};
}
+ template <typename Lock, typename Func>
+ [[gnu::always_inline]]
+ static auto with_lock(Lock& lock, Func&& func) {
+ return seastar::with_lock(
+ lock,
+ [func=std::move(func),
+ interrupt_condition=interrupt_cond<InterruptCond>.interrupt_cond]() mutable {
+ return call_with_interruption(interrupt_condition, func);
+ });
+ }
+
template <typename Iterator,
InvokeReturnsInterruptibleFuture<typename Iterator::reference> AsyncAction>
[[gnu::always_inline]]
using watch_key_t = std::pair<uint64_t, entity_name_t>;
std::map<watch_key_t, seastar::shared_ptr<crimson::osd::Watch>> 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 {
dpp, obc->get_oid(),
obc->fully_loaded,
obc->invalidated_by_interval_change);
- auto loaded =
- load_obc_iertr::make_ready_future<ObjectContextRef>(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<State, IOInterruptCondition>(
- [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<ObjectContextRef>(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<State, IOInterruptCondition>(
+ [obc, this] {
+ return load_obc(obc);
+ });
+ }
+ return loaded;
+ });
}
ObjectContextLoader::load_obc_iertr::future<>
::crimson::osd::IOInterruptCondition,
load_obc_ertr>;
+ using interruptor = ::crimson::interruptible::interruptor<
+ ::crimson::osd::IOInterruptCondition>;
+
using with_obc_func_t =
std::function<load_obc_iertr::future<> (ObjectContextRef, ObjectContextRef)>;