]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/io/ObjectRequest.h
Import ceph 15.2.8
[ceph.git] / ceph / src / librbd / io / ObjectRequest.h
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#ifndef CEPH_LIBRBD_IO_OBJECT_REQUEST_H
5#define CEPH_LIBRBD_IO_OBJECT_REQUEST_H
6
7#include "include/int_types.h"
7c673cae
FG
8#include "include/buffer.h"
9#include "include/rados/librados.hpp"
31f18b77
FG
10#include "common/snap_types.h"
11#include "common/zipkin_trace.h"
7c673cae 12#include "librbd/ObjectMap.h"
b32b8144 13#include "librbd/io/Types.h"
31f18b77 14#include <map>
7c673cae
FG
15
16class Context;
11fdf7f2 17class ObjectExtent;
7c673cae
FG
18
19namespace librbd {
20
21struct ImageCtx;
22
23namespace io {
24
25struct AioCompletion;
b32b8144 26template <typename> class CopyupRequest;
7c673cae 27
7c673cae
FG
28/**
29 * This class represents an I/O operation to a single RBD data object.
30 * Its subclasses encapsulate logic for dealing with special cases
31 * for I/O due to layering.
32 */
33template <typename ImageCtxT = ImageCtx>
11fdf7f2 34class ObjectRequest {
7c673cae 35public:
11fdf7f2 36 static ObjectRequest* create_write(
9f95a23c
TL
37 ImageCtxT *ictx, uint64_t object_no, uint64_t object_off,
38 ceph::bufferlist&& data, const ::SnapContext &snapc, int op_flags,
39 const ZTracer::Trace &parent_trace, Context *completion);
11fdf7f2 40 static ObjectRequest* create_discard(
9f95a23c
TL
41 ImageCtxT *ictx, uint64_t object_no, uint64_t object_off,
42 uint64_t object_len, const ::SnapContext &snapc, int discard_flags,
11fdf7f2 43 const ZTracer::Trace &parent_trace, Context *completion);
9f95a23c
TL
44 static ObjectRequest* create_write_same(
45 ImageCtxT *ictx, uint64_t object_no, uint64_t object_off,
46 uint64_t object_len, ceph::bufferlist&& data, const ::SnapContext &snapc,
47 int op_flags, const ZTracer::Trace &parent_trace, Context *completion);
11fdf7f2 48 static ObjectRequest* create_compare_and_write(
9f95a23c
TL
49 ImageCtxT *ictx, uint64_t object_no, uint64_t object_off,
50 ceph::bufferlist&& cmp_data, ceph::bufferlist&& write_data,
51 const ::SnapContext &snapc, uint64_t *mismatch_offset, int op_flags,
11fdf7f2 52 const ZTracer::Trace &parent_trace, Context *completion);
7c673cae 53
9f95a23c 54 ObjectRequest(ImageCtxT *ictx, uint64_t objectno, uint64_t off, uint64_t len,
b32b8144
FG
55 librados::snap_t snap_id, const char *trace_name,
56 const ZTracer::Trace &parent_trace, Context *completion);
11fdf7f2 57 virtual ~ObjectRequest() {
31f18b77
FG
58 m_trace.event("finish");
59 }
7c673cae 60
b32b8144
FG
61 static void add_write_hint(ImageCtxT& image_ctx,
62 librados::ObjectWriteOperation *wr);
7c673cae 63
11fdf7f2 64 virtual void send() = 0;
7c673cae
FG
65
66 bool has_parent() const {
67 return m_has_parent;
68 }
69
7c673cae 70 virtual const char *get_op_type() const = 0;
7c673cae
FG
71
72protected:
11fdf7f2 73 bool compute_parent_extents(Extents *parent_extents, bool read_request);
7c673cae 74
b32b8144 75 ImageCtxT *m_ictx;
7c673cae
FG
76 uint64_t m_object_no, m_object_off, m_object_len;
77 librados::snap_t m_snap_id;
78 Context *m_completion;
31f18b77 79 ZTracer::Trace m_trace;
7c673cae 80
b32b8144
FG
81 void async_finish(int r);
82 void finish(int r);
83
7c673cae
FG
84private:
85 bool m_has_parent = false;
86};
87
88template <typename ImageCtxT = ImageCtx>
89class ObjectReadRequest : public ObjectRequest<ImageCtxT> {
90public:
7c673cae
FG
91 typedef std::map<uint64_t, uint64_t> ExtentMap;
92
9f95a23c
TL
93 static ObjectReadRequest* create(
94 ImageCtxT *ictx, uint64_t objectno, uint64_t offset, uint64_t len,
95 librados::snap_t snap_id, int op_flags,
96 const ZTracer::Trace &parent_trace, ceph::bufferlist* read_data,
97 ExtentMap* extent_map, Context *completion) {
98 return new ObjectReadRequest(ictx, objectno, offset, len,
11fdf7f2
TL
99 snap_id, op_flags, parent_trace, read_data,
100 extent_map, completion);
7c673cae
FG
101 }
102
9f95a23c
TL
103 ObjectReadRequest(
104 ImageCtxT *ictx, uint64_t objectno, uint64_t offset, uint64_t len,
105 librados::snap_t snap_id, int op_flags,
106 const ZTracer::Trace &parent_trace, ceph::bufferlist* read_data,
107 ExtentMap* extent_map, Context *completion);
7c673cae 108
7c673cae 109 void send() override;
7c673cae 110
7c673cae
FG
111 const char *get_op_type() const override {
112 return "read";
113 }
114
7c673cae 115private:
7c673cae 116 /**
b32b8144 117 * @verbatim
7c673cae 118 *
11fdf7f2
TL
119 * <start>
120 * |
121 * |
122 * v
123 * READ_OBJECT
b32b8144
FG
124 * |
125 * v (skip if not needed)
126 * READ_PARENT
127 * |
128 * v (skip if not needed)
129 * COPYUP
130 * |
131 * v
132 * <finish>
7c673cae 133 *
b32b8144 134 * @endverbatim
7c673cae 135 */
7c673cae 136
b32b8144 137 int m_op_flags;
7c673cae 138
11fdf7f2
TL
139 ceph::bufferlist* m_read_data;
140 ExtentMap* m_extent_map;
7c673cae 141
b32b8144
FG
142 void read_object();
143 void handle_read_object(int r);
144
145 void read_parent();
146 void handle_read_parent(int r);
147
148 void copyup();
7c673cae
FG
149};
150
b32b8144
FG
151template <typename ImageCtxT = ImageCtx>
152class AbstractObjectWriteRequest : public ObjectRequest<ImageCtxT> {
7c673cae 153public:
9f95a23c
TL
154 AbstractObjectWriteRequest(
155 ImageCtxT *ictx, uint64_t object_no, uint64_t object_off, uint64_t len,
156 const ::SnapContext &snapc, const char *trace_name,
157 const ZTracer::Trace &parent_trace, Context *completion);
7c673cae 158
b32b8144
FG
159 virtual bool is_empty_write_op() const {
160 return false;
7c673cae
FG
161 }
162
b32b8144
FG
163 virtual uint8_t get_pre_write_object_map_state() const {
164 return OBJECT_EXISTS;
165 }
166
167 virtual void add_copyup_ops(librados::ObjectWriteOperation *wr) {
168 add_write_ops(wr);
169 }
170
171 void handle_copyup(int r);
172
7c673cae
FG
173 void send() override;
174
b32b8144
FG
175protected:
176 bool m_full_object = false;
11fdf7f2 177 bool m_copyup_enabled = true;
b32b8144
FG
178
179 virtual bool is_no_op_for_nonexistent_object() const {
180 return false;
181 }
182 virtual bool is_object_map_update_enabled() const {
183 return true;
184 }
185 virtual bool is_post_copyup_write_required() const {
186 return false;
187 }
188 virtual bool is_non_existent_post_write_object_map_state() const {
189 return false;
190 }
191
192 virtual void add_write_hint(librados::ObjectWriteOperation *wr);
193 virtual void add_write_ops(librados::ObjectWriteOperation *wr) = 0;
194
195 virtual int filter_write_result(int r) const {
196 return r;
197 }
198
199private:
7c673cae 200 /**
b32b8144 201 * @verbatim
7c673cae 202 *
b32b8144
FG
203 * <start>
204 * |
205 * v (no-op write request)
206 * DETECT_NO_OP . . . . . . . . . . . . . . . . . . .
207 * | .
208 * v (skip if not required/disabled) .
209 * PRE_UPDATE_OBJECT_MAP .
210 * | . .
211 * | . (child dne) .
212 * | . . . . . . . . . .
213 * | . .
214 * | (post-copyup write) . .
215 * | . . . . . . . . . . . . . .
216 * | . . . .
217 * v v . v .
218 * WRITE . . . . . . . . > COPYUP (if required) .
219 * | | .
220 * |/----------------------/ .
221 * | .
222 * v (skip if not required/disabled) .
223 * POST_UPDATE_OBJECT_MAP .
224 * | .
225 * v .
226 * <finish> < . . . . . . . . . . . . . . . . . . . .
7c673cae 227 *
b32b8144 228 * @endverbatim
7c673cae 229 */
7c673cae 230
7c673cae
FG
231 uint64_t m_snap_seq;
232 std::vector<librados::snap_t> m_snaps;
7c673cae 233
b32b8144
FG
234 Extents m_parent_extents;
235 bool m_object_may_exist = false;
b32b8144 236 bool m_copyup_in_progress = false;
11fdf7f2
TL
237 bool m_guarding_migration_write = false;
238
239 void compute_parent_info();
7c673cae 240
b32b8144
FG
241 void pre_write_object_map_update();
242 void handle_pre_write_object_map_update(int r);
243
244 void write_object();
245 void handle_write_object(int r);
246
247 void copyup();
248
249 void post_write_object_map_update();
250 void handle_post_write_object_map_update(int r);
7c673cae 251
7c673cae
FG
252};
253
b32b8144
FG
254template <typename ImageCtxT = ImageCtx>
255class ObjectWriteRequest : public AbstractObjectWriteRequest<ImageCtxT> {
7c673cae 256public:
9f95a23c
TL
257 ObjectWriteRequest(
258 ImageCtxT *ictx, uint64_t object_no, uint64_t object_off,
259 ceph::bufferlist&& data, const ::SnapContext &snapc, int op_flags,
260 const ZTracer::Trace &parent_trace, Context *completion)
261 : AbstractObjectWriteRequest<ImageCtxT>(ictx, object_no, object_off,
b32b8144
FG
262 data.length(), snapc, "write",
263 parent_trace, completion),
11fdf7f2 264 m_write_data(std::move(data)), m_op_flags(op_flags) {
7c673cae
FG
265 }
266
b32b8144 267 bool is_empty_write_op() const override {
7c673cae
FG
268 return (m_write_data.length() == 0);
269 }
270
271 const char *get_op_type() const override {
272 return "write";
273 }
274
7c673cae 275protected:
b32b8144 276 void add_write_ops(librados::ObjectWriteOperation *wr) override;
7c673cae
FG
277
278private:
279 ceph::bufferlist m_write_data;
280 int m_op_flags;
281};
282
b32b8144
FG
283template <typename ImageCtxT = ImageCtx>
284class ObjectDiscardRequest : public AbstractObjectWriteRequest<ImageCtxT> {
7c673cae 285public:
9f95a23c
TL
286 ObjectDiscardRequest(
287 ImageCtxT *ictx, uint64_t object_no, uint64_t object_off,
288 uint64_t object_len, const ::SnapContext &snapc, int discard_flags,
289 const ZTracer::Trace &parent_trace, Context *completion)
290 : AbstractObjectWriteRequest<ImageCtxT>(ictx, object_no, object_off,
b32b8144
FG
291 object_len, snapc, "discard",
292 parent_trace, completion),
11fdf7f2 293 m_discard_flags(discard_flags) {
b32b8144 294 if (this->m_full_object) {
11fdf7f2
TL
295 if ((m_discard_flags & OBJECT_DISCARD_FLAG_DISABLE_CLONE_REMOVE) != 0 &&
296 this->has_parent()) {
297 if (!this->m_copyup_enabled) {
298 // need to hide the parent object instead of child object
299 m_discard_action = DISCARD_ACTION_REMOVE_TRUNCATE;
300 } else {
301 m_discard_action = DISCARD_ACTION_TRUNCATE;
302 }
b32b8144
FG
303 this->m_object_len = 0;
304 } else {
305 m_discard_action = DISCARD_ACTION_REMOVE;
306 }
307 } else if (object_off + object_len == ictx->layout.object_size) {
308 m_discard_action = DISCARD_ACTION_TRUNCATE;
7c673cae 309 } else {
b32b8144 310 m_discard_action = DISCARD_ACTION_ZERO;
7c673cae 311 }
7c673cae
FG
312 }
313
b32b8144
FG
314 const char* get_op_type() const override {
315 switch (m_discard_action) {
316 case DISCARD_ACTION_REMOVE:
317 return "remove";
318 case DISCARD_ACTION_REMOVE_TRUNCATE:
94b18763 319 return "remove (create+truncate)";
b32b8144
FG
320 case DISCARD_ACTION_TRUNCATE:
321 return "truncate";
322 case DISCARD_ACTION_ZERO:
323 return "zero";
7c673cae 324 }
11fdf7f2 325 ceph_abort();
b32b8144 326 return nullptr;
7c673cae
FG
327 }
328
b32b8144
FG
329 uint8_t get_pre_write_object_map_state() const override {
330 if (m_discard_action == DISCARD_ACTION_REMOVE) {
331 return OBJECT_PENDING;
7c673cae 332 }
b32b8144 333 return OBJECT_EXISTS;
7c673cae
FG
334 }
335
336protected:
b32b8144
FG
337 bool is_no_op_for_nonexistent_object() const override {
338 return (!this->has_parent());
7c673cae 339 }
b32b8144 340 bool is_object_map_update_enabled() const override {
11fdf7f2
TL
341 return (
342 (m_discard_flags & OBJECT_DISCARD_FLAG_DISABLE_OBJECT_MAP_UPDATE) == 0);
7c673cae 343 }
b32b8144
FG
344 bool is_non_existent_post_write_object_map_state() const override {
345 return (m_discard_action == DISCARD_ACTION_REMOVE);
7c673cae
FG
346 }
347
b32b8144
FG
348 void add_write_hint(librados::ObjectWriteOperation *wr) override {
349 // no hint for discard
7c673cae 350 }
7c673cae 351
b32b8144
FG
352 void add_write_ops(librados::ObjectWriteOperation *wr) override {
353 switch (m_discard_action) {
354 case DISCARD_ACTION_REMOVE:
355 wr->remove();
356 break;
357 case DISCARD_ACTION_REMOVE_TRUNCATE:
94b18763
FG
358 wr->create(false);
359 // fall through
b32b8144
FG
360 case DISCARD_ACTION_TRUNCATE:
361 wr->truncate(this->m_object_off);
362 break;
363 case DISCARD_ACTION_ZERO:
364 wr->zero(this->m_object_off, this->m_object_len);
365 break;
366 default:
11fdf7f2 367 ceph_abort();
b32b8144
FG
368 break;
369 }
7c673cae
FG
370 }
371
b32b8144
FG
372private:
373 enum DiscardAction {
374 DISCARD_ACTION_REMOVE,
375 DISCARD_ACTION_REMOVE_TRUNCATE,
376 DISCARD_ACTION_TRUNCATE,
377 DISCARD_ACTION_ZERO
378 };
7c673cae 379
b32b8144 380 DiscardAction m_discard_action;
11fdf7f2 381 int m_discard_flags;
31f18b77 382
7c673cae
FG
383};
384
b32b8144
FG
385template <typename ImageCtxT = ImageCtx>
386class ObjectWriteSameRequest : public AbstractObjectWriteRequest<ImageCtxT> {
7c673cae 387public:
9f95a23c
TL
388 ObjectWriteSameRequest(
389 ImageCtxT *ictx, uint64_t object_no, uint64_t object_off,
390 uint64_t object_len, ceph::bufferlist&& data, const ::SnapContext &snapc,
391 int op_flags, const ZTracer::Trace &parent_trace, Context *completion)
392 : AbstractObjectWriteRequest<ImageCtxT>(ictx, object_no, object_off,
b32b8144
FG
393 object_len, snapc, "writesame",
394 parent_trace, completion),
11fdf7f2 395 m_write_data(std::move(data)), m_op_flags(op_flags) {
7c673cae
FG
396 }
397
398 const char *get_op_type() const override {
399 return "writesame";
400 }
401
7c673cae 402protected:
b32b8144 403 void add_write_ops(librados::ObjectWriteOperation *wr) override;
7c673cae
FG
404
405private:
406 ceph::bufferlist m_write_data;
407 int m_op_flags;
408};
409
b32b8144
FG
410template <typename ImageCtxT = ImageCtx>
411class ObjectCompareAndWriteRequest : public AbstractObjectWriteRequest<ImageCtxT> {
c07f9fc5 412public:
9f95a23c
TL
413 ObjectCompareAndWriteRequest(
414 ImageCtxT *ictx, uint64_t object_no, uint64_t object_off,
415 ceph::bufferlist&& cmp_bl, ceph::bufferlist&& write_bl,
416 const ::SnapContext &snapc, uint64_t *mismatch_offset, int op_flags,
417 const ZTracer::Trace &parent_trace, Context *completion)
418 : AbstractObjectWriteRequest<ImageCtxT>(ictx, object_no, object_off,
b32b8144
FG
419 cmp_bl.length(), snapc,
420 "compare_and_write", parent_trace,
421 completion),
11fdf7f2 422 m_cmp_bl(std::move(cmp_bl)), m_write_bl(std::move(write_bl)),
c07f9fc5
FG
423 m_mismatch_offset(mismatch_offset), m_op_flags(op_flags) {
424 }
425
426 const char *get_op_type() const override {
427 return "compare_and_write";
428 }
429
b32b8144
FG
430 void add_copyup_ops(librados::ObjectWriteOperation *wr) override {
431 // no-op on copyup
c07f9fc5
FG
432 }
433
c07f9fc5 434protected:
b32b8144
FG
435 virtual bool is_post_copyup_write_required() const {
436 return true;
437 }
438
439 void add_write_ops(librados::ObjectWriteOperation *wr) override;
c07f9fc5 440
b32b8144 441 int filter_write_result(int r) const override;
c07f9fc5
FG
442
443private:
444 ceph::bufferlist m_cmp_bl;
445 ceph::bufferlist m_write_bl;
446 uint64_t *m_mismatch_offset;
447 int m_op_flags;
448};
449
7c673cae
FG
450} // namespace io
451} // namespace librbd
452
453extern template class librbd::io::ObjectRequest<librbd::ImageCtx>;
454extern template class librbd::io::ObjectReadRequest<librbd::ImageCtx>;
b32b8144
FG
455extern template class librbd::io::AbstractObjectWriteRequest<librbd::ImageCtx>;
456extern template class librbd::io::ObjectWriteRequest<librbd::ImageCtx>;
457extern template class librbd::io::ObjectDiscardRequest<librbd::ImageCtx>;
458extern template class librbd::io::ObjectWriteSameRequest<librbd::ImageCtx>;
459extern template class librbd::io::ObjectCompareAndWriteRequest<librbd::ImageCtx>;
7c673cae
FG
460
461#endif // CEPH_LIBRBD_IO_OBJECT_REQUEST_H