]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/image/CloneRequest.cc
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / librbd / image / CloneRequest.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 "cls/rbd/cls_rbd_client.h"
5#include "cls/rbd/cls_rbd_types.h"
6#include "common/dout.h"
7#include "common/errno.h"
11fdf7f2 8#include "include/ceph_assert.h"
7c673cae 9#include "librbd/ImageState.h"
11fdf7f2
TL
10#include "librbd/Utils.h"
11#include "librbd/image/AttachChildRequest.h"
12#include "librbd/image/AttachParentRequest.h"
7c673cae
FG
13#include "librbd/image/CloneRequest.h"
14#include "librbd/image/CreateRequest.h"
15#include "librbd/image/RemoveRequest.h"
7c673cae
FG
16#include "librbd/mirror/EnableRequest.h"
17
18#define dout_subsys ceph_subsys_rbd
19#undef dout_prefix
11fdf7f2
TL
20#define dout_prefix *_dout << "librbd::image::CloneRequest: " << this << " " \
21 << __func__ << ": "
7c673cae 22
b32b8144
FG
23#define MAX_KEYS 64
24
7c673cae
FG
25namespace librbd {
26namespace image {
27
28using util::create_rados_callback;
29using util::create_context_callback;
30using util::create_async_context_callback;
31
32template <typename I>
11fdf7f2
TL
33CloneRequest<I>::CloneRequest(ConfigProxy& config,
34 IoCtx& parent_io_ctx,
35 const std::string& parent_image_id,
36 const std::string& parent_snap_name,
37 uint64_t parent_snap_id,
38 IoCtx &c_ioctx,
7c673cae
FG
39 const std::string &c_name,
40 const std::string &c_id,
41 ImageOptions c_options,
42 const std::string &non_primary_global_image_id,
43 const std::string &primary_mirror_uuid,
44 ContextWQ *op_work_queue, Context *on_finish)
11fdf7f2
TL
45 : m_config(config), m_parent_io_ctx(parent_io_ctx),
46 m_parent_image_id(parent_image_id), m_parent_snap_name(parent_snap_name),
47 m_parent_snap_id(parent_snap_id), m_ioctx(c_ioctx), m_name(c_name),
48 m_id(c_id), m_opts(c_options),
7c673cae
FG
49 m_non_primary_global_image_id(non_primary_global_image_id),
50 m_primary_mirror_uuid(primary_mirror_uuid),
51 m_op_work_queue(op_work_queue), m_on_finish(on_finish),
52 m_use_p_features(true) {
53
54 m_cct = reinterpret_cast<CephContext *>(m_ioctx.cct());
55
56 bool default_format_set;
57 m_opts.is_set(RBD_IMAGE_OPTION_FORMAT, &default_format_set);
58 if (!default_format_set) {
59 m_opts.set(RBD_IMAGE_OPTION_FORMAT, static_cast<uint64_t>(2));
60 }
61
11fdf7f2
TL
62 ldout(m_cct, 20) << "parent_pool_id=" << parent_io_ctx.get_id() << ", "
63 << "parent_image_id=" << parent_image_id << ", "
64 << "parent_snap=" << parent_snap_name << "/"
65 << parent_snap_id << " clone to "
66 << "pool_id=" << m_ioctx.get_id() << ", "
67 << "name=" << m_name << ", "
68 << "opts=" << m_opts << dendl;
7c673cae
FG
69}
70
71template <typename I>
72void CloneRequest<I>::send() {
11fdf7f2 73 ldout(m_cct, 20) << dendl;
7c673cae
FG
74 validate_options();
75}
76
77template <typename I>
78void CloneRequest<I>::validate_options() {
11fdf7f2 79 ldout(m_cct, 20) << dendl;
7c673cae
FG
80
81 uint64_t format = 0;
82 m_opts.get(RBD_IMAGE_OPTION_FORMAT, &format);
83 if (format < 2) {
84 lderr(m_cct) << "format 2 or later required for clone" << dendl;
11fdf7f2
TL
85 complete(-EINVAL);
86 return;
7c673cae
FG
87 }
88
89 if (m_opts.get(RBD_IMAGE_OPTION_FEATURES, &m_features) == 0) {
90 if (m_features & ~RBD_FEATURES_ALL) {
91 lderr(m_cct) << "librbd does not support requested features" << dendl;
11fdf7f2
TL
92 complete(-ENOSYS);
93 return;
7c673cae
FG
94 }
95 m_use_p_features = false;
96 }
97
92f5a8d4
TL
98 if (m_opts.get(RBD_IMAGE_OPTION_CLONE_FORMAT, &m_clone_format) < 0) {
99 std::string default_clone_format = m_config.get_val<std::string>(
100 "rbd_default_clone_format");
101 if (default_clone_format == "1") {
11fdf7f2 102 m_clone_format = 1;
92f5a8d4
TL
103 } else if (default_clone_format == "auto") {
104 librados::Rados rados(m_ioctx);
105 int8_t min_compat_client;
106 int8_t require_min_compat_client;
107 int r = rados.get_min_compatible_client(&min_compat_client,
108 &require_min_compat_client);
109 if (r < 0) {
110 complete(r);
111 return;
112 }
113 if (std::max(min_compat_client, require_min_compat_client) <
114 CEPH_RELEASE_MIMIC) {
115 m_clone_format = 1;
116 }
11fdf7f2
TL
117 }
118 }
119
120 if (m_clone_format == 1 &&
121 m_parent_io_ctx.get_namespace() != m_ioctx.get_namespace()) {
122 ldout(m_cct, 1) << "clone v2 required for cross-namespace clones" << dendl;
123 complete(-EXDEV);
124 return;
125 }
126
127 open_parent();
7c673cae
FG
128}
129
130template <typename I>
11fdf7f2
TL
131void CloneRequest<I>::open_parent() {
132 ldout(m_cct, 20) << dendl;
133 ceph_assert(m_parent_snap_name.empty() ^ (m_parent_snap_id == CEPH_NOSNAP));
134
135 if (m_parent_snap_id != CEPH_NOSNAP) {
136 m_parent_image_ctx = I::create("", m_parent_image_id, m_parent_snap_id,
137 m_parent_io_ctx, true);
138 } else {
139 m_parent_image_ctx = I::create("", m_parent_image_id,
140 m_parent_snap_name.c_str(), m_parent_io_ctx,
141 true);
142 }
143
144 Context *ctx = create_context_callback<
145 CloneRequest<I>, &CloneRequest<I>::handle_open_parent>(this);
146 m_parent_image_ctx->state->open(OPEN_FLAG_SKIP_OPEN_PARENT, ctx);
147}
148
149template <typename I>
150void CloneRequest<I>::handle_open_parent(int r) {
151 ldout(m_cct, 20) << "r=" << r << dendl;
152
153 if (r < 0) {
154 m_parent_image_ctx->destroy();
155 m_parent_image_ctx = nullptr;
7c673cae 156
11fdf7f2
TL
157 lderr(m_cct) << "failed to open parent image: " << cpp_strerror(r) << dendl;
158 complete(r);
159 return;
160 }
161
162 m_parent_snap_id = m_parent_image_ctx->snap_id;
163 m_pspec = {m_parent_io_ctx.get_id(), m_parent_io_ctx.get_namespace(),
164 m_parent_image_id, m_parent_snap_id};
165 validate_parent();
166}
167
168template <typename I>
169void CloneRequest<I>::validate_parent() {
170 ldout(m_cct, 20) << dendl;
171
172 if (m_parent_image_ctx->operations_disabled) {
173 lderr(m_cct) << "image operations disabled due to unsupported op features"
174 << dendl;
175 m_r_saved = -EROFS;
176 close_parent();
177 return;
178 }
179
180 if (m_parent_image_ctx->snap_id == CEPH_NOSNAP) {
7c673cae 181 lderr(m_cct) << "image to be cloned must be a snapshot" << dendl;
11fdf7f2
TL
182 m_r_saved = -EINVAL;
183 close_parent();
184 return;
7c673cae
FG
185 }
186
11fdf7f2 187 if (m_parent_image_ctx->old_format) {
7c673cae 188 lderr(m_cct) << "parent image must be in new format" << dendl;
11fdf7f2
TL
189 m_r_saved = -EINVAL;
190 close_parent();
191 return;
7c673cae
FG
192 }
193
11fdf7f2
TL
194 m_parent_image_ctx->snap_lock.get_read();
195 uint64_t p_features = m_parent_image_ctx->features;
196 m_size = m_parent_image_ctx->get_image_size(m_parent_image_ctx->snap_id);
197
7c673cae 198 bool snap_protected;
11fdf7f2
TL
199 int r = m_parent_image_ctx->is_snap_protected(m_parent_image_ctx->snap_id, &snap_protected);
200 m_parent_image_ctx->snap_lock.put_read();
7c673cae 201
11fdf7f2 202 if ((p_features & RBD_FEATURE_LAYERING) != RBD_FEATURE_LAYERING) {
7c673cae 203 lderr(m_cct) << "parent image must support layering" << dendl;
11fdf7f2
TL
204 m_r_saved = -ENOSYS;
205 close_parent();
206 return;
207 }
208 if (m_use_p_features) {
209 m_features = (p_features & ~RBD_FEATURES_IMPLICIT_ENABLE);
7c673cae
FG
210 }
211
212 if (r < 0) {
213 lderr(m_cct) << "unable to locate parent's snapshot" << dendl;
11fdf7f2
TL
214 m_r_saved = r;
215 close_parent();
216 return;
7c673cae
FG
217 }
218
11fdf7f2 219 if (m_clone_format == 1 && !snap_protected) {
7c673cae 220 lderr(m_cct) << "parent snapshot must be protected" << dendl;
11fdf7f2
TL
221 m_r_saved = -EINVAL;
222 close_parent();
7c673cae
FG
223 return;
224 }
225
11fdf7f2 226 validate_child();
7c673cae
FG
227}
228
229template <typename I>
11fdf7f2
TL
230void CloneRequest<I>::validate_child() {
231 ldout(m_cct, 15) << dendl;
7c673cae 232
11fdf7f2
TL
233 if ((m_features & RBD_FEATURE_LAYERING) != RBD_FEATURE_LAYERING) {
234 lderr(m_cct) << "cloning image must support layering" << dendl;
235 m_r_saved = -ENOSYS;
236 close_parent();
237 return;
7c673cae
FG
238 }
239
7c673cae 240 using klass = CloneRequest<I>;
11fdf7f2
TL
241 librados::AioCompletion *comp = create_rados_callback<
242 klass, &klass::handle_validate_child>(this);
7c673cae
FG
243
244 librados::ObjectReadOperation op;
245 op.stat(NULL, NULL, NULL);
246
11fdf7f2
TL
247 int r = m_ioctx.aio_operate(util::old_header_name(m_name), comp, &op,
248 &m_out_bl);
249 ceph_assert(r == 0);
7c673cae
FG
250 comp->release();
251}
252
253template <typename I>
254void CloneRequest<I>::handle_validate_child(int r) {
11fdf7f2 255 ldout(m_cct, 15) << "r=" << r << dendl;
7c673cae
FG
256
257 if (r != -ENOENT) {
258 lderr(m_cct) << "rbd image " << m_name << " already exists" << dendl;
11fdf7f2
TL
259 m_r_saved = r;
260 close_parent();
261 return;
7c673cae
FG
262 }
263
11fdf7f2 264 create_child();
7c673cae
FG
265}
266
267template <typename I>
11fdf7f2
TL
268void CloneRequest<I>::create_child() {
269 ldout(m_cct, 15) << dendl;
7c673cae 270
11fdf7f2 271 uint64_t order = m_parent_image_ctx->order;
7c673cae
FG
272 if (m_opts.get(RBD_IMAGE_OPTION_ORDER, &order) != 0) {
273 m_opts.set(RBD_IMAGE_OPTION_ORDER, order);
274 }
7c673cae
FG
275 m_opts.set(RBD_IMAGE_OPTION_FEATURES, m_features);
276
277 using klass = CloneRequest<I>;
11fdf7f2
TL
278 Context *ctx = create_context_callback<
279 klass, &klass::handle_create_child>(this);
7c673cae 280
11fdf7f2 281 RWLock::RLocker snap_locker(m_parent_image_ctx->snap_lock);
7c673cae 282 CreateRequest<I> *req = CreateRequest<I>::create(
11fdf7f2
TL
283 m_config, m_ioctx, m_name, m_id, m_size, m_opts,
284 m_non_primary_global_image_id, m_primary_mirror_uuid, true,
285 m_op_work_queue, ctx);
7c673cae
FG
286 req->send();
287}
288
289template <typename I>
11fdf7f2
TL
290void CloneRequest<I>::handle_create_child(int r) {
291 ldout(m_cct, 15) << "r=" << r << dendl;
7c673cae 292
11fdf7f2
TL
293 if (r == -EBADF) {
294 ldout(m_cct, 5) << "image id already in-use" << dendl;
295 complete(r);
296 return;
297 } else if (r < 0) {
7c673cae 298 lderr(m_cct) << "error creating child: " << cpp_strerror(r) << dendl;
11fdf7f2
TL
299 m_r_saved = r;
300 close_parent();
301 return;
7c673cae 302 }
11fdf7f2 303 open_child();
7c673cae
FG
304}
305
306template <typename I>
11fdf7f2
TL
307void CloneRequest<I>::open_child() {
308 ldout(m_cct, 15) << dendl;
7c673cae 309
11fdf7f2 310 m_imctx = I::create(m_name, "", nullptr, m_ioctx, false);
7c673cae
FG
311
312 using klass = CloneRequest<I>;
11fdf7f2
TL
313 Context *ctx = create_context_callback<
314 klass, &klass::handle_open_child>(this);
7c673cae 315
11fdf7f2
TL
316 uint64_t flags = OPEN_FLAG_SKIP_OPEN_PARENT;
317 if ((m_features & RBD_FEATURE_MIGRATING) != 0) {
318 flags |= OPEN_FLAG_IGNORE_MIGRATING;
7c673cae
FG
319 }
320
11fdf7f2 321 m_imctx->state->open(flags, ctx);
7c673cae
FG
322}
323
324template <typename I>
11fdf7f2
TL
325void CloneRequest<I>::handle_open_child(int r) {
326 ldout(m_cct, 15) << "r=" << r << dendl;
7c673cae
FG
327
328 if (r < 0) {
11fdf7f2
TL
329 m_imctx->destroy();
330 m_imctx = nullptr;
331
332 lderr(m_cct) << "Error opening new image: " << cpp_strerror(r) << dendl;
7c673cae 333 m_r_saved = r;
11fdf7f2
TL
334 remove_child();
335 return;
7c673cae
FG
336 }
337
11fdf7f2 338 attach_parent();
7c673cae
FG
339}
340
341template <typename I>
11fdf7f2
TL
342void CloneRequest<I>::attach_parent() {
343 ldout(m_cct, 15) << dendl;
7c673cae 344
11fdf7f2
TL
345 auto ctx = create_context_callback<
346 CloneRequest<I>, &CloneRequest<I>::handle_attach_parent>(this);
347 auto req = AttachParentRequest<I>::create(
348 *m_imctx, m_pspec, m_size, false, ctx);
349 req->send();
7c673cae
FG
350}
351
352template <typename I>
11fdf7f2
TL
353void CloneRequest<I>::handle_attach_parent(int r) {
354 ldout(m_cct, 15) << "r=" << r << dendl;
7c673cae
FG
355
356 if (r < 0) {
11fdf7f2 357 lderr(m_cct) << "failed to attach parent: " << cpp_strerror(r) << dendl;
7c673cae 358 m_r_saved = r;
11fdf7f2
TL
359 close_child();
360 return;
7c673cae
FG
361 }
362
11fdf7f2 363 attach_child();
7c673cae
FG
364}
365
366template <typename I>
11fdf7f2
TL
367void CloneRequest<I>::attach_child() {
368 ldout(m_cct, 15) << dendl;
7c673cae 369
11fdf7f2
TL
370 auto ctx = create_context_callback<
371 CloneRequest<I>, &CloneRequest<I>::handle_attach_child>(this);
372 auto req = AttachChildRequest<I>::create(
373 m_imctx, m_parent_image_ctx, m_parent_image_ctx->snap_id, nullptr, 0,
374 m_clone_format, ctx);
7c673cae
FG
375 req->send();
376}
377
378template <typename I>
11fdf7f2
TL
379void CloneRequest<I>::handle_attach_child(int r) {
380 ldout(m_cct, 15) << "r=" << r << dendl;
7c673cae 381
11fdf7f2
TL
382 if (r < 0) {
383 lderr(m_cct) << "failed to attach parent: " << cpp_strerror(r) << dendl;
384 m_r_saved = r;
385 close_child();
386 return;
7c673cae
FG
387 }
388
11fdf7f2 389 metadata_list();
7c673cae
FG
390}
391
392template <typename I>
11fdf7f2
TL
393void CloneRequest<I>::metadata_list() {
394 ldout(m_cct, 15) << "start_key=" << m_last_metadata_key << dendl;
7c673cae
FG
395
396 librados::ObjectReadOperation op;
b32b8144 397 cls_client::metadata_list_start(&op, m_last_metadata_key, 0);
7c673cae
FG
398
399 using klass = CloneRequest<I>;
400 librados::AioCompletion *comp =
401 create_rados_callback<klass, &klass::handle_metadata_list>(this);
402 m_out_bl.clear();
11fdf7f2 403 m_parent_image_ctx->md_ctx.aio_operate(m_parent_image_ctx->header_oid,
7c673cae
FG
404 comp, &op, &m_out_bl);
405 comp->release();
406}
407
408template <typename I>
409void CloneRequest<I>::handle_metadata_list(int r) {
11fdf7f2 410 ldout(m_cct, 15) << "r=" << r << dendl;
7c673cae 411
b32b8144 412 map<string, bufferlist> metadata;
7c673cae 413 if (r == 0) {
11fdf7f2 414 auto it = m_out_bl.cbegin();
b32b8144 415 r = cls_client::metadata_list_finish(&it, &metadata);
7c673cae
FG
416 }
417
b32b8144
FG
418 if (r < 0) {
419 if (r == -EOPNOTSUPP || r == -EIO) {
420 ldout(m_cct, 10) << "config metadata not supported by OSD" << dendl;
421 get_mirror_mode();
422 } else {
423 lderr(m_cct) << "couldn't list metadata: " << cpp_strerror(r) << dendl;
424 m_r_saved = r;
11fdf7f2 425 close_child();
b32b8144 426 }
b32b8144
FG
427 return;
428 }
429
430 if (!metadata.empty()) {
431 m_pairs.insert(metadata.begin(), metadata.end());
432 m_last_metadata_key = m_pairs.rbegin()->first;
433 }
434
435 if (metadata.size() == MAX_KEYS) {
11fdf7f2 436 metadata_list();
7c673cae 437 } else {
11fdf7f2 438 metadata_set();
7c673cae
FG
439 }
440}
441
442template <typename I>
11fdf7f2
TL
443void CloneRequest<I>::metadata_set() {
444 if (m_pairs.empty()) {
445 get_mirror_mode();
446 return;
447 }
448
449 ldout(m_cct, 15) << dendl;
7c673cae
FG
450
451 librados::ObjectWriteOperation op;
452 cls_client::metadata_set(&op, m_pairs);
453
454 using klass = CloneRequest<I>;
455 librados::AioCompletion *comp =
456 create_rados_callback<klass, &klass::handle_metadata_set>(this);
457 int r = m_ioctx.aio_operate(m_imctx->header_oid, comp, &op);
11fdf7f2 458 ceph_assert(r == 0);
7c673cae
FG
459 comp->release();
460}
461
462template <typename I>
463void CloneRequest<I>::handle_metadata_set(int r) {
11fdf7f2 464 ldout(m_cct, 15) << "r=" << r << dendl;
7c673cae
FG
465
466 if (r < 0) {
467 lderr(m_cct) << "couldn't set metadata: " << cpp_strerror(r) << dendl;
468 m_r_saved = r;
11fdf7f2 469 close_child();
7c673cae
FG
470 } else {
471 get_mirror_mode();
472 }
473}
474
475template <typename I>
476void CloneRequest<I>::get_mirror_mode() {
11fdf7f2 477 ldout(m_cct, 15) << dendl;
7c673cae
FG
478
479 if (!m_imctx->test_features(RBD_FEATURE_JOURNALING)) {
11fdf7f2 480 close_child();
7c673cae
FG
481 return;
482 }
483
484 librados::ObjectReadOperation op;
485 cls_client::mirror_mode_get_start(&op);
486
487 using klass = CloneRequest<I>;
488 librados::AioCompletion *comp =
489 create_rados_callback<klass, &klass::handle_get_mirror_mode>(this);
490 m_out_bl.clear();
491 m_imctx->md_ctx.aio_operate(RBD_MIRRORING,
492 comp, &op, &m_out_bl);
493 comp->release();
494}
495
496template <typename I>
497void CloneRequest<I>::handle_get_mirror_mode(int r) {
11fdf7f2 498 ldout(m_cct, 15) << "r=" << r << dendl;
7c673cae
FG
499
500 if (r == 0) {
11fdf7f2 501 auto it = m_out_bl.cbegin();
7c673cae
FG
502 r = cls_client::mirror_mode_get_finish(&it, &m_mirror_mode);
503 }
504
505 if (r < 0 && r != -ENOENT) {
c07f9fc5
FG
506 lderr(m_cct) << "failed to retrieve mirror mode: " << cpp_strerror(r)
507 << dendl;
508
7c673cae 509 m_r_saved = r;
11fdf7f2 510 close_child();
7c673cae
FG
511 } else {
512 if (m_mirror_mode == cls::rbd::MIRROR_MODE_POOL ||
513 !m_non_primary_global_image_id.empty()) {
11fdf7f2 514 enable_mirror();
7c673cae 515 } else {
11fdf7f2 516 close_child();
7c673cae
FG
517 }
518 }
519}
520
521template <typename I>
11fdf7f2
TL
522void CloneRequest<I>::enable_mirror() {
523 ldout(m_cct, 15) << dendl;
7c673cae
FG
524
525 using klass = CloneRequest<I>;
11fdf7f2
TL
526 Context *ctx = create_context_callback<
527 klass, &klass::handle_enable_mirror>(this);
7c673cae
FG
528
529 mirror::EnableRequest<I> *req = mirror::EnableRequest<I>::create(
530 m_imctx->md_ctx, m_id, m_non_primary_global_image_id,
531 m_imctx->op_work_queue, ctx);
532 req->send();
533}
534
535template <typename I>
536void CloneRequest<I>::handle_enable_mirror(int r) {
11fdf7f2 537 ldout(m_cct, 15) << "r=" << r << dendl;
7c673cae
FG
538
539 if (r < 0) {
540 lderr(m_cct) << "failed to enable mirroring: " << cpp_strerror(r)
541 << dendl;
542 m_r_saved = r;
7c673cae 543 }
11fdf7f2 544 close_child();
7c673cae
FG
545}
546
547template <typename I>
11fdf7f2
TL
548void CloneRequest<I>::close_child() {
549 ldout(m_cct, 15) << dendl;
7c673cae 550
11fdf7f2 551 ceph_assert(m_imctx != nullptr);
7c673cae
FG
552
553 using klass = CloneRequest<I>;
554 Context *ctx = create_async_context_callback(
555 *m_imctx, create_context_callback<
11fdf7f2 556 klass, &klass::handle_close_child>(this));
7c673cae
FG
557 m_imctx->state->close(ctx);
558}
559
560template <typename I>
11fdf7f2
TL
561void CloneRequest<I>::handle_close_child(int r) {
562 ldout(m_cct, 15) << dendl;
7c673cae
FG
563
564 m_imctx->destroy();
565 m_imctx = nullptr;
566
567 if (r < 0) {
568 lderr(m_cct) << "couldn't close image: " << cpp_strerror(r) << dendl;
11fdf7f2
TL
569 if (m_r_saved == 0) {
570 m_r_saved = r;
571 }
7c673cae
FG
572 }
573
11fdf7f2
TL
574 if (m_r_saved < 0) {
575 remove_child();
576 return;
7c673cae 577 }
11fdf7f2
TL
578
579 close_parent();
7c673cae
FG
580}
581
582template <typename I>
11fdf7f2
TL
583void CloneRequest<I>::remove_child() {
584 ldout(m_cct, 15) << dendl;
7c673cae
FG
585
586 using klass = CloneRequest<I>;
11fdf7f2
TL
587 Context *ctx = create_context_callback<
588 klass, &klass::handle_remove_child>(this);
589
590 auto req = librbd::image::RemoveRequest<I>::create(
591 m_ioctx, m_name, m_id, false, false, m_no_op, m_op_work_queue, ctx);
592 req->send();
7c673cae
FG
593}
594
595template <typename I>
596void CloneRequest<I>::handle_remove_child(int r) {
11fdf7f2 597 ldout(m_cct, 15) << "r=" << r << dendl;
7c673cae
FG
598
599 if (r < 0) {
11fdf7f2
TL
600 lderr(m_cct) << "Error removing failed clone: "
601 << cpp_strerror(r) << dendl;
7c673cae
FG
602 }
603
11fdf7f2 604 close_parent();
7c673cae
FG
605}
606
607template <typename I>
11fdf7f2
TL
608void CloneRequest<I>::close_parent() {
609 ldout(m_cct, 20) << dendl;
610 ceph_assert(m_parent_image_ctx != nullptr);
7c673cae 611
11fdf7f2
TL
612 Context *ctx = create_async_context_callback(
613 *m_parent_image_ctx, create_context_callback<
614 CloneRequest<I>, &CloneRequest<I>::handle_close_parent>(this));
615 m_parent_image_ctx->state->close(ctx);
7c673cae
FG
616}
617
618template <typename I>
11fdf7f2
TL
619void CloneRequest<I>::handle_close_parent(int r) {
620 ldout(m_cct, 20) << "r=" << r << dendl;
621
622 m_parent_image_ctx->destroy();
623 m_parent_image_ctx = nullptr;
7c673cae
FG
624
625 if (r < 0) {
11fdf7f2 626 lderr(m_cct) << "failed to close parent image: "
7c673cae 627 << cpp_strerror(r) << dendl;
11fdf7f2
TL
628 if (m_r_saved == 0) {
629 m_r_saved = r;
630 }
7c673cae 631 }
11fdf7f2
TL
632
633 complete(m_r_saved);
7c673cae
FG
634}
635
636template <typename I>
637void CloneRequest<I>::complete(int r) {
11fdf7f2 638 ldout(m_cct, 15) << "r=" << r << dendl;
7c673cae
FG
639
640 m_on_finish->complete(r);
641 delete this;
642}
643
644} //namespace image
645} //namespace librbd
646
647template class librbd::image::CloneRequest<librbd::ImageCtx>;