]> 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>
Thu, 25 Jun 2026 15:00:49 +0000 (11:00 -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>
(cherry picked from commit aabb5c70c56ed630a01c6f89d9981cdb6317ea34)

src/osdc/Objecter.h

index b4e5a84e2b94ebb24a148c2f1ea5400df602c543..bf9ba976114733a6df61c7c591daccf50931d63d 100644 (file)
@@ -2061,8 +2061,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));
     }