]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/io/ObjectRequest.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / librbd / io / ObjectRequest.cc
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#include "librbd/io/ObjectRequest.h"
5#include "common/ceph_context.h"
6#include "common/dout.h"
7#include "common/errno.h"
9f95a23c 8#include "common/ceph_mutex.h"
7c673cae
FG
9#include "common/WorkQueue.h"
10#include "include/Context.h"
c07f9fc5 11#include "include/err.h"
11fdf7f2 12#include "osd/osd_types.h"
7c673cae
FG
13
14#include "librbd/ExclusiveLock.h"
15#include "librbd/ImageCtx.h"
16#include "librbd/ObjectMap.h"
17#include "librbd/Utils.h"
18#include "librbd/io/AioCompletion.h"
19#include "librbd/io/CopyupRequest.h"
20#include "librbd/io/ImageRequest.h"
21#include "librbd/io/ReadResult.h"
22
23#include <boost/bind.hpp>
24#include <boost/optional.hpp>
25
26#define dout_subsys ceph_subsys_rbd
27#undef dout_prefix
9f95a23c
TL
28#define dout_prefix *_dout << "librbd::io::ObjectRequest: " << this \
29 << " " << __func__ << ": " \
30 << data_object_name(this->m_ictx, \
31 this->m_object_no) << " "
7c673cae
FG
32
33namespace librbd {
34namespace io {
35
9f95a23c
TL
36using librbd::util::data_object_name;
37
b32b8144 38namespace {
7c673cae
FG
39
40template <typename I>
b32b8144 41inline bool is_copy_on_read(I *ictx, librados::snap_t snap_id) {
9f95a23c 42 std::shared_lock image_locker{ictx->image_lock};
b32b8144
FG
43 return (ictx->clone_copy_on_read &&
44 !ictx->read_only && snap_id == CEPH_NOSNAP &&
45 (ictx->exclusive_lock == nullptr ||
46 ictx->exclusive_lock->is_lock_owner()));
7c673cae
FG
47}
48
b32b8144 49} // anonymous namespace
3efd9988 50
7c673cae
FG
51template <typename I>
52ObjectRequest<I>*
9f95a23c
TL
53ObjectRequest<I>::create_write(
54 I *ictx, uint64_t object_no, uint64_t object_off, ceph::bufferlist&& data,
55 const ::SnapContext &snapc, int op_flags,
56 const ZTracer::Trace &parent_trace, Context *completion) {
57 return new ObjectWriteRequest<I>(ictx, object_no, object_off,
11fdf7f2
TL
58 std::move(data), snapc, op_flags,
59 parent_trace, completion);
7c673cae
FG
60}
61
62template <typename I>
63ObjectRequest<I>*
9f95a23c
TL
64ObjectRequest<I>::create_discard(
65 I *ictx, uint64_t object_no, uint64_t object_off, uint64_t object_len,
66 const ::SnapContext &snapc, int discard_flags,
67 const ZTracer::Trace &parent_trace, Context *completion) {
68 return new ObjectDiscardRequest<I>(ictx, object_no, object_off,
11fdf7f2
TL
69 object_len, snapc, discard_flags,
70 parent_trace, completion);
7c673cae
FG
71}
72
73template <typename I>
74ObjectRequest<I>*
9f95a23c
TL
75ObjectRequest<I>::create_write_same(
76 I *ictx, uint64_t object_no, uint64_t object_off, uint64_t object_len,
77 ceph::bufferlist&& data, const ::SnapContext &snapc, int op_flags,
78 const ZTracer::Trace &parent_trace, Context *completion) {
79 return new ObjectWriteSameRequest<I>(ictx, object_no, object_off,
11fdf7f2
TL
80 object_len, std::move(data), snapc,
81 op_flags, parent_trace, completion);
7c673cae
FG
82}
83
c07f9fc5
FG
84template <typename I>
85ObjectRequest<I>*
9f95a23c
TL
86ObjectRequest<I>::create_compare_and_write(
87 I *ictx, uint64_t object_no, uint64_t object_off,
88 ceph::bufferlist&& cmp_data, ceph::bufferlist&& write_data,
89 const ::SnapContext &snapc, uint64_t *mismatch_offset, int op_flags,
90 const ZTracer::Trace &parent_trace, Context *completion) {
91 return new ObjectCompareAndWriteRequest<I>(ictx, object_no, object_off,
11fdf7f2
TL
92 std::move(cmp_data),
93 std::move(write_data), snapc,
b32b8144
FG
94 mismatch_offset, op_flags,
95 parent_trace, completion);
c07f9fc5
FG
96}
97
7c673cae 98template <typename I>
9f95a23c
TL
99ObjectRequest<I>::ObjectRequest(
100 I *ictx, uint64_t objectno, uint64_t off, uint64_t len,
101 librados::snap_t snap_id, const char *trace_name,
102 const ZTracer::Trace &trace, Context *completion)
103 : m_ictx(ictx), m_object_no(objectno), m_object_off(off),
7c673cae 104 m_object_len(len), m_snap_id(snap_id), m_completion(completion),
31f18b77 105 m_trace(util::create_trace(*ictx, "", trace)) {
eafe8130 106 ceph_assert(m_ictx->data_ctx.is_valid());
31f18b77 107 if (m_trace.valid()) {
9f95a23c
TL
108 m_trace.copy_name(trace_name + std::string(" ") +
109 data_object_name(ictx, objectno));
31f18b77
FG
110 m_trace.event("start");
111 }
7c673cae
FG
112}
113
114template <typename I>
b32b8144
FG
115void ObjectRequest<I>::add_write_hint(I& image_ctx,
116 librados::ObjectWriteOperation *wr) {
117 if (image_ctx.enable_alloc_hint) {
92f5a8d4
TL
118 wr->set_alloc_hint2(image_ctx.get_object_size(),
119 image_ctx.get_object_size(),
120 image_ctx.alloc_hint_flags);
121 } else if (image_ctx.alloc_hint_flags != 0U) {
122 wr->set_alloc_hint2(0, 0, image_ctx.alloc_hint_flags);
7c673cae
FG
123 }
124}
125
126template <typename I>
11fdf7f2
TL
127bool ObjectRequest<I>::compute_parent_extents(Extents *parent_extents,
128 bool read_request) {
9f95a23c 129 ceph_assert(ceph_mutex_is_locked(m_ictx->image_lock));
7c673cae 130
b32b8144
FG
131 m_has_parent = false;
132 parent_extents->clear();
133
7c673cae
FG
134 uint64_t parent_overlap;
135 int r = m_ictx->get_parent_overlap(m_snap_id, &parent_overlap);
136 if (r < 0) {
137 // NOTE: it's possible for a snapshot to be deleted while we are
138 // still reading from it
139 lderr(m_ictx->cct) << "failed to retrieve parent overlap: "
b32b8144
FG
140 << cpp_strerror(r) << dendl;
141 return false;
11fdf7f2
TL
142 }
143
144 if (!read_request && !m_ictx->migration_info.empty()) {
145 parent_overlap = m_ictx->migration_info.overlap;
146 }
147
148 if (parent_overlap == 0) {
7c673cae
FG
149 return false;
150 }
151
b32b8144
FG
152 Striper::extent_to_file(m_ictx->cct, &m_ictx->layout, m_object_no, 0,
153 m_ictx->layout.object_size, *parent_extents);
154 uint64_t object_overlap = m_ictx->prune_parent_extents(*parent_extents,
155 parent_overlap);
7c673cae
FG
156 if (object_overlap > 0) {
157 ldout(m_ictx->cct, 20) << "overlap " << parent_overlap << " "
b32b8144
FG
158 << "extents " << *parent_extents << dendl;
159 m_has_parent = !parent_extents->empty();
7c673cae
FG
160 return true;
161 }
162 return false;
163}
164
b32b8144
FG
165template <typename I>
166void ObjectRequest<I>::async_finish(int r) {
167 ldout(m_ictx->cct, 20) << "r=" << r << dendl;
168 m_ictx->op_work_queue->queue(util::create_context_callback<
169 ObjectRequest<I>, &ObjectRequest<I>::finish>(this), r);
170}
171
172template <typename I>
173void ObjectRequest<I>::finish(int r) {
174 ldout(m_ictx->cct, 20) << "r=" << r << dendl;
175 m_completion->complete(r);
176 delete this;
7c673cae
FG
177}
178
179/** read **/
180
181template <typename I>
9f95a23c
TL
182ObjectReadRequest<I>::ObjectReadRequest(
183 I *ictx, uint64_t objectno, uint64_t offset, uint64_t len,
184 librados::snap_t snap_id, int op_flags, const ZTracer::Trace &parent_trace,
185 bufferlist* read_data, ExtentMap* extent_map, Context *completion)
186 : ObjectRequest<I>(ictx, objectno, offset, len, snap_id, "read",
b32b8144 187 parent_trace, completion),
11fdf7f2 188 m_op_flags(op_flags), m_read_data(read_data), m_extent_map(extent_map) {
7c673cae
FG
189}
190
191template <typename I>
b32b8144
FG
192void ObjectReadRequest<I>::send() {
193 I *image_ctx = this->m_ictx;
194 ldout(image_ctx->cct, 20) << dendl;
7c673cae 195
11fdf7f2 196 read_object();
b32b8144
FG
197}
198
199template <typename I>
200void ObjectReadRequest<I>::read_object() {
201 I *image_ctx = this->m_ictx;
7c673cae 202 {
9f95a23c 203 std::shared_lock image_locker{image_ctx->image_lock};
7c673cae
FG
204 if (image_ctx->object_map != nullptr &&
205 !image_ctx->object_map->object_may_exist(this->m_object_no)) {
9f95a23c 206 image_ctx->op_work_queue->queue(new LambdaContext([this](int r) {
b32b8144
FG
207 read_parent();
208 }), 0);
7c673cae
FG
209 return;
210 }
211 }
212
b32b8144
FG
213 ldout(image_ctx->cct, 20) << dendl;
214
7c673cae 215 librados::ObjectReadOperation op;
b32b8144 216 if (this->m_object_len >= image_ctx->sparse_read_threshold_bytes) {
11fdf7f2
TL
217 op.sparse_read(this->m_object_off, this->m_object_len, m_extent_map,
218 m_read_data, nullptr);
7c673cae 219 } else {
11fdf7f2 220 op.read(this->m_object_off, this->m_object_len, m_read_data, nullptr);
7c673cae
FG
221 }
222 op.set_op_flags2(m_op_flags);
223
b32b8144
FG
224 librados::AioCompletion *rados_completion = util::create_rados_callback<
225 ObjectReadRequest<I>, &ObjectReadRequest<I>::handle_read_object>(this);
226 int flags = image_ctx->get_read_flags(this->m_snap_id);
31f18b77 227 int r = image_ctx->data_ctx.aio_operate(
9f95a23c
TL
228 data_object_name(this->m_ictx, this->m_object_no), rados_completion, &op,
229 flags, nullptr,
31f18b77 230 (this->m_trace.valid() ? this->m_trace.get_info() : nullptr));
11fdf7f2 231 ceph_assert(r == 0);
7c673cae
FG
232
233 rados_completion->release();
234}
235
236template <typename I>
b32b8144
FG
237void ObjectReadRequest<I>::handle_read_object(int r) {
238 I *image_ctx = this->m_ictx;
239 ldout(image_ctx->cct, 20) << "r=" << r << dendl;
240
241 if (r == -ENOENT) {
242 read_parent();
243 return;
244 } else if (r < 0) {
245 lderr(image_ctx->cct) << "failed to read from object: "
246 << cpp_strerror(r) << dendl;
247 this->finish(r);
248 return;
249 }
7c673cae 250
b32b8144
FG
251 this->finish(0);
252}
253
254template <typename I>
255void ObjectReadRequest<I>::read_parent() {
256 I *image_ctx = this->m_ictx;
b32b8144 257
9f95a23c 258 std::shared_lock image_locker{image_ctx->image_lock};
81eedcae
TL
259
260 // calculate reverse mapping onto the image
b32b8144 261 Extents parent_extents;
81eedcae
TL
262 Striper::extent_to_file(image_ctx->cct, &image_ctx->layout,
263 this->m_object_no, this->m_object_off,
264 this->m_object_len, parent_extents);
265
266 uint64_t parent_overlap = 0;
267 uint64_t object_overlap = 0;
268 int r = image_ctx->get_parent_overlap(this->m_snap_id, &parent_overlap);
269 if (r == 0) {
270 object_overlap = image_ctx->prune_parent_extents(parent_extents,
271 parent_overlap);
7c673cae
FG
272 }
273
b32b8144 274 if (object_overlap == 0) {
9f95a23c 275 image_locker.unlock();
81eedcae 276
b32b8144
FG
277 this->finish(-ENOENT);
278 return;
279 }
280
281 ldout(image_ctx->cct, 20) << dendl;
282
81eedcae 283 auto parent_completion = AioCompletion::create_and_start<
b32b8144
FG
284 ObjectReadRequest<I>, &ObjectReadRequest<I>::handle_read_parent>(
285 this, util::get_image_ctx(image_ctx->parent), AIO_TYPE_READ);
286 ImageRequest<I>::aio_read(image_ctx->parent, parent_completion,
11fdf7f2 287 std::move(parent_extents), ReadResult{m_read_data},
b32b8144
FG
288 0, this->m_trace);
289}
290
291template <typename I>
292void ObjectReadRequest<I>::handle_read_parent(int r) {
293 I *image_ctx = this->m_ictx;
294 ldout(image_ctx->cct, 20) << "r=" << r << dendl;
295
296 if (r == -ENOENT) {
297 this->finish(r);
298 return;
299 } else if (r < 0) {
300 lderr(image_ctx->cct) << "failed to read parent extents: "
301 << cpp_strerror(r) << dendl;
302 this->finish(r);
303 return;
304 }
305
306 copyup();
307}
308
309template <typename I>
310void ObjectReadRequest<I>::copyup() {
311 I *image_ctx = this->m_ictx;
312 if (!is_copy_on_read(image_ctx, this->m_snap_id)) {
313 this->finish(0);
314 return;
315 }
316
9f95a23c
TL
317 image_ctx->owner_lock.lock_shared();
318 image_ctx->image_lock.lock_shared();
b32b8144 319 Extents parent_extents;
11fdf7f2 320 if (!this->compute_parent_extents(&parent_extents, true) ||
b32b8144
FG
321 (image_ctx->exclusive_lock != nullptr &&
322 !image_ctx->exclusive_lock->is_lock_owner())) {
9f95a23c
TL
323 image_ctx->image_lock.unlock_shared();
324 image_ctx->owner_lock.unlock_shared();
b32b8144
FG
325 this->finish(0);
326 return;
327 }
328
329 ldout(image_ctx->cct, 20) << dendl;
330
9f95a23c 331 image_ctx->copyup_list_lock.lock();
b32b8144 332 auto it = image_ctx->copyup_list.find(this->m_object_no);
7c673cae
FG
333 if (it == image_ctx->copyup_list.end()) {
334 // create and kick off a CopyupRequest
b32b8144 335 auto new_req = CopyupRequest<I>::create(
9f95a23c 336 image_ctx, this->m_object_no, std::move(parent_extents), this->m_trace);
7c673cae
FG
337
338 image_ctx->copyup_list[this->m_object_no] = new_req;
9f95a23c
TL
339 image_ctx->copyup_list_lock.unlock();
340 image_ctx->image_lock.unlock_shared();
7c673cae 341 new_req->send();
11fdf7f2 342 } else {
9f95a23c
TL
343 image_ctx->copyup_list_lock.unlock();
344 image_ctx->image_lock.unlock_shared();
7c673cae 345 }
7c673cae 346
9f95a23c 347 image_ctx->owner_lock.unlock_shared();
b32b8144 348 this->finish(0);
7c673cae
FG
349}
350
351/** write **/
352
b32b8144
FG
353template <typename I>
354AbstractObjectWriteRequest<I>::AbstractObjectWriteRequest(
9f95a23c
TL
355 I *ictx, uint64_t object_no, uint64_t object_off, uint64_t len,
356 const ::SnapContext &snapc, const char *trace_name,
b32b8144 357 const ZTracer::Trace &parent_trace, Context *completion)
9f95a23c
TL
358 : ObjectRequest<I>(ictx, object_no, object_off, len, CEPH_NOSNAP, trace_name,
359 parent_trace, completion),
b32b8144 360 m_snap_seq(snapc.seq.val)
7c673cae
FG
361{
362 m_snaps.insert(m_snaps.end(), snapc.snaps.begin(), snapc.snaps.end());
7c673cae 363
b32b8144
FG
364 if (this->m_object_off == 0 &&
365 this->m_object_len == ictx->get_object_size()) {
366 m_full_object = true;
367 }
7c673cae 368
11fdf7f2 369 compute_parent_info();
81eedcae 370
9f95a23c 371 ictx->image_lock.lock_shared();
81eedcae
TL
372 if (!ictx->migration_info.empty()) {
373 m_guarding_migration_write = true;
374 }
9f95a23c 375 ictx->image_lock.unlock_shared();
11fdf7f2
TL
376}
377
378template <typename I>
379void AbstractObjectWriteRequest<I>::compute_parent_info() {
380 I *image_ctx = this->m_ictx;
9f95a23c 381 std::shared_lock image_locker{image_ctx->image_lock};
11fdf7f2
TL
382
383 this->compute_parent_extents(&m_parent_extents, false);
384
b32b8144
FG
385 if (!this->has_parent() ||
386 (m_full_object && m_snaps.empty() && !is_post_copyup_write_required())) {
11fdf7f2 387 m_copyup_enabled = false;
7c673cae 388 }
b32b8144 389}
7c673cae 390
b32b8144
FG
391template <typename I>
392void AbstractObjectWriteRequest<I>::add_write_hint(
393 librados::ObjectWriteOperation *wr) {
394 I *image_ctx = this->m_ictx;
9f95a23c 395 std::shared_lock image_locker{image_ctx->image_lock};
b32b8144
FG
396 if (image_ctx->object_map == nullptr || !this->m_object_may_exist) {
397 ObjectRequest<I>::add_write_hint(*image_ctx, wr);
398 }
7c673cae
FG
399}
400
b32b8144
FG
401template <typename I>
402void AbstractObjectWriteRequest<I>::send() {
403 I *image_ctx = this->m_ictx;
9f95a23c 404 ldout(image_ctx->cct, 20) << this->get_op_type() << " "
b32b8144
FG
405 << this->m_object_off << "~" << this->m_object_len
406 << dendl;
7c673cae 407 {
9f95a23c 408 std::shared_lock image_lock{image_ctx->image_lock};
b32b8144
FG
409 if (image_ctx->object_map == nullptr) {
410 m_object_may_exist = true;
7c673cae
FG
411 } else {
412 // should have been flushed prior to releasing lock
11fdf7f2 413 ceph_assert(image_ctx->exclusive_lock->is_lock_owner());
b32b8144
FG
414 m_object_may_exist = image_ctx->object_map->object_may_exist(
415 this->m_object_no);
7c673cae
FG
416 }
417 }
418
b32b8144
FG
419 if (!m_object_may_exist && is_no_op_for_nonexistent_object()) {
420 ldout(image_ctx->cct, 20) << "skipping no-op on nonexistent object"
421 << dendl;
422 this->async_finish(0);
423 return;
7c673cae
FG
424 }
425
b32b8144 426 pre_write_object_map_update();
7c673cae
FG
427}
428
b32b8144
FG
429template <typename I>
430void AbstractObjectWriteRequest<I>::pre_write_object_map_update() {
431 I *image_ctx = this->m_ictx;
7c673cae 432
9f95a23c 433 image_ctx->image_lock.lock_shared();
b32b8144 434 if (image_ctx->object_map == nullptr || !is_object_map_update_enabled()) {
9f95a23c 435 image_ctx->image_lock.unlock_shared();
b32b8144
FG
436 write_object();
437 return;
7c673cae
FG
438 }
439
b32b8144
FG
440 if (!m_object_may_exist && m_copyup_enabled) {
441 // optimization: copyup required
9f95a23c 442 image_ctx->image_lock.unlock_shared();
b32b8144
FG
443 copyup();
444 return;
445 }
7c673cae 446
b32b8144 447 uint8_t new_state = this->get_pre_write_object_map_state();
9f95a23c
TL
448 ldout(image_ctx->cct, 20) << this->m_object_off << "~" << this->m_object_len
449 << dendl;
7c673cae 450
b32b8144
FG
451 if (image_ctx->object_map->template aio_update<
452 AbstractObjectWriteRequest<I>,
453 &AbstractObjectWriteRequest<I>::handle_pre_write_object_map_update>(
91327a77
AA
454 CEPH_NOSNAP, this->m_object_no, new_state, {}, this->m_trace, false,
455 this)) {
9f95a23c 456 image_ctx->image_lock.unlock_shared();
b32b8144 457 return;
7c673cae
FG
458 }
459
9f95a23c 460 image_ctx->image_lock.unlock_shared();
b32b8144 461 write_object();
7c673cae
FG
462}
463
b32b8144
FG
464template <typename I>
465void AbstractObjectWriteRequest<I>::handle_pre_write_object_map_update(int r) {
466 I *image_ctx = this->m_ictx;
467 ldout(image_ctx->cct, 20) << "r=" << r << dendl;
11fdf7f2
TL
468 if (r < 0) {
469 lderr(image_ctx->cct) << "failed to update object map: "
470 << cpp_strerror(r) << dendl;
471 this->finish(r);
472 return;
473 }
7c673cae 474
b32b8144 475 write_object();
7c673cae
FG
476}
477
b32b8144
FG
478template <typename I>
479void AbstractObjectWriteRequest<I>::write_object() {
480 I *image_ctx = this->m_ictx;
481 ldout(image_ctx->cct, 20) << dendl;
7c673cae 482
b32b8144
FG
483 librados::ObjectWriteOperation write;
484 if (m_copyup_enabled) {
485 ldout(image_ctx->cct, 20) << "guarding write" << dendl;
81eedcae 486 if (m_guarding_migration_write) {
11fdf7f2
TL
487 cls_client::assert_snapc_seq(
488 &write, m_snap_seq, cls::rbd::ASSERT_SNAPC_SEQ_LE_SNAPSET_SEQ);
489 } else {
490 write.assert_exists();
491 }
7c673cae
FG
492 }
493
b32b8144
FG
494 add_write_hint(&write);
495 add_write_ops(&write);
11fdf7f2 496 ceph_assert(write.size() != 0);
7c673cae 497
b32b8144
FG
498 librados::AioCompletion *rados_completion = util::create_rados_callback<
499 AbstractObjectWriteRequest<I>,
500 &AbstractObjectWriteRequest<I>::handle_write_object>(this);
501 int r = image_ctx->data_ctx.aio_operate(
9f95a23c
TL
502 data_object_name(this->m_ictx, this->m_object_no), rados_completion,
503 &write, m_snap_seq, m_snaps,
31f18b77 504 (this->m_trace.valid() ? this->m_trace.get_info() : nullptr));
11fdf7f2 505 ceph_assert(r == 0);
7c673cae
FG
506 rados_completion->release();
507}
7c673cae 508
b32b8144
FG
509template <typename I>
510void AbstractObjectWriteRequest<I>::handle_write_object(int r) {
511 I *image_ctx = this->m_ictx;
512 ldout(image_ctx->cct, 20) << "r=" << r << dendl;
513
514 r = filter_write_result(r);
515 if (r == -ENOENT) {
516 if (m_copyup_enabled) {
517 copyup();
518 return;
519 }
11fdf7f2 520 } else if (r == -ERANGE && m_guarding_migration_write) {
9f95a23c 521 image_ctx->image_lock.lock_shared();
81eedcae 522 m_guarding_migration_write = !image_ctx->migration_info.empty();
9f95a23c 523 image_ctx->image_lock.unlock_shared();
81eedcae
TL
524
525 if (m_guarding_migration_write) {
11fdf7f2
TL
526 copyup();
527 } else {
528 ldout(image_ctx->cct, 10) << "migration parent gone, restart io" << dendl;
11fdf7f2
TL
529 compute_parent_info();
530 write_object();
531 }
532 return;
b32b8144
FG
533 } else if (r == -EILSEQ) {
534 ldout(image_ctx->cct, 10) << "failed to write object" << dendl;
535 this->finish(r);
536 return;
537 } else if (r < 0) {
538 lderr(image_ctx->cct) << "failed to write object: " << cpp_strerror(r)
539 << dendl;
540 this->finish(r);
541 return;
7c673cae
FG
542 }
543
b32b8144 544 post_write_object_map_update();
7c673cae
FG
545}
546
b32b8144
FG
547template <typename I>
548void AbstractObjectWriteRequest<I>::copyup() {
549 I *image_ctx = this->m_ictx;
550 ldout(image_ctx->cct, 20) << dendl;
7c673cae 551
11fdf7f2 552 ceph_assert(!m_copyup_in_progress);
b32b8144 553 m_copyup_in_progress = true;
7c673cae 554
9f95a23c 555 image_ctx->copyup_list_lock.lock();
b32b8144
FG
556 auto it = image_ctx->copyup_list.find(this->m_object_no);
557 if (it == image_ctx->copyup_list.end()) {
558 auto new_req = CopyupRequest<I>::create(
9f95a23c
TL
559 image_ctx, this->m_object_no, std::move(this->m_parent_extents),
560 this->m_trace);
b32b8144
FG
561 this->m_parent_extents.clear();
562
563 // make sure to wait on this CopyupRequest
564 new_req->append_request(this);
565 image_ctx->copyup_list[this->m_object_no] = new_req;
566
9f95a23c 567 image_ctx->copyup_list_lock.unlock();
b32b8144 568 new_req->send();
31f18b77 569 } else {
b32b8144 570 it->second->append_request(this);
9f95a23c 571 image_ctx->copyup_list_lock.unlock();
31f18b77 572 }
7c673cae
FG
573}
574
b32b8144
FG
575template <typename I>
576void AbstractObjectWriteRequest<I>::handle_copyup(int r) {
577 I *image_ctx = this->m_ictx;
578 ldout(image_ctx->cct, 20) << "r=" << r << dendl;
579
11fdf7f2 580 ceph_assert(m_copyup_in_progress);
b32b8144
FG
581 m_copyup_in_progress = false;
582
81eedcae 583 if (r < 0 && r != -ERESTART) {
b32b8144
FG
584 lderr(image_ctx->cct) << "failed to copyup object: " << cpp_strerror(r)
585 << dendl;
586 this->finish(r);
587 return;
31f18b77 588 }
31f18b77 589
81eedcae 590 if (r == -ERESTART || is_post_copyup_write_required()) {
b32b8144
FG
591 write_object();
592 return;
7c673cae 593 }
b32b8144
FG
594
595 post_write_object_map_update();
7c673cae
FG
596}
597
b32b8144
FG
598template <typename I>
599void AbstractObjectWriteRequest<I>::post_write_object_map_update() {
600 I *image_ctx = this->m_ictx;
601
9f95a23c 602 image_ctx->image_lock.lock_shared();
b32b8144
FG
603 if (image_ctx->object_map == nullptr || !is_object_map_update_enabled() ||
604 !is_non_existent_post_write_object_map_state()) {
9f95a23c 605 image_ctx->image_lock.unlock_shared();
b32b8144
FG
606 this->finish(0);
607 return;
7c673cae
FG
608 }
609
b32b8144 610 ldout(image_ctx->cct, 20) << dendl;
7c673cae 611
b32b8144 612 // should have been flushed prior to releasing lock
11fdf7f2 613 ceph_assert(image_ctx->exclusive_lock->is_lock_owner());
b32b8144
FG
614 if (image_ctx->object_map->template aio_update<
615 AbstractObjectWriteRequest<I>,
616 &AbstractObjectWriteRequest<I>::handle_post_write_object_map_update>(
617 CEPH_NOSNAP, this->m_object_no, OBJECT_NONEXISTENT, OBJECT_PENDING,
91327a77 618 this->m_trace, false, this)) {
9f95a23c 619 image_ctx->image_lock.unlock_shared();
b32b8144 620 return;
7c673cae
FG
621 }
622
9f95a23c 623 image_ctx->image_lock.unlock_shared();
b32b8144 624 this->finish(0);
7c673cae
FG
625}
626
b32b8144
FG
627template <typename I>
628void AbstractObjectWriteRequest<I>::handle_post_write_object_map_update(int r) {
629 I *image_ctx = this->m_ictx;
630 ldout(image_ctx->cct, 20) << "r=" << r << dendl;
11fdf7f2
TL
631 if (r < 0) {
632 lderr(image_ctx->cct) << "failed to update object map: "
633 << cpp_strerror(r) << dendl;
634 this->finish(r);
635 return;
636 }
c07f9fc5 637
b32b8144
FG
638 this->finish(0);
639}
c07f9fc5 640
b32b8144
FG
641template <typename I>
642void ObjectWriteRequest<I>::add_write_ops(librados::ObjectWriteOperation *wr) {
643 if (this->m_full_object) {
644 wr->write_full(m_write_data);
c07f9fc5 645 } else {
b32b8144 646 wr->write(this->m_object_off, m_write_data);
c07f9fc5
FG
647 }
648 wr->set_op_flags2(m_op_flags);
649}
650
b32b8144
FG
651template <typename I>
652void ObjectWriteSameRequest<I>::add_write_ops(
653 librados::ObjectWriteOperation *wr) {
654 wr->writesame(this->m_object_off, this->m_object_len, m_write_data);
655 wr->set_op_flags2(m_op_flags);
c07f9fc5
FG
656}
657
b32b8144
FG
658template <typename I>
659void ObjectCompareAndWriteRequest<I>::add_write_ops(
660 librados::ObjectWriteOperation *wr) {
661 wr->cmpext(this->m_object_off, m_cmp_bl, nullptr);
c07f9fc5 662
b32b8144
FG
663 if (this->m_full_object) {
664 wr->write_full(m_write_bl);
665 } else {
666 wr->write(this->m_object_off, m_write_bl);
667 }
668 wr->set_op_flags2(m_op_flags);
669}
c07f9fc5 670
b32b8144
FG
671template <typename I>
672int ObjectCompareAndWriteRequest<I>::filter_write_result(int r) const {
673 if (r <= -MAX_ERRNO) {
674 I *image_ctx = this->m_ictx;
675 Extents image_extents;
676
677 // object extent compare mismatch
678 uint64_t offset = -MAX_ERRNO - r;
679 Striper::extent_to_file(image_ctx->cct, &image_ctx->layout,
680 this->m_object_no, offset, this->m_object_len,
681 image_extents);
11fdf7f2 682 ceph_assert(image_extents.size() == 1);
b32b8144
FG
683
684 if (m_mismatch_offset) {
685 *m_mismatch_offset = image_extents[0].first;
c07f9fc5 686 }
b32b8144 687 r = -EILSEQ;
c07f9fc5 688 }
b32b8144 689 return r;
c07f9fc5
FG
690}
691
7c673cae
FG
692} // namespace io
693} // namespace librbd
694
695template class librbd::io::ObjectRequest<librbd::ImageCtx>;
696template class librbd::io::ObjectReadRequest<librbd::ImageCtx>;
b32b8144
FG
697template class librbd::io::AbstractObjectWriteRequest<librbd::ImageCtx>;
698template class librbd::io::ObjectWriteRequest<librbd::ImageCtx>;
699template class librbd::io::ObjectDiscardRequest<librbd::ImageCtx>;
700template class librbd::io::ObjectWriteSameRequest<librbd::ImageCtx>;
701template class librbd::io::ObjectCompareAndWriteRequest<librbd::ImageCtx>;