From: Casey Bodley Date: Fri, 25 Oct 2024 14:16:49 +0000 (-0400) Subject: librados/asio: take ref arguments as cref from async_initiate() X-Git-Tag: v20.0.0~225^2~4 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=887ed45a33ea062726657da38d54d67b778dd8e1;p=ceph.git librados/asio: take ref arguments as cref from async_initiate() when called with 'use_awaitable' for c++20 coroutines, these functions fail to compile because async_initiate() tries to pass the IoCtx argument by rvalue reference, but our lambda expects lvalue reference: > src/librados/librados_asio.h:196:7: note: template argument deduction/substitution failed: > boost/asio/impl/use_awaitable.hpp:276:26: note: cannot convert ‘std::move((* & args#1))’ (type ‘std::remove_reference::type’ {aka ‘librados::v14_2_0::IoCtx’}) to type ‘librados::v14_2_0::IoCtx&’ > 276 | std::move(initiation)(std::move(handler), std::move(args)...); > | ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ async_initiate() for 'deferred' shows the same issue: > src/librados/librados_asio.h:196:7: note: template argument deduction/substitution failed: > boost/asio/async_result.hpp:322:9: note: cannot convert ‘args#1’ (type ‘const librados::v14_2_0::IoCtx’) to type ‘librados::v14_2_0::IoCtx&’ > 322 | static_cast(args)...); > | ^~~~~~~~~~~~~~~~~~~~~~~~~ in both cases, async_initiate() has to copy the arguments for deferred/lazy initiation, then move them into our lambda when invoked because our lambdas take mutable references, they won't accept these rvalue references. taking them as const references instead allows the caller to pass either lvalue- or rvalue references this requires internal const_casts to convert them back to mutable references. while casting away const risks undefined behavior, these casts are safe because: - in the deferred/lazy case, the arguments were decay-copied (const removed) into temporary storage - in the normal case, the initial arguments were passed as mutable refs Signed-off-by: Casey Bodley --- diff --git a/src/librados/librados_asio.h b/src/librados/librados_asio.h index 4484859b3c0..7d767603b63 100644 --- a/src/librados/librados_asio.h +++ b/src/librados/librados_asio.h @@ -159,12 +159,13 @@ auto async_read(IoExecutor ex, IoCtx& io, const std::string& oid, using Op = detail::AsyncOp; using Signature = typename Op::Signature; return boost::asio::async_initiate( - [] (auto handler, IoExecutor ex, IoCtx& io, const std::string& oid, - size_t len, uint64_t off) { + [] (auto handler, IoExecutor ex, const IoCtx& i, + const std::string& oid, size_t len, uint64_t off) { constexpr bool is_read = true; auto p = Op::create(ex, is_read, std::move(handler)); auto& op = p->user_data; + IoCtx& io = const_cast(i); int ret = io.aio_read(oid, op.aio_completion.get(), &op.result, len, off); if (ret < 0) { auto ec = boost::system::error_code{-ret, librados::detail::err_category()}; @@ -188,12 +189,13 @@ auto async_write(IoExecutor ex, IoCtx& io, const std::string& oid, using Op = detail::AsyncOp; using Signature = typename Op::Signature; return boost::asio::async_initiate( - [] (auto handler, IoExecutor ex, IoCtx& io, const std::string& oid, + [] (auto handler, IoExecutor ex, const IoCtx& i, const std::string& oid, const bufferlist &bl, size_t len, uint64_t off) { constexpr bool is_read = false; auto p = Op::create(ex, is_read, std::move(handler)); auto& op = p->user_data; + IoCtx& io = const_cast(i); int ret = io.aio_write(oid, op.aio_completion.get(), bl, len, off); if (ret < 0) { auto ec = boost::system::error_code{-ret, librados::detail::err_category()}; @@ -217,12 +219,13 @@ auto async_operate(IoExecutor ex, IoCtx& io, const std::string& oid, using Op = detail::AsyncOp; using Signature = typename Op::Signature; return boost::asio::async_initiate( - [] (auto handler, IoExecutor ex, IoCtx& io, const std::string& oid, + [] (auto handler, IoExecutor ex, const IoCtx& i, const std::string& oid, ObjectReadOperation *read_op, int flags) { constexpr bool is_read = true; auto p = Op::create(ex, is_read, std::move(handler)); auto& op = p->user_data; + IoCtx& io = const_cast(i); int ret = io.aio_operate(oid, op.aio_completion.get(), read_op, flags, &op.result); if (ret < 0) { @@ -247,13 +250,14 @@ auto async_operate(IoExecutor ex, IoCtx& io, const std::string& oid, using Op = detail::AsyncOp; using Signature = typename Op::Signature; return boost::asio::async_initiate( - [] (auto handler, IoExecutor ex, IoCtx& io, const std::string& oid, + [] (auto handler, IoExecutor ex, const IoCtx& i, const std::string& oid, ObjectWriteOperation *write_op, int flags, const jspan_context* trace_ctx) { constexpr bool is_read = false; auto p = Op::create(ex, is_read, std::move(handler)); auto& op = p->user_data; + IoCtx& io = const_cast(i); int ret = io.aio_operate(oid, op.aio_completion.get(), write_op, flags, trace_ctx); if (ret < 0) { auto ec = boost::system::error_code{-ret, librados::detail::err_category()}; @@ -276,12 +280,14 @@ auto async_notify(IoExecutor ex, IoCtx& io, const std::string& oid, using Op = detail::AsyncOp; using Signature = typename Op::Signature; return boost::asio::async_initiate( - [] (auto handler, IoExecutor ex, IoCtx& io, const std::string& oid, - bufferlist& bl, uint64_t timeout_ms) { + [] (auto handler, IoExecutor ex, const IoCtx& i, const std::string& oid, + const bufferlist& b, uint64_t timeout_ms) { constexpr bool is_read = false; auto p = Op::create(ex, is_read, std::move(handler)); auto& op = p->user_data; + IoCtx& io = const_cast(i); + bufferlist& bl = const_cast(b); int ret = io.aio_notify(oid, op.aio_completion.get(), bl, timeout_ms, &op.result); if (ret < 0) {