]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_aio.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / rgw / rgw_aio.cc
CommitLineData
9f95a23c
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab ft=cpp
3
4/*
5 * Ceph - scalable distributed file system
6 *
7 * Copyright (C) 2018 Red Hat, Inc.
8 *
9 * This is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License version 2.1, as published by the Free Software
12 * Foundation. See file COPYING.
13 *
14 */
15
16#include <type_traits>
17#include "include/rados/librados.hpp"
18#include "librados/librados_asio.h"
19
20#include "rgw_aio.h"
20effc67 21#include "rgw_d3n_cacherequest.h"
9f95a23c
TL
22
23namespace rgw {
24
25namespace {
26
27void cb(librados::completion_t, void* arg);
28
29struct state {
30 Aio* aio;
31 librados::AioCompletion* c;
32
33 state(Aio* aio, AioResult& r)
34 : aio(aio),
35 c(librados::Rados::aio_create_completion(&r, &cb)) {}
36};
37
38void cb(librados::completion_t, void* arg) {
39 static_assert(sizeof(AioResult::user_data) >= sizeof(state));
40 static_assert(std::is_trivially_destructible_v<state>);
41 auto& r = *(static_cast<AioResult*>(arg));
42 auto s = reinterpret_cast<state*>(&r.user_data);
43 r.result = s->c->get_return_value();
44 s->c->release();
45 s->aio->put(r);
46}
47
48template <typename Op>
49Aio::OpFunc aio_abstract(Op&& op) {
50 return [op = std::move(op)] (Aio* aio, AioResult& r) mutable {
51 constexpr bool read = std::is_same_v<std::decay_t<Op>, librados::ObjectReadOperation>;
52 auto s = new (&r.user_data) state(aio, r);
53 if constexpr (read) {
54 r.result = r.obj.aio_operate(s->c, &op, &r.data);
55 } else {
56 r.result = r.obj.aio_operate(s->c, &op);
57 }
58 if (r.result < 0) {
59 s->c->release();
60 aio->put(r);
61 }
62 };
63}
64
9f95a23c
TL
65struct Handler {
66 Aio* throttle = nullptr;
67 AioResult& r;
68 // write callback
69 void operator()(boost::system::error_code ec) const {
70 r.result = -ec.value();
71 throttle->put(r);
72 }
73 // read callback
74 void operator()(boost::system::error_code ec, bufferlist bl) const {
75 r.result = -ec.value();
76 r.data = std::move(bl);
77 throttle->put(r);
78 }
79};
80
81template <typename Op>
82Aio::OpFunc aio_abstract(Op&& op, boost::asio::io_context& context,
20effc67 83 yield_context yield) {
9f95a23c
TL
84 return [op = std::move(op), &context, yield] (Aio* aio, AioResult& r) mutable {
85 // arrange for the completion Handler to run on the yield_context's strand
86 // executor so it can safely call back into Aio without locking
87 using namespace boost::asio;
20effc67 88 async_completion<yield_context, void()> init(yield);
9f95a23c
TL
89 auto ex = get_associated_executor(init.completion_handler);
90
91 auto& ref = r.obj.get_ref();
92 librados::async_operate(context, ref.pool.ioctx(), ref.obj.oid, &op, 0,
93 bind_executor(ex, Handler{aio, r}));
94 };
95}
9f95a23c 96
20effc67
TL
97
98Aio::OpFunc d3n_cache_aio_abstract(const DoutPrefixProvider *dpp, optional_yield y, off_t read_ofs, off_t read_len, std::string& location) {
99 return [dpp, y, read_ofs, read_len, location] (Aio* aio, AioResult& r) mutable {
100 // d3n data cache requires yield context (rgw_beast_enable_async=true)
101 ceph_assert(y);
102 auto& ref = r.obj.get_ref();
103 auto c = std::make_unique<D3nL1CacheRequest>();
104 lsubdout(g_ceph_context, rgw_datacache, 20) << "D3nDataCache: d3n_cache_aio_abstract(): libaio Read From Cache, oid=" << ref.obj.oid << dendl;
105 c->file_aio_read_abstract(dpp, y.get_io_context(), y.get_yield_context(), location, read_ofs, read_len, aio, r);
106 };
107}
108
109
9f95a23c
TL
110template <typename Op>
111Aio::OpFunc aio_abstract(Op&& op, optional_yield y) {
112 static_assert(std::is_base_of_v<librados::ObjectOperation, std::decay_t<Op>>);
113 static_assert(!std::is_lvalue_reference_v<Op>);
114 static_assert(!std::is_const_v<Op>);
9f95a23c
TL
115 if (y) {
116 return aio_abstract(std::forward<Op>(op), y.get_io_context(),
117 y.get_yield_context());
118 }
9f95a23c
TL
119 return aio_abstract(std::forward<Op>(op));
120}
121
122} // anonymous namespace
123
124Aio::OpFunc Aio::librados_op(librados::ObjectReadOperation&& op,
125 optional_yield y) {
126 return aio_abstract(std::move(op), y);
127}
128Aio::OpFunc Aio::librados_op(librados::ObjectWriteOperation&& op,
129 optional_yield y) {
130 return aio_abstract(std::move(op), y);
131}
132
20effc67
TL
133Aio::OpFunc Aio::d3n_cache_op(const DoutPrefixProvider *dpp, optional_yield y,
134 off_t read_ofs, off_t read_len, std::string& location) {
135 return d3n_cache_aio_abstract(dpp, y, read_ofs, read_len, location);
136}
137
9f95a23c 138} // namespace rgw