]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/io/ObjectRequest.h
import 15.2.0 Octopus source
[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 "librbd/io/Types.h"
14 #include <map>
15
16 class Context;
17 class ObjectExtent;
18
19 namespace librbd {
20
21 struct ImageCtx;
22
23 namespace io {
24
25 struct AioCompletion;
26 template <typename> class CopyupRequest;
27
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 */
33 template <typename ImageCtxT = ImageCtx>
34 class ObjectRequest {
35 public:
36 static ObjectRequest* create_write(
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);
40 static ObjectRequest* create_discard(
41 ImageCtxT *ictx, uint64_t object_no, uint64_t object_off,
42 uint64_t object_len, const ::SnapContext &snapc, int discard_flags,
43 const ZTracer::Trace &parent_trace, Context *completion);
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);
48 static ObjectRequest* create_compare_and_write(
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,
52 const ZTracer::Trace &parent_trace, Context *completion);
53
54 ObjectRequest(ImageCtxT *ictx, uint64_t objectno, uint64_t off, uint64_t len,
55 librados::snap_t snap_id, const char *trace_name,
56 const ZTracer::Trace &parent_trace, Context *completion);
57 virtual ~ObjectRequest() {
58 m_trace.event("finish");
59 }
60
61 static void add_write_hint(ImageCtxT& image_ctx,
62 librados::ObjectWriteOperation *wr);
63
64 virtual void send() = 0;
65
66 bool has_parent() const {
67 return m_has_parent;
68 }
69
70 virtual const char *get_op_type() const = 0;
71
72 protected:
73 bool compute_parent_extents(Extents *parent_extents, bool read_request);
74
75 ImageCtxT *m_ictx;
76 uint64_t m_object_no, m_object_off, m_object_len;
77 librados::snap_t m_snap_id;
78 Context *m_completion;
79 ZTracer::Trace m_trace;
80
81 void async_finish(int r);
82 void finish(int r);
83
84 private:
85 bool m_has_parent = false;
86 };
87
88 template <typename ImageCtxT = ImageCtx>
89 class ObjectReadRequest : public ObjectRequest<ImageCtxT> {
90 public:
91 typedef std::map<uint64_t, uint64_t> ExtentMap;
92
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,
99 snap_id, op_flags, parent_trace, read_data,
100 extent_map, completion);
101 }
102
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);
108
109 void send() override;
110
111 const char *get_op_type() const override {
112 return "read";
113 }
114
115 private:
116 /**
117 * @verbatim
118 *
119 * <start>
120 * |
121 * |
122 * v
123 * READ_OBJECT
124 * |
125 * v (skip if not needed)
126 * READ_PARENT
127 * |
128 * v (skip if not needed)
129 * COPYUP
130 * |
131 * v
132 * <finish>
133 *
134 * @endverbatim
135 */
136
137 int m_op_flags;
138
139 ceph::bufferlist* m_read_data;
140 ExtentMap* m_extent_map;
141
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();
149 };
150
151 template <typename ImageCtxT = ImageCtx>
152 class AbstractObjectWriteRequest : public ObjectRequest<ImageCtxT> {
153 public:
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);
158
159 virtual bool is_empty_write_op() const {
160 return false;
161 }
162
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
173 void send() override;
174
175 protected:
176 bool m_full_object = false;
177 bool m_copyup_enabled = true;
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
199 private:
200 /**
201 * @verbatim
202 *
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> < . . . . . . . . . . . . . . . . . . . .
227 *
228 * @endverbatim
229 */
230
231 uint64_t m_snap_seq;
232 std::vector<librados::snap_t> m_snaps;
233
234 Extents m_parent_extents;
235 bool m_object_may_exist = false;
236 bool m_copyup_in_progress = false;
237 bool m_guarding_migration_write = false;
238
239 void compute_parent_info();
240
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);
251
252 };
253
254 template <typename ImageCtxT = ImageCtx>
255 class ObjectWriteRequest : public AbstractObjectWriteRequest<ImageCtxT> {
256 public:
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,
262 data.length(), snapc, "write",
263 parent_trace, completion),
264 m_write_data(std::move(data)), m_op_flags(op_flags) {
265 }
266
267 bool is_empty_write_op() const override {
268 return (m_write_data.length() == 0);
269 }
270
271 const char *get_op_type() const override {
272 return "write";
273 }
274
275 protected:
276 void add_write_ops(librados::ObjectWriteOperation *wr) override;
277
278 private:
279 ceph::bufferlist m_write_data;
280 int m_op_flags;
281 };
282
283 template <typename ImageCtxT = ImageCtx>
284 class ObjectDiscardRequest : public AbstractObjectWriteRequest<ImageCtxT> {
285 public:
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,
291 object_len, snapc, "discard",
292 parent_trace, completion),
293 m_discard_flags(discard_flags) {
294 if (this->m_full_object) {
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 }
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;
309 } else {
310 m_discard_action = DISCARD_ACTION_ZERO;
311 }
312 }
313
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:
319 return "remove (create+truncate)";
320 case DISCARD_ACTION_TRUNCATE:
321 return "truncate";
322 case DISCARD_ACTION_ZERO:
323 return "zero";
324 }
325 ceph_abort();
326 return nullptr;
327 }
328
329 uint8_t get_pre_write_object_map_state() const override {
330 if (m_discard_action == DISCARD_ACTION_REMOVE) {
331 return OBJECT_PENDING;
332 }
333 return OBJECT_EXISTS;
334 }
335
336 protected:
337 bool is_no_op_for_nonexistent_object() const override {
338 return (!this->has_parent());
339 }
340 bool is_object_map_update_enabled() const override {
341 return (
342 (m_discard_flags & OBJECT_DISCARD_FLAG_DISABLE_OBJECT_MAP_UPDATE) == 0);
343 }
344 bool is_non_existent_post_write_object_map_state() const override {
345 return (m_discard_action == DISCARD_ACTION_REMOVE);
346 }
347
348 void add_write_hint(librados::ObjectWriteOperation *wr) override {
349 // no hint for discard
350 }
351
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:
358 wr->create(false);
359 // fall through
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:
367 ceph_abort();
368 break;
369 }
370 }
371
372 private:
373 enum DiscardAction {
374 DISCARD_ACTION_REMOVE,
375 DISCARD_ACTION_REMOVE_TRUNCATE,
376 DISCARD_ACTION_TRUNCATE,
377 DISCARD_ACTION_ZERO
378 };
379
380 DiscardAction m_discard_action;
381 int m_discard_flags;
382
383 };
384
385 template <typename ImageCtxT = ImageCtx>
386 class ObjectWriteSameRequest : public AbstractObjectWriteRequest<ImageCtxT> {
387 public:
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,
393 object_len, snapc, "writesame",
394 parent_trace, completion),
395 m_write_data(std::move(data)), m_op_flags(op_flags) {
396 }
397
398 const char *get_op_type() const override {
399 return "writesame";
400 }
401
402 protected:
403 void add_write_ops(librados::ObjectWriteOperation *wr) override;
404
405 private:
406 ceph::bufferlist m_write_data;
407 int m_op_flags;
408 };
409
410 template <typename ImageCtxT = ImageCtx>
411 class ObjectCompareAndWriteRequest : public AbstractObjectWriteRequest<ImageCtxT> {
412 public:
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,
419 cmp_bl.length(), snapc,
420 "compare_and_write", parent_trace,
421 completion),
422 m_cmp_bl(std::move(cmp_bl)), m_write_bl(std::move(write_bl)),
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
430 void add_copyup_ops(librados::ObjectWriteOperation *wr) override {
431 // no-op on copyup
432 }
433
434 protected:
435 virtual bool is_post_copyup_write_required() const {
436 return true;
437 }
438
439 void add_write_ops(librados::ObjectWriteOperation *wr) override;
440
441 int filter_write_result(int r) const override;
442
443 private:
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
450 } // namespace io
451 } // namespace librbd
452
453 extern template class librbd::io::ObjectRequest<librbd::ImageCtx>;
454 extern template class librbd::io::ObjectReadRequest<librbd::ImageCtx>;
455 extern template class librbd::io::AbstractObjectWriteRequest<librbd::ImageCtx>;
456 extern template class librbd::io::ObjectWriteRequest<librbd::ImageCtx>;
457 extern template class librbd::io::ObjectDiscardRequest<librbd::ImageCtx>;
458 extern template class librbd::io::ObjectWriteSameRequest<librbd::ImageCtx>;
459 extern template class librbd::io::ObjectCompareAndWriteRequest<librbd::ImageCtx>;
460
461 #endif // CEPH_LIBRBD_IO_OBJECT_REQUEST_H