]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/io/ObjectRequest.h
update sources to 12.2.2
[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"
31f18b77 13#include <map>
7c673cae
FG
14
15class Context;
16
17namespace librbd {
18
19struct ImageCtx;
20
21namespace io {
22
23struct AioCompletion;
24class CopyupRequest;
25class ObjectRemoveRequest;
26class ObjectTruncateRequest;
27class ObjectWriteRequest;
28class ObjectZeroRequest;
29
30struct ObjectRequestHandle {
31 virtual ~ObjectRequestHandle() {
32 }
33
34 virtual void complete(int r) = 0;
35 virtual void send() = 0;
36};
37
38/**
39 * This class represents an I/O operation to a single RBD data object.
40 * Its subclasses encapsulate logic for dealing with special cases
41 * for I/O due to layering.
42 */
43template <typename ImageCtxT = ImageCtx>
44class ObjectRequest : public ObjectRequestHandle {
45public:
46 typedef std::vector<std::pair<uint64_t, uint64_t> > Extents;
47
48 static ObjectRequest* create_remove(ImageCtxT *ictx,
49 const std::string &oid,
50 uint64_t object_no,
51 const ::SnapContext &snapc,
31f18b77 52 const ZTracer::Trace &parent_trace,
7c673cae
FG
53 Context *completion);
54 static ObjectRequest* create_truncate(ImageCtxT *ictx,
55 const std::string &oid,
56 uint64_t object_no,
57 uint64_t object_off,
58 const ::SnapContext &snapc,
31f18b77 59 const ZTracer::Trace &parent_trace,
7c673cae 60 Context *completion);
3efd9988
FG
61 static ObjectRequest* create_trim(ImageCtxT *ictx, const std::string &oid,
62 uint64_t object_no,
63 const ::SnapContext &snapc,
64 bool post_object_map_update,
65 Context *completion);
7c673cae
FG
66 static ObjectRequest* create_write(ImageCtxT *ictx, const std::string &oid,
67 uint64_t object_no,
68 uint64_t object_off,
69 const ceph::bufferlist &data,
31f18b77
FG
70 const ::SnapContext &snapc, int op_flags,
71 const ZTracer::Trace &parent_trace,
72 Context *completion);
7c673cae
FG
73 static ObjectRequest* create_zero(ImageCtxT *ictx, const std::string &oid,
74 uint64_t object_no, uint64_t object_off,
75 uint64_t object_len,
76 const ::SnapContext &snapc,
31f18b77 77 const ZTracer::Trace &parent_trace,
7c673cae
FG
78 Context *completion);
79 static ObjectRequest* create_writesame(ImageCtxT *ictx,
80 const std::string &oid,
81 uint64_t object_no,
82 uint64_t object_off,
83 uint64_t object_len,
84 const ceph::bufferlist &data,
85 const ::SnapContext &snapc,
31f18b77
FG
86 int op_flags,
87 const ZTracer::Trace &parent_trace,
88 Context *completion);
c07f9fc5
FG
89 static ObjectRequest* create_compare_and_write(ImageCtxT *ictx,
90 const std::string &oid,
91 uint64_t object_no,
92 uint64_t object_off,
93 const ceph::bufferlist &cmp_data,
94 const ceph::bufferlist &write_data,
95 const ::SnapContext &snapc,
96 uint64_t *mismatch_offset, int op_flags,
97 const ZTracer::Trace &parent_trace,
98 Context *completion);
7c673cae
FG
99
100 ObjectRequest(ImageCtx *ictx, const std::string &oid,
101 uint64_t objectno, uint64_t off, uint64_t len,
31f18b77
FG
102 librados::snap_t snap_id, bool hide_enoent,
103 const char *trace_name, const ZTracer::Trace &parent_trace,
104 Context *completion);
105 ~ObjectRequest() override {
106 m_trace.event("finish");
107 }
7c673cae 108
31f18b77
FG
109 virtual void add_copyup_ops(librados::ObjectWriteOperation *wr,
110 bool set_hints) {
111 };
7c673cae 112
c07f9fc5 113 virtual void complete(int r);
7c673cae
FG
114
115 virtual bool should_complete(int r) = 0;
116 void send() override = 0;
117
118 bool has_parent() const {
119 return m_has_parent;
120 }
121
122 virtual bool is_op_payload_empty() const {
123 return false;
124 }
125
126 virtual const char *get_op_type() const = 0;
127 virtual bool pre_object_map_update(uint8_t *new_state) = 0;
128
129protected:
130 bool compute_parent_extents();
131
132 ImageCtx *m_ictx;
133 std::string m_oid;
134 uint64_t m_object_no, m_object_off, m_object_len;
135 librados::snap_t m_snap_id;
136 Context *m_completion;
137 Extents m_parent_extents;
138 bool m_hide_enoent;
31f18b77 139 ZTracer::Trace m_trace;
7c673cae
FG
140
141private:
142 bool m_has_parent = false;
143};
144
145template <typename ImageCtxT = ImageCtx>
146class ObjectReadRequest : public ObjectRequest<ImageCtxT> {
147public:
148 typedef std::vector<std::pair<uint64_t, uint64_t> > Extents;
149 typedef std::map<uint64_t, uint64_t> ExtentMap;
150
151 static ObjectReadRequest* create(ImageCtxT *ictx, const std::string &oid,
152 uint64_t objectno, uint64_t offset,
153 uint64_t len, Extents &buffer_extents,
154 librados::snap_t snap_id, bool sparse,
31f18b77
FG
155 int op_flags,
156 const ZTracer::Trace &parent_trace,
157 Context *completion) {
7c673cae 158 return new ObjectReadRequest(ictx, oid, objectno, offset, len,
31f18b77
FG
159 buffer_extents, snap_id, sparse, op_flags,
160 parent_trace, completion);
7c673cae
FG
161 }
162
163 ObjectReadRequest(ImageCtxT *ictx, const std::string &oid,
164 uint64_t objectno, uint64_t offset, uint64_t len,
165 Extents& buffer_extents, librados::snap_t snap_id,
31f18b77
FG
166 bool sparse, int op_flags,
167 const ZTracer::Trace &parent_trace, Context *completion);
7c673cae
FG
168
169 bool should_complete(int r) override;
170 void send() override;
171 void guard_read();
172
173 inline uint64_t get_offset() const {
174 return this->m_object_off;
175 }
176 inline uint64_t get_length() const {
177 return this->m_object_len;
178 }
179 ceph::bufferlist &data() {
180 return m_read_data;
181 }
182 const Extents &get_buffer_extents() const {
183 return m_buffer_extents;
184 }
185 ExtentMap &get_extent_map() {
186 return m_ext_map;
187 }
188
189 const char *get_op_type() const override {
190 return "read";
191 }
192
193 bool pre_object_map_update(uint8_t *new_state) override {
194 return false;
195 }
196
197private:
198 Extents m_buffer_extents;
199 bool m_tried_parent;
200 bool m_sparse;
201 int m_op_flags;
202 ceph::bufferlist m_read_data;
203 ExtentMap m_ext_map;
204
205 /**
206 * Reads go through the following state machine to deal with
207 * layering:
208 *
209 * need copyup
210 * LIBRBD_AIO_READ_GUARD ---------------> LIBRBD_AIO_READ_COPYUP
211 * | |
212 * v |
213 * done <------------------------------------/
214 * ^
215 * |
216 * LIBRBD_AIO_READ_FLAT
217 *
218 * Reads start in LIBRBD_AIO_READ_GUARD or _FLAT, depending on
219 * whether there is a parent or not.
220 */
221 enum read_state_d {
222 LIBRBD_AIO_READ_GUARD,
223 LIBRBD_AIO_READ_COPYUP,
224 LIBRBD_AIO_READ_FLAT
225 };
226
227 read_state_d m_state;
228
229 void send_copyup();
230
231 void read_from_parent(Extents&& image_extents);
232};
233
234class AbstractObjectWriteRequest : public ObjectRequest<> {
235public:
236 AbstractObjectWriteRequest(ImageCtx *ictx, const std::string &oid,
237 uint64_t object_no, uint64_t object_off,
238 uint64_t len, const ::SnapContext &snapc,
31f18b77
FG
239 bool hide_enoent, const char *trace_name,
240 const ZTracer::Trace &parent_trace,
241 Context *completion);
7c673cae 242
31f18b77
FG
243 void add_copyup_ops(librados::ObjectWriteOperation *wr,
244 bool set_hints) override
7c673cae 245 {
31f18b77 246 add_write_ops(wr, set_hints);
7c673cae
FG
247 }
248
249 bool should_complete(int r) override;
250 void send() override;
251
252 /**
253 * Writes go through the following state machine to deal with
254 * layering and the object map:
255 *
256 * <start>
257 * |
258 * |\
259 * | \ -or-
260 * | ---------------------------------> LIBRBD_AIO_WRITE_PRE
261 * | . |
262 * | . |
263 * | . v
264 * | . . . . > LIBRBD_AIO_WRITE_FLAT. . .
265 * | | .
266 * | | .
267 * | | .
268 * v need copyup (copyup performs pre) | .
269 * LIBRBD_AIO_WRITE_GUARD -----------> LIBRBD_AIO_WRITE_COPYUP | .
270 * . | | . | .
271 * . | | . | .
272 * . | /-----/ . | .
273 * . | | . | .
274 * . \-------------------\ | /-------------------/ .
275 * . | | | . .
276 * . v v v . .
277 * . LIBRBD_AIO_WRITE_POST . .
278 * . | . .
279 * . | . . . . . . . . .
280 * . | . .
281 * . v v .
282 * . . . . . . . . . . . . . . > <finish> < . . . . . . . . . . . . . .
283 *
284 * The _PRE/_POST states are skipped if the object map is disabled.
285 * The write starts in _WRITE_GUARD or _FLAT depending on whether or not
286 * there is a parent overlap.
287 */
288protected:
289 enum write_state_d {
290 LIBRBD_AIO_WRITE_GUARD,
291 LIBRBD_AIO_WRITE_COPYUP,
292 LIBRBD_AIO_WRITE_FLAT,
293 LIBRBD_AIO_WRITE_PRE,
294 LIBRBD_AIO_WRITE_POST,
295 LIBRBD_AIO_WRITE_ERROR
296 };
297
298 write_state_d m_state;
299 librados::ObjectWriteOperation m_write;
300 uint64_t m_snap_seq;
301 std::vector<librados::snap_t> m_snaps;
302 bool m_object_exist;
303 bool m_guard = true;
304
31f18b77
FG
305 virtual void add_write_ops(librados::ObjectWriteOperation *wr,
306 bool set_hints) = 0;
7c673cae
FG
307 virtual void guard_write();
308 virtual bool post_object_map_update() {
309 return false;
310 }
311 virtual void send_write();
312 virtual void send_write_op();
313 virtual void handle_write_guard();
314
315 void send_pre_object_map_update();
316
317private:
318 bool send_post_object_map_update();
319 void send_copyup();
320};
321
322class ObjectWriteRequest : public AbstractObjectWriteRequest {
323public:
324 ObjectWriteRequest(ImageCtx *ictx, const std::string &oid, uint64_t object_no,
325 uint64_t object_off, const ceph::bufferlist &data,
31f18b77
FG
326 const ::SnapContext &snapc, int op_flags,
327 const ZTracer::Trace &parent_trace, Context *completion)
7c673cae 328 : AbstractObjectWriteRequest(ictx, oid, object_no, object_off,
31f18b77
FG
329 data.length(), snapc, false, "write",
330 parent_trace, completion),
7c673cae
FG
331 m_write_data(data), m_op_flags(op_flags) {
332 }
333
334 bool is_op_payload_empty() const override {
335 return (m_write_data.length() == 0);
336 }
337
338 const char *get_op_type() const override {
339 return "write";
340 }
341
342 bool pre_object_map_update(uint8_t *new_state) override {
343 *new_state = OBJECT_EXISTS;
344 return true;
345 }
346
347protected:
31f18b77
FG
348 void add_write_ops(librados::ObjectWriteOperation *wr,
349 bool set_hints) override;
7c673cae
FG
350
351 void send_write() override;
352
353private:
354 ceph::bufferlist m_write_data;
355 int m_op_flags;
356};
357
358class ObjectRemoveRequest : public AbstractObjectWriteRequest {
359public:
360 ObjectRemoveRequest(ImageCtx *ictx, const std::string &oid,
361 uint64_t object_no, const ::SnapContext &snapc,
31f18b77
FG
362 const ZTracer::Trace &parent_trace, Context *completion)
363 : AbstractObjectWriteRequest(ictx, oid, object_no, 0, 0, snapc, true,
364 "remote", parent_trace, completion),
7c673cae
FG
365 m_object_state(OBJECT_NONEXISTENT) {
366 }
367
368 const char* get_op_type() const override {
369 if (has_parent()) {
370 return "remove (trunc)";
371 }
372 return "remove";
373 }
374
375 bool pre_object_map_update(uint8_t *new_state) override {
376 if (has_parent()) {
377 m_object_state = OBJECT_EXISTS;
378 } else {
379 m_object_state = OBJECT_PENDING;
380 }
381 *new_state = m_object_state;
382 return true;
383 }
384
385 bool post_object_map_update() override {
386 if (m_object_state == OBJECT_EXISTS) {
387 return false;
388 }
389 return true;
390 }
391
392 void guard_write() override;
393 void send_write() override;
394
395protected:
31f18b77
FG
396 void add_write_ops(librados::ObjectWriteOperation *wr,
397 bool set_hints) override {
7c673cae
FG
398 if (has_parent()) {
399 wr->truncate(0);
400 } else {
401 wr->remove();
402 }
403 }
404
405private:
406 uint8_t m_object_state;
407};
408
409class ObjectTrimRequest : public AbstractObjectWriteRequest {
410public:
411 // we'd need to only conditionally specify if a post object map
412 // update is needed. pre update is decided as usual (by checking
413 // the state of the object in the map).
414 ObjectTrimRequest(ImageCtx *ictx, const std::string &oid, uint64_t object_no,
31f18b77
FG
415 const ::SnapContext &snapc, bool post_object_map_update,
416 Context *completion)
417 : AbstractObjectWriteRequest(ictx, oid, object_no, 0, 0, snapc, true,
418 "trim", {}, completion),
7c673cae
FG
419 m_post_object_map_update(post_object_map_update) {
420 }
421
422 const char* get_op_type() const override {
423 return "remove (trim)";
424 }
425
426 bool pre_object_map_update(uint8_t *new_state) override {
427 *new_state = OBJECT_PENDING;
428 return true;
429 }
430
431 bool post_object_map_update() override {
432 return m_post_object_map_update;
433 }
434
435protected:
31f18b77
FG
436 void add_write_ops(librados::ObjectWriteOperation *wr,
437 bool set_hints) override {
7c673cae
FG
438 wr->remove();
439 }
440
441private:
442 bool m_post_object_map_update;
443};
444
445class ObjectTruncateRequest : public AbstractObjectWriteRequest {
446public:
447 ObjectTruncateRequest(ImageCtx *ictx, const std::string &oid,
448 uint64_t object_no, uint64_t object_off,
31f18b77
FG
449 const ::SnapContext &snapc,
450 const ZTracer::Trace &parent_trace, Context *completion)
7c673cae 451 : AbstractObjectWriteRequest(ictx, oid, object_no, object_off, 0, snapc,
31f18b77 452 true, "truncate", parent_trace, completion) {
7c673cae
FG
453 }
454
455 const char* get_op_type() const override {
456 return "truncate";
457 }
458
459 bool pre_object_map_update(uint8_t *new_state) override {
460 if (!m_object_exist && !has_parent())
461 *new_state = OBJECT_NONEXISTENT;
462 else
463 *new_state = OBJECT_EXISTS;
464 return true;
465 }
466
467 void send_write() override;
468
469protected:
31f18b77
FG
470 void add_write_ops(librados::ObjectWriteOperation *wr,
471 bool set_hints) override {
7c673cae
FG
472 wr->truncate(m_object_off);
473 }
474};
475
476class ObjectZeroRequest : public AbstractObjectWriteRequest {
477public:
478 ObjectZeroRequest(ImageCtx *ictx, const std::string &oid, uint64_t object_no,
479 uint64_t object_off, uint64_t object_len,
31f18b77
FG
480 const ::SnapContext &snapc,
481 const ZTracer::Trace &parent_trace, Context *completion)
7c673cae 482 : AbstractObjectWriteRequest(ictx, oid, object_no, object_off, object_len,
31f18b77
FG
483 snapc, true, "zero", parent_trace,
484 completion) {
7c673cae
FG
485 }
486
487 const char* get_op_type() const override {
488 return "zero";
489 }
490
491 bool pre_object_map_update(uint8_t *new_state) override {
492 *new_state = OBJECT_EXISTS;
493 return true;
494 }
495
31f18b77
FG
496 void send_write() override;
497
7c673cae 498protected:
31f18b77
FG
499 void add_write_ops(librados::ObjectWriteOperation *wr,
500 bool set_hints) override {
7c673cae
FG
501 wr->zero(m_object_off, m_object_len);
502 }
503};
504
505class ObjectWriteSameRequest : public AbstractObjectWriteRequest {
506public:
31f18b77
FG
507 ObjectWriteSameRequest(ImageCtx *ictx, const std::string &oid,
508 uint64_t object_no, uint64_t object_off,
509 uint64_t object_len, const ceph::bufferlist &data,
510 const ::SnapContext &snapc, int op_flags,
511 const ZTracer::Trace &parent_trace,
512 Context *completion)
7c673cae 513 : AbstractObjectWriteRequest(ictx, oid, object_no, object_off,
31f18b77
FG
514 object_len, snapc, false, "writesame",
515 parent_trace, completion),
7c673cae
FG
516 m_write_data(data), m_op_flags(op_flags) {
517 }
518
519 const char *get_op_type() const override {
520 return "writesame";
521 }
522
523 bool pre_object_map_update(uint8_t *new_state) override {
524 *new_state = OBJECT_EXISTS;
525 return true;
526 }
527
528protected:
31f18b77
FG
529 void add_write_ops(librados::ObjectWriteOperation *wr,
530 bool set_hints) override;
7c673cae
FG
531
532 void send_write() override;
533
534private:
535 ceph::bufferlist m_write_data;
536 int m_op_flags;
537};
538
c07f9fc5
FG
539class ObjectCompareAndWriteRequest : public AbstractObjectWriteRequest {
540public:
541 typedef std::vector<std::pair<uint64_t, uint64_t> > Extents;
542
543 ObjectCompareAndWriteRequest(ImageCtx *ictx, const std::string &oid,
544 uint64_t object_no, uint64_t object_off,
545 const ceph::bufferlist &cmp_bl,
546 const ceph::bufferlist &write_bl,
547 const ::SnapContext &snapc,
548 uint64_t *mismatch_offset, int op_flags,
549 const ZTracer::Trace &parent_trace,
550 Context *completion)
551 : AbstractObjectWriteRequest(ictx, oid, object_no, object_off,
552 cmp_bl.length(), snapc, false, "compare_and_write",
553 parent_trace, completion),
554 m_cmp_bl(cmp_bl), m_write_bl(write_bl),
555 m_mismatch_offset(mismatch_offset), m_op_flags(op_flags) {
556 }
557
558 const char *get_op_type() const override {
559 return "compare_and_write";
560 }
561
562 bool pre_object_map_update(uint8_t *new_state) override {
563 *new_state = OBJECT_EXISTS;
564 return true;
565 }
566
567 void complete(int r) override;
568protected:
569 void add_write_ops(librados::ObjectWriteOperation *wr,
570 bool set_hints) override;
571
572 void send_write() override;
573
574private:
575 ceph::bufferlist m_cmp_bl;
576 ceph::bufferlist m_write_bl;
577 uint64_t *m_mismatch_offset;
578 int m_op_flags;
579};
580
7c673cae
FG
581} // namespace io
582} // namespace librbd
583
584extern template class librbd::io::ObjectRequest<librbd::ImageCtx>;
585extern template class librbd::io::ObjectReadRequest<librbd::ImageCtx>;
586
587#endif // CEPH_LIBRBD_IO_OBJECT_REQUEST_H