]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
osdc: deliver neorados completions to associated executor
authorCasey Bodley <cbodley@redhat.com>
Tue, 2 Jun 2026 20:17:59 +0000 (16:17 -0400)
committerCasey Bodley <cbodley@redhat.com>
Wed, 3 Jun 2026 12:56:58 +0000 (08:56 -0400)
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 <oozmen@bloomberg.net>
Signed-off-by: Casey Bodley <cbodley@redhat.com>
src/osdc/Objecter.h

index a40ba465fcc7a037824c64122219223df94bab3c..ab971798813711a010ae835b5558f317919c7473 100644 (file)
@@ -2072,8 +2072,9 @@ public:
                              fu2::unique_function<OpSig>>) {
                     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));
     }