From: Casey Bodley Date: Tue, 2 Jun 2026 20:17:59 +0000 (-0400) Subject: osdc: deliver neorados completions to associated executor X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=99460f8ae876dd72358a59d96dedcdb88bd9a0f1;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 (cherry picked from commit aabb5c70c56ed630a01c6f89d9981cdb6317ea34) --- diff --git a/src/osdc/Objecter.h b/src/osdc/Objecter.h index b4e5a84e2b9..bf9ba976114 100644 --- a/src/osdc/Objecter.h +++ b/src/osdc/Objecter.h @@ -2061,8 +2061,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)); }