From: Radoslaw Zarzynski Date: Mon, 29 Mar 2021 16:01:47 +0000 (+0000) Subject: crimson/osd: implement ObjectContext relocking. X-Git-Tag: v17.1.0~1984^2~22 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=6235e8d52f190683c798153ba0a353336d3d0b8d;p=ceph.git crimson/osd: implement ObjectContext relocking. This commit introduces a `ObjectContext`-taking variant of `PG::with_locked_obc()`. The upcoming internal counterpart for the `ClientRequest` is the intended audience. Signed-off-by: Radoslaw Zarzynski --- diff --git a/src/crimson/osd/object_context.h b/src/crimson/osd/object_context.h index 99285d735eb9..f1613564e8c1 100644 --- a/src/crimson/osd/object_context.h +++ b/src/crimson/osd/object_context.h @@ -59,6 +59,14 @@ public: return get_oid().is_head(); } + Ref get_head_obc() const { + return head; + } + + hobject_t get_head_oid() const { + return get_oid().get_head(); + } + const SnapSet &get_ro_ss() const { if (is_head()) { ceph_assert(ss); diff --git a/src/crimson/osd/pg.cc b/src/crimson/osd/pg.cc index 298f5223a7f5..1b52c2067bc9 100644 --- a/src/crimson/osd/pg.cc +++ b/src/crimson/osd/pg.cc @@ -857,13 +857,10 @@ std::optional PG::resolve_oid( template PG::load_obc_iertr::future<> -PG::with_head_obc(hobject_t oid, with_obc_func_t&& func) +PG::with_head_obc(ObjectContextRef obc, bool existed, with_obc_func_t&& func) { - logger().debug("{} {}", __func__, oid); - boost::intrusive_ptr pgref{this}; - assert(oid.is_head()); - auto [obc, existed] = - shard_services.obc_registry.get_cached_obc(std::move(oid)); + logger().debug("{} {}", __func__, 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] { @@ -879,12 +876,31 @@ PG::with_head_obc(hobject_t oid, with_obc_func_t&& func) return loaded.safe_then_interruptible([func = std::move(func)](auto obc) { return std::move(func)(std::move(obc)); }); - }).finally([this, pgref, obc=std::move(obc)] { + }).finally([this, pgref=boost::intrusive_ptr{this}, obc=std::move(obc)] { logger().debug("with_head_obc: released {}", obc->get_oid()); obc->remove_from(obc_set_accessing); }); } +template +PG::load_obc_iertr::future<> +PG::with_head_obc(hobject_t oid, with_obc_func_t&& func) +{ + auto [obc, existed] = + shard_services.obc_registry.get_cached_obc(std::move(oid)); + return with_head_obc(std::move(obc), existed, std::move(func)); +} + +template +PG::interruptible_future<> +PG::with_existing_head_obc(ObjectContextRef obc, with_obc_func_t&& func) +{ + constexpr bool existed = true; + return with_head_obc( + std::move(obc), existed, std::move(func) + ).handle_error_interruptible(load_obc_ertr::assert_all{"can't happen"}); +} + template PG::load_obc_iertr::future<> PG::with_clone_obc(hobject_t oid, with_obc_func_t&& func) @@ -928,6 +944,23 @@ PG::with_clone_obc(hobject_t oid, with_obc_func_t&& func) template PG::load_obc_iertr::future<> PG::with_head_obc(hobject_t, with_obc_func_t&&); +template +PG::interruptible_future<> +PG::with_existing_clone_obc(ObjectContextRef clone, with_obc_func_t&& func) +{ + assert(clone); + assert(clone->get_head_obc()); + assert(!clone->get_oid().is_head()); + return with_existing_head_obc(clone->get_head_obc(), + [clone=std::move(clone), func=std::move(func)] ([[maybe_unused]] auto head) { + assert(head == clone->get_head_obc()); + return clone->template with_lock( + [clone=std::move(clone), func=std::move(func)] { + std::move(func)(std::move(clone)); + }); + }); +} + PG::load_obc_iertr::future PG::load_head_obc(ObjectContextRef obc) { @@ -1007,6 +1040,26 @@ PG::with_locked_obc(Ref &m, const OpInfo &op_info, }; } +template +PG::interruptible_future<> +PG::with_locked_obc(ObjectContextRef obc, PG::with_obc_func_t &&f) +{ + // TODO: a question from rebase: do we really need such checks when + // the interruptible stuff is being used? + if (__builtin_expect(stopping, false)) { + throw crimson::common::system_shutdown_exception(); + } + if (obc->is_head()) { + return with_existing_head_obc(obc, std::move(f)); + } else { + return with_existing_clone_obc(obc, std::move(f)); + } +} + +// explicitly instantiate the used instantiations +template PG::interruptible_future<> +PG::with_locked_obc(ObjectContextRef, with_obc_func_t&&); + PG::interruptible_future<> PG::handle_rep_op(Ref req) { if (__builtin_expect(stopping, false)) { diff --git a/src/crimson/osd/pg.h b/src/crimson/osd/pg.h index f633f89636c7..9de11f7dda9e 100644 --- a/src/crimson/osd/pg.h +++ b/src/crimson/osd/pg.h @@ -517,6 +517,10 @@ public: template load_obc_iertr::future<> with_head_obc(hobject_t oid, with_obc_func_t&& func); + template + interruptible_future<> with_locked_obc( + ObjectContextRef obc, + with_obc_func_t&& f); load_obc_iertr::future<> with_locked_obc( Ref &m, const OpInfo &op_info, @@ -530,8 +534,21 @@ public: void dump_primary(Formatter*); private: + template + load_obc_iertr::future<> with_head_obc( + ObjectContextRef obc, + bool existed, + with_obc_func_t&& func); + template + interruptible_future<> with_existing_head_obc( + ObjectContextRef head, + with_obc_func_t&& func); + template load_obc_iertr::future<> with_clone_obc(hobject_t oid, with_obc_func_t&& func); + template + interruptible_future<> with_existing_clone_obc( + ObjectContextRef clone, with_obc_func_t&& func); load_obc_iertr::future get_locked_obc( Operation *op,