]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/io/Utils.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / librbd / io / Utils.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "librbd/io/Utils.h"
5 #include "common/dout.h"
6 #include "include/buffer.h"
7 #include "include/rados/librados.hpp"
8 #include "include/neorados/RADOS.hpp"
9 #include "librbd/internal.h"
10 #include "librbd/Utils.h"
11 #include "librbd/io/AioCompletion.h"
12 #include "librbd/io/ImageDispatchSpec.h"
13 #include "librbd/io/ObjectRequest.h"
14 #include "librbd/io/ImageDispatcherInterface.h"
15 #include "osd/osd_types.h"
16 #include "osdc/Striper.h"
17
18 #define dout_subsys ceph_subsys_rbd
19 #undef dout_prefix
20 #define dout_prefix *_dout << "librbd::io::util: " << __func__ << ": "
21
22 namespace librbd {
23 namespace io {
24 namespace util {
25
26 void apply_op_flags(uint32_t op_flags, uint32_t flags, neorados::Op* op) {
27 if (op_flags & LIBRADOS_OP_FLAG_FADVISE_RANDOM)
28 op->set_fadvise_random();
29 if (op_flags & LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL)
30 op->set_fadvise_sequential();
31 if (op_flags & LIBRADOS_OP_FLAG_FADVISE_WILLNEED)
32 op->set_fadvise_willneed();
33 if (op_flags & LIBRADOS_OP_FLAG_FADVISE_DONTNEED)
34 op->set_fadvise_dontneed();
35 if (op_flags & LIBRADOS_OP_FLAG_FADVISE_NOCACHE)
36 op->set_fadvise_nocache();
37
38 if (flags & librados::OPERATION_BALANCE_READS)
39 op->balance_reads();
40 if (flags & librados::OPERATION_LOCALIZE_READS)
41 op->localize_reads();
42 }
43
44 bool assemble_write_same_extent(
45 const LightweightObjectExtent &object_extent, const ceph::bufferlist& data,
46 ceph::bufferlist *ws_data, bool force_write) {
47 size_t data_len = data.length();
48
49 if (!force_write) {
50 bool may_writesame = true;
51 for (auto& q : object_extent.buffer_extents) {
52 if (!(q.first % data_len == 0 && q.second % data_len == 0)) {
53 may_writesame = false;
54 break;
55 }
56 }
57
58 if (may_writesame) {
59 ws_data->append(data);
60 return true;
61 }
62 }
63
64 for (auto& q : object_extent.buffer_extents) {
65 bufferlist sub_bl;
66 uint64_t sub_off = q.first % data_len;
67 uint64_t sub_len = data_len - sub_off;
68 uint64_t extent_left = q.second;
69 while (extent_left >= sub_len) {
70 sub_bl.substr_of(data, sub_off, sub_len);
71 ws_data->claim_append(sub_bl);
72 extent_left -= sub_len;
73 if (sub_off) {
74 sub_off = 0;
75 sub_len = data_len;
76 }
77 }
78 if (extent_left) {
79 sub_bl.substr_of(data, sub_off, extent_left);
80 ws_data->claim_append(sub_bl);
81 }
82 }
83 return false;
84 }
85
86 template <typename I>
87 void read_parent(I *image_ctx, uint64_t object_no, ReadExtents* read_extents,
88 librados::snap_t snap_id, const ZTracer::Trace &trace,
89 Context* on_finish) {
90
91 auto cct = image_ctx->cct;
92
93 std::shared_lock image_locker{image_ctx->image_lock};
94
95 Extents parent_extents;
96 ImageArea area;
97 uint64_t raw_overlap = 0;
98 uint64_t object_overlap = 0;
99 image_ctx->get_parent_overlap(snap_id, &raw_overlap);
100 if (raw_overlap > 0) {
101 // calculate reverse mapping onto the parent image
102 Extents extents;
103 for (const auto& extent : *read_extents) {
104 extents.emplace_back(extent.offset, extent.length);
105 }
106 std::tie(parent_extents, area) = object_to_area_extents(image_ctx,
107 object_no, extents);
108 object_overlap = image_ctx->prune_parent_extents(parent_extents, area,
109 raw_overlap, false);
110 }
111 if (object_overlap == 0) {
112 image_locker.unlock();
113
114 on_finish->complete(-ENOENT);
115 return;
116 }
117
118 ldout(cct, 20) << dendl;
119
120 ceph::bufferlist* parent_read_bl;
121 if (read_extents->size() > 1) {
122 auto parent_comp = new ReadResult::C_ObjectReadMergedExtents(
123 cct, read_extents, on_finish);
124 parent_read_bl = &parent_comp->bl;
125 on_finish = parent_comp;
126 } else {
127 parent_read_bl = &read_extents->front().bl;
128 }
129
130 auto comp = AioCompletion::create_and_start(on_finish, image_ctx->parent,
131 AIO_TYPE_READ);
132 ldout(cct, 20) << "completion=" << comp
133 << " parent_extents=" << parent_extents
134 << " area=" << area << dendl;
135 auto req = io::ImageDispatchSpec::create_read(
136 *image_ctx->parent, io::IMAGE_DISPATCH_LAYER_INTERNAL_START, comp,
137 std::move(parent_extents), area, ReadResult{parent_read_bl},
138 image_ctx->parent->get_data_io_context(), 0, 0, trace);
139 req->send();
140 }
141
142 template <typename I>
143 int clip_request(I* image_ctx, Extents* image_extents, ImageArea area) {
144 std::shared_lock image_locker{image_ctx->image_lock};
145 for (auto &image_extent : *image_extents) {
146 auto clip_len = image_extent.second;
147 int r = clip_io(librbd::util::get_image_ctx(image_ctx),
148 image_extent.first, &clip_len, area);
149 if (r < 0) {
150 return r;
151 }
152
153 image_extent.second = clip_len;
154 }
155 return 0;
156 }
157
158 void unsparsify(CephContext* cct, ceph::bufferlist* bl,
159 const Extents& extent_map, uint64_t bl_off,
160 uint64_t out_bl_len) {
161 Striper::StripedReadResult destriper;
162 bufferlist out_bl;
163
164 destriper.add_partial_sparse_result(cct, std::move(*bl), extent_map, bl_off,
165 {{0, out_bl_len}});
166 destriper.assemble_result(cct, out_bl, true);
167 *bl = out_bl;
168 }
169
170 template <typename I>
171 bool trigger_copyup(I* image_ctx, uint64_t object_no, IOContext io_context,
172 Context* on_finish) {
173 bufferlist bl;
174 auto req = new ObjectWriteRequest<I>(
175 image_ctx, object_no, 0, std::move(bl), io_context, 0, 0,
176 std::nullopt, {}, on_finish);
177 if (!req->has_parent()) {
178 delete req;
179 return false;
180 }
181
182 req->send();
183 return true;
184 }
185
186 template <typename I>
187 void area_to_object_extents(I* image_ctx, uint64_t offset, uint64_t length,
188 ImageArea area, uint64_t buffer_offset,
189 striper::LightweightObjectExtents* object_extents) {
190 Extents extents = {{offset, length}};
191 image_ctx->io_image_dispatcher->remap_to_physical(extents, area);
192 for (auto [off, len] : extents) {
193 Striper::file_to_extents(image_ctx->cct, &image_ctx->layout, off, len, 0,
194 buffer_offset, object_extents);
195 }
196 }
197
198 template <typename I>
199 std::pair<Extents, ImageArea> object_to_area_extents(
200 I* image_ctx, uint64_t object_no, const Extents& object_extents) {
201 Extents extents;
202 for (auto [off, len] : object_extents) {
203 Striper::extent_to_file(image_ctx->cct, &image_ctx->layout, object_no, off,
204 len, extents);
205 }
206 auto area = image_ctx->io_image_dispatcher->remap_to_logical(extents);
207 return {std::move(extents), area};
208 }
209
210 template <typename I>
211 uint64_t area_to_raw_offset(const I& image_ctx, uint64_t offset,
212 ImageArea area) {
213 Extents extents = {{offset, 0}};
214 image_ctx.io_image_dispatcher->remap_to_physical(extents, area);
215 return extents[0].first;
216 }
217
218 template <typename I>
219 std::pair<uint64_t, ImageArea> raw_to_area_offset(const I& image_ctx,
220 uint64_t offset) {
221 Extents extents = {{offset, 0}};
222 auto area = image_ctx.io_image_dispatcher->remap_to_logical(extents);
223 return {extents[0].first, area};
224 }
225
226 } // namespace util
227 } // namespace io
228 } // namespace librbd
229
230 template void librbd::io::util::read_parent(
231 librbd::ImageCtx *image_ctx, uint64_t object_no, ReadExtents* extents,
232 librados::snap_t snap_id, const ZTracer::Trace &trace, Context* on_finish);
233 template int librbd::io::util::clip_request(
234 librbd::ImageCtx* image_ctx, Extents* image_extents, ImageArea area);
235 template bool librbd::io::util::trigger_copyup(
236 librbd::ImageCtx *image_ctx, uint64_t object_no, IOContext io_context,
237 Context* on_finish);
238 template void librbd::io::util::area_to_object_extents(
239 librbd::ImageCtx* image_ctx, uint64_t offset, uint64_t length,
240 ImageArea area, uint64_t buffer_offset,
241 striper::LightweightObjectExtents* object_extents);
242 template auto librbd::io::util::object_to_area_extents(
243 librbd::ImageCtx* image_ctx, uint64_t object_no, const Extents& extents)
244 -> std::pair<Extents, ImageArea>;
245 template uint64_t librbd::io::util::area_to_raw_offset(
246 const librbd::ImageCtx& image_ctx, uint64_t offset, ImageArea area);
247 template auto librbd::io::util::raw_to_area_offset(
248 const librbd::ImageCtx& image_ctx, uint64_t offset)
249 -> std::pair<uint64_t, ImageArea>;