From: Casey Bodley Date: Tue, 2 Jun 2026 20:17:59 +0000 (-0400) Subject: osdc: deliver neorados completions to associated executor X-Git-Tag: v21.0.1~21^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=aabb5c70c56ed630a01c6f89d9981cdb6317ea34;p=ceph.git osdc: deliver neorados completions to associated executor while Objecter delivers librados completions directly by calling Context::complete(), neorados completions are passed in as boost::asio::any_completion_handler and delivered to an asio executor via boost::asio::defer() on completion asio handlers may have an "associated executor" so callers can customize where these completions are delivered. for example, multithreaded applications often use strand executors to synchronize completion handlers and prevent data races between concurrent operations however, applications like radosgw that depend on strands for thread-safety did not get it due to the fact that Objecter's Op::complete() delivered all neorados completions to the default io_context executor use boost::asio::get_associated_executor() to respect the handler's executor affinity, if any. but because the Op's handler is the type-erased any_completion_handler, its associated executor is also type-erased as any_completion_executor. that any_completion_executor doesn't support the blocking::never_t property required by defer/post, so defer() was changed to dispatch() which may call the handler directly if Objecter is already running on the requested executor. i assume this is safe, given that librados' Context-based completions already do this Fixes: https://tracker.ceph.com/issues/76725 Co-Authored-by: Oguzhan Ozmen Signed-off-by: Casey Bodley --- diff --git a/src/osdc/Objecter.h b/src/osdc/Objecter.h index a40ba465fcc..ab971798813 100644 --- a/src/osdc/Objecter.h +++ b/src/osdc/Objecter.h @@ -2072,8 +2072,9 @@ public: fu2::unique_function>) { std::move(arg)(ec); } else { - boost::asio::defer(e, - boost::asio::append(std::move(arg), ec)); + auto ex = boost::asio::get_associated_executor(arg, e); + boost::asio::dispatch(ex, + boost::asio::append(std::move(arg), ec)); } }, std::move(f)); }