#include "crimson/osd/object_context_loader.h" #include "osd/osd_types_fmt.h" SET_SUBSYS(osd); namespace crimson::osd { using crimson::common::local_conf; template ObjectContextLoader::load_obc_iertr::future<> ObjectContextLoader::with_head_obc(ObjectContextRef obc, bool existed, with_obc_func_t&& func) { LOG_PREFIX(ObjectContextLoader::with_head_obc); DEBUGDPP("object {}", dpp, obc->get_oid()); assert(obc->is_head()); obc->append_to(obc_set_accessing); return obc->with_lock( [existed=existed, obc=obc, func=std::move(func), this] { return get_or_load_obc(obc, existed) .safe_then_interruptible( [func = std::move(func)](auto obc) { return std::move(func)(std::move(obc)); }); }).finally([FNAME, this, obc=std::move(obc)] { DEBUGDPP("released object {}", dpp, obc->get_oid()); obc->remove_from(obc_set_accessing); }); } template ObjectContextLoader::load_obc_iertr::future<> ObjectContextLoader::with_clone_obc(hobject_t oid, with_obc_func_t&& func) { LOG_PREFIX(ObjectContextLoader::with_clone_obc); assert(!oid.is_head()); return with_obc( oid.get_head(), [FNAME, oid, func=std::move(func), this](auto head) mutable -> load_obc_iertr::future<> { if (!head->obs.exists) { ERRORDPP("head doesn't exist for object {}", dpp, head->obs.oi.soid); return load_obc_iertr::future<>{ crimson::ct_error::enoent::make() }; } return this->with_clone_obc_only(std::move(head), oid, std::move(func)); }); } template ObjectContextLoader::load_obc_iertr::future<> ObjectContextLoader::with_clone_obc_only(ObjectContextRef head, hobject_t oid, with_obc_func_t&& func) { LOG_PREFIX(ObjectContextLoader::with_clone_obc_only); auto coid = resolve_oid(head->get_head_ss(), oid); if (!coid) { ERRORDPP("clone {} not found", dpp, oid); return load_obc_iertr::future<>{ crimson::ct_error::enoent::make() }; } auto [clone, existed] = obc_registry.get_cached_obc(*coid); return clone->template with_lock( [existed=existed, clone=std::move(clone), func=std::move(func), head=std::move(head), this]() -> load_obc_iertr::future<> { auto loaded = get_or_load_obc(clone, existed); return loaded.safe_then_interruptible( [func = std::move(func)](auto clone) { return std::move(func)(std::move(clone)); }); }); } template ObjectContextLoader::load_obc_iertr::future<> ObjectContextLoader::with_clone_obc_direct( hobject_t oid, with_both_obc_func_t&& func) { LOG_PREFIX(ObjectContextLoader::with_clone_obc_direct); assert(!oid.is_head()); return with_obc( oid.get_head(), [FNAME, oid, func=std::move(func), this](auto head) mutable -> load_obc_iertr::future<> { if (!head->obs.exists) { ERRORDPP("head doesn't exist for object {}", dpp, head->obs.oi.soid); return load_obc_iertr::future<>{ crimson::ct_error::enoent::make() }; } #ifndef NDEBUG auto &ss = head->get_head_ss(); auto cit = std::find( std::begin(ss.clones), std::end(ss.clones), oid.snap); assert(cit != std::end(ss.clones)); #endif auto [clone, existed] = obc_registry.get_cached_obc(oid); return clone->template with_lock( [existed=existed, clone=std::move(clone), func=std::move(func), head=std::move(head), this]() -> load_obc_iertr::future<> { auto loaded = get_or_load_obc(clone, existed); return loaded.safe_then_interruptible( [func = std::move(func), head=std::move(head)](auto clone) { return std::move(func)(std::move(head), std::move(clone)); }); }); }); } template ObjectContextLoader::load_obc_iertr::future<> ObjectContextLoader::with_obc(hobject_t oid, with_obc_func_t&& func) { if (oid.is_head()) { auto [obc, existed] = obc_registry.get_cached_obc(std::move(oid)); return with_head_obc(std::move(obc), existed, std::move(func)); } else { return with_clone_obc(oid, std::move(func)); } } ObjectContextLoader::load_obc_iertr::future ObjectContextLoader::load_obc(ObjectContextRef obc) { LOG_PREFIX(ObjectContextLoader::load_obc); return backend.load_metadata(obc->get_oid()) .safe_then_interruptible( [FNAME, this, obc=std::move(obc)](auto md) -> load_obc_ertr::future { const hobject_t& oid = md->os.oi.soid; DEBUGDPP("loaded obs {} for {}", dpp, md->os.oi, oid); if (oid.is_head()) { if (!md->ssc) { ERRORDPP("oid {} missing snapsetcontext", dpp, oid); return crimson::ct_error::object_corrupted::make(); } obc->set_head_state(std::move(md->os), std::move(md->ssc)); } else { obc->set_clone_state(std::move(md->os)); } DEBUGDPP("returning obc {} for {}", dpp, obc->obs.oi, obc->obs.oi.soid); return load_obc_ertr::make_ready_future(obc); }); } template ObjectContextLoader::load_obc_iertr::future ObjectContextLoader::get_or_load_obc(ObjectContextRef obc, bool existed) { LOG_PREFIX(ObjectContextLoader::get_or_load_obc); auto loaded = load_obc_iertr::make_ready_future(obc); if (existed) { 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<> ObjectContextLoader::reload_obc(ObjectContext& obc) const { LOG_PREFIX(ObjectContextLoader::reload_obc); assert(obc.is_head()); return backend.load_metadata(obc.get_oid()) .safe_then_interruptible( [FNAME, this, &obc](auto md)-> load_obc_ertr::future<> { DEBUGDPP("reloaded obs {} for {}", dpp, md->os.oi, obc.get_oid()); if (!md->ssc) { ERRORDPP("oid {} missing snapsetcontext", dpp, obc.get_oid()); return crimson::ct_error::object_corrupted::make(); } obc.set_head_state(std::move(md->os), std::move(md->ssc)); return load_obc_ertr::now(); }); } void ObjectContextLoader::notify_on_change(bool is_primary) { LOG_PREFIX(ObjectContextLoader::notify_on_change); DEBUGDPP("is_primary: {}", dpp, is_primary); for (auto& obc : obc_set_accessing) { DEBUGDPP("interrupting obc: {}", dpp, obc.get_oid()); obc.interrupt(::crimson::common::actingset_changed(is_primary)); } } // explicitly instantiate the used instantiations template ObjectContextLoader::load_obc_iertr::future<> ObjectContextLoader::with_obc(hobject_t, with_obc_func_t&&); template ObjectContextLoader::load_obc_iertr::future<> ObjectContextLoader::with_obc(hobject_t, with_obc_func_t&&); template ObjectContextLoader::load_obc_iertr::future<> ObjectContextLoader::with_obc(hobject_t, with_obc_func_t&&); template ObjectContextLoader::load_obc_iertr::future<> ObjectContextLoader::with_obc(hobject_t, with_obc_func_t&&); template ObjectContextLoader::load_obc_iertr::future<> ObjectContextLoader::with_clone_obc_direct( hobject_t, with_both_obc_func_t&&); }