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