]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/io/Utils.cc
bump version to 18.2.2-pve1
[ceph.git] / ceph / src / librbd / io / Utils.cc
CommitLineData
11fdf7f2
TL
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"
f91f0fd5 5#include "common/dout.h"
11fdf7f2 6#include "include/buffer.h"
f91f0fd5 7#include "include/rados/librados.hpp"
f67539c2
TL
8#include "include/neorados/RADOS.hpp"
9#include "librbd/internal.h"
10#include "librbd/Utils.h"
f91f0fd5 11#include "librbd/io/AioCompletion.h"
f67539c2
TL
12#include "librbd/io/ImageDispatchSpec.h"
13#include "librbd/io/ObjectRequest.h"
14#include "librbd/io/ImageDispatcherInterface.h"
11fdf7f2 15#include "osd/osd_types.h"
f91f0fd5
TL
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__ << ": "
11fdf7f2
TL
21
22namespace librbd {
23namespace io {
24namespace util {
25
f67539c2
TL
26void 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
11fdf7f2 44bool assemble_write_same_extent(
9f95a23c 45 const LightweightObjectExtent &object_extent, const ceph::bufferlist& data,
11fdf7f2
TL
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
f91f0fd5 86template <typename I>
1e59de90 87void read_parent(I *image_ctx, uint64_t object_no, ReadExtents* read_extents,
f67539c2 88 librados::snap_t snap_id, const ZTracer::Trace &trace,
f91f0fd5
TL
89 Context* on_finish) {
90
91 auto cct = image_ctx->cct;
92
93 std::shared_lock image_locker{image_ctx->image_lock};
94
f91f0fd5 95 Extents parent_extents;
1e59de90
TL
96 ImageArea area;
97 uint64_t raw_overlap = 0;
f91f0fd5 98 uint64_t object_overlap = 0;
1e59de90
TL
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);
f91f0fd5 110 }
f91f0fd5
TL
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
f67539c2 120 ceph::bufferlist* parent_read_bl;
1e59de90 121 if (read_extents->size() > 1) {
f67539c2 122 auto parent_comp = new ReadResult::C_ObjectReadMergedExtents(
1e59de90 123 cct, read_extents, on_finish);
f67539c2
TL
124 parent_read_bl = &parent_comp->bl;
125 on_finish = parent_comp;
126 } else {
1e59de90 127 parent_read_bl = &read_extents->front().bl;
f67539c2
TL
128 }
129
f91f0fd5
TL
130 auto comp = AioCompletion::create_and_start(on_finish, image_ctx->parent,
131 AIO_TYPE_READ);
1e59de90
TL
132 ldout(cct, 20) << "completion=" << comp
133 << " parent_extents=" << parent_extents
134 << " area=" << area << dendl;
f67539c2
TL
135 auto req = io::ImageDispatchSpec::create_read(
136 *image_ctx->parent, io::IMAGE_DISPATCH_LAYER_INTERNAL_START, comp,
1e59de90 137 std::move(parent_extents), area, ReadResult{parent_read_bl},
f67539c2
TL
138 image_ctx->parent->get_data_io_context(), 0, 0, trace);
139 req->send();
140}
f91f0fd5 141
f67539c2 142template <typename I>
1e59de90 143int clip_request(I* image_ctx, Extents* image_extents, ImageArea area) {
f67539c2
TL
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),
1e59de90 148 image_extent.first, &clip_len, area);
f67539c2
TL
149 if (r < 0) {
150 return r;
151 }
152
153 image_extent.second = clip_len;
154 }
155 return 0;
156}
157
158void 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
170template <typename I>
171bool 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
186template <typename I>
1e59de90
TL
187void 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) {
f67539c2 190 Extents extents = {{offset, length}};
1e59de90 191 image_ctx->io_image_dispatcher->remap_to_physical(extents, area);
f67539c2
TL
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
198template <typename I>
1e59de90
TL
199std::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};
f67539c2
TL
208}
209
210template <typename I>
1e59de90
TL
211uint64_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);
f67539c2 215 return extents[0].first;
f91f0fd5
TL
216}
217
1e59de90
TL
218template <typename I>
219std::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
11fdf7f2
TL
226} // namespace util
227} // namespace io
228} // namespace librbd
229
f91f0fd5 230template void librbd::io::util::read_parent(
f67539c2
TL
231 librbd::ImageCtx *image_ctx, uint64_t object_no, ReadExtents* extents,
232 librados::snap_t snap_id, const ZTracer::Trace &trace, Context* on_finish);
233template int librbd::io::util::clip_request(
1e59de90 234 librbd::ImageCtx* image_ctx, Extents* image_extents, ImageArea area);
f67539c2
TL
235template bool librbd::io::util::trigger_copyup(
236 librbd::ImageCtx *image_ctx, uint64_t object_no, IOContext io_context,
237 Context* on_finish);
1e59de90
TL
238template 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);
242template 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>;
245template uint64_t librbd::io::util::area_to_raw_offset(
246 const librbd::ImageCtx& image_ctx, uint64_t offset, ImageArea area);
247template auto librbd::io::util::raw_to_area_offset(
248 const librbd::ImageCtx& image_ctx, uint64_t offset)
249 -> std::pair<uint64_t, ImageArea>;