]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/image/RemoveRequest.cc
update sources to 12.2.8
[ceph.git] / ceph / src / librbd / image / RemoveRequest.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 "common/dout.h"
5#include "common/errno.h"
6#include "librbd/internal.h"
7#include "librbd/ImageState.h"
8#include "librbd/Journal.h"
9#include "librbd/ObjectMap.h"
10#include "librbd/ExclusiveLock.h"
11#include "librbd/MirroringWatcher.h"
1adf2230 12#include "librbd/journal/DisabledPolicy.h"
7c673cae
FG
13#include "librbd/journal/RemoveRequest.h"
14#include "librbd/image/RemoveRequest.h"
15#include "librbd/operation/TrimRequest.h"
16#include "librbd/mirror/DisableRequest.h"
17
18#define dout_subsys ceph_subsys_rbd
19#undef dout_prefix
20#define dout_prefix *_dout << "librbd::image::RemoveRequest: " << this << " " \
31f18b77 21 << __func__ << ": "
7c673cae
FG
22
23namespace librbd {
24namespace image {
25
26using librados::IoCtx;
27using util::create_context_callback;
28using util::create_async_context_callback;
29using util::create_rados_callback;
30
31template<typename I>
32RemoveRequest<I>::RemoveRequest(IoCtx &ioctx, const std::string &image_name,
33 const std::string &image_id, bool force,
34 bool from_trash_remove,
35 ProgressContext &prog_ctx,
36 ContextWQ *op_work_queue, Context *on_finish)
37 : m_ioctx(ioctx), m_image_name(image_name), m_image_id(image_id),
38 m_force(force), m_from_trash_remove(from_trash_remove),
39 m_prog_ctx(prog_ctx), m_op_work_queue(op_work_queue),
40 m_on_finish(on_finish) {
41 m_cct = reinterpret_cast<CephContext *>(m_ioctx.cct());
42
43 m_image_ctx = I::create((m_image_id.empty() ? m_image_name : std::string()),
44 m_image_id, nullptr, m_ioctx, false);
45}
46
47template<typename I>
48void RemoveRequest<I>::send() {
49 ldout(m_cct, 20) << dendl;
50
51 open_image();
52}
53
54template<typename I>
55void RemoveRequest<I>::open_image() {
56 ldout(m_cct, 20) << dendl;
57
58 using klass = RemoveRequest<I>;
59 Context *ctx = create_context_callback<klass, &klass::handle_open_image>(
60 this);
61
62 m_image_ctx->state->open(true, ctx);
63}
64
65template<typename I>
31f18b77
FG
66void RemoveRequest<I>::handle_open_image(int r) {
67 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae 68
31f18b77 69 if (r < 0) {
7c673cae
FG
70 m_image_ctx->destroy();
71 m_image_ctx = nullptr;
72
31f18b77
FG
73 if (r != -ENOENT) {
74 lderr(m_cct) << "error opening image: " << cpp_strerror(r) << dendl;
75 finish(r);
76 return;
7c673cae
FG
77 }
78
79 remove_image();
31f18b77 80 return;
7c673cae
FG
81 }
82
83 m_image_id = m_image_ctx->id;
84 m_image_name = m_image_ctx->name;
85 m_header_oid = m_image_ctx->header_oid;
86 m_old_format = m_image_ctx->old_format;
87 m_unknown_format = false;
88
89 check_exclusive_lock();
7c673cae
FG
90}
91
92template<typename I>
93void RemoveRequest<I>::check_exclusive_lock() {
94 ldout(m_cct, 20) << dendl;
95
96 if (m_image_ctx->exclusive_lock == nullptr) {
97 validate_image_removal();
98 } else {
99 acquire_exclusive_lock();
100 }
101}
102
103template<typename I>
104void RemoveRequest<I>::acquire_exclusive_lock() {
105 ldout(m_cct, 20) << dendl;
106
1adf2230
AA
107 // do not attempt to open the journal when removing the image in case
108 // it's corrupt
109 if (m_image_ctx->test_features(RBD_FEATURE_JOURNALING)) {
110 RWLock::WLocker snap_locker(m_image_ctx->snap_lock);
111 m_image_ctx->set_journal_policy(new journal::DisabledPolicy());
112 }
113
7c673cae
FG
114 using klass = RemoveRequest<I>;
115 if (m_force) {
116 Context *ctx = create_context_callback<
117 klass, &klass::handle_exclusive_lock_force>(this);
31f18b77
FG
118 m_exclusive_lock = m_image_ctx->exclusive_lock;
119 m_exclusive_lock->shut_down(ctx);
7c673cae
FG
120 } else {
121 Context *ctx = create_context_callback<
122 klass, &klass::handle_exclusive_lock>(this);
123 RWLock::WLocker owner_lock(m_image_ctx->owner_lock);
124 m_image_ctx->exclusive_lock->try_acquire_lock(ctx);
125 }
126}
127
128template<typename I>
31f18b77
FG
129void RemoveRequest<I>::handle_exclusive_lock_force(int r) {
130 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae 131
31f18b77
FG
132 delete m_exclusive_lock;
133 m_exclusive_lock = nullptr;
134
135 if (r < 0) {
7c673cae 136 lderr(m_cct) << "error shutting down exclusive lock: "
31f18b77
FG
137 << cpp_strerror(r) << dendl;
138 send_close_image(r);
139 return;
7c673cae
FG
140 }
141
142 assert(m_image_ctx->exclusive_lock == nullptr);
143 validate_image_removal();
7c673cae
FG
144}
145
146template<typename I>
31f18b77
FG
147void RemoveRequest<I>::handle_exclusive_lock(int r) {
148 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae 149
31f18b77 150 if (r < 0 || !m_image_ctx->exclusive_lock->is_lock_owner()) {
7c673cae
FG
151 lderr(m_cct) << "cannot obtain exclusive lock - not removing" << dendl;
152 send_close_image(-EBUSY);
31f18b77 153 return;
7c673cae
FG
154 }
155
156 validate_image_removal();
7c673cae
FG
157}
158
159template<typename I>
160void RemoveRequest<I>::validate_image_removal() {
161 ldout(m_cct, 20) << dendl;
162
163 check_image_snaps();
164}
165
166template<typename I>
167void RemoveRequest<I>::check_image_snaps() {
168 ldout(m_cct, 20) << dendl;
169
170 if (m_image_ctx->snaps.size()) {
171 lderr(m_cct) << "image has snapshots - not removing" << dendl;
172 send_close_image(-ENOTEMPTY);
173 return;
174 }
175
31f18b77 176 list_image_watchers();
7c673cae
FG
177}
178
179template<typename I>
31f18b77 180void RemoveRequest<I>::list_image_watchers() {
7c673cae
FG
181 ldout(m_cct, 20) << dendl;
182
183 librados::ObjectReadOperation op;
184 op.list_watchers(&m_watchers, &m_ret_val);
185
186 using klass = RemoveRequest<I>;
187 librados::AioCompletion *rados_completion =
31f18b77 188 create_rados_callback<klass, &klass::handle_list_image_watchers>(this);
7c673cae
FG
189
190 int r = m_image_ctx->md_ctx.aio_operate(m_header_oid, rados_completion,
191 &op, &m_out_bl);
192 assert(r == 0);
193 rados_completion->release();
194}
195
196template<typename I>
31f18b77
FG
197void RemoveRequest<I>::handle_list_image_watchers(int r) {
198 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae 199
31f18b77
FG
200 if (r == 0 && m_ret_val < 0) {
201 r = m_ret_val;
7c673cae 202 }
7c673cae 203 if (r < 0) {
31f18b77
FG
204 lderr(m_cct) << "error listing image watchers: " << cpp_strerror(r)
205 << dendl;
206 send_close_image(r);
7c673cae
FG
207 return;
208 }
209
31f18b77
FG
210 get_mirror_image();
211}
212
213template<typename I>
214void RemoveRequest<I>::get_mirror_image() {
215 ldout(m_cct, 20) << dendl;
216 if ((m_watchers.empty()) ||
217 ((m_image_ctx->features & RBD_FEATURE_JOURNALING) == 0)) {
218 check_image_watchers();
7c673cae
FG
219 return;
220 }
221
31f18b77
FG
222 librados::ObjectReadOperation op;
223 cls_client::mirror_image_get_start(&op, m_image_id);
224
225 using klass = RemoveRequest<I>;
226 librados::AioCompletion *comp =
227 create_rados_callback<klass, &klass::handle_get_mirror_image>(this);
228 m_out_bl.clear();
229 int r = m_image_ctx->md_ctx.aio_operate(RBD_MIRRORING, comp, &op, &m_out_bl);
230 assert(r == 0);
231 comp->release();
232}
233
234template<typename I>
235void RemoveRequest<I>::handle_get_mirror_image(int r) {
236 ldout(m_cct, 20) << "r=" << r << dendl;
237
238 if (r == -ENOENT || r == -EOPNOTSUPP) {
239 check_image_watchers();
7c673cae 240 return;
31f18b77
FG
241 } else if (r < 0) {
242 ldout(m_cct, 5) << "error retrieving mirror image: " << cpp_strerror(r)
243 << dendl;
7c673cae 244 }
31f18b77
FG
245
246 list_mirror_watchers();
7c673cae
FG
247}
248
249template<typename I>
31f18b77
FG
250void RemoveRequest<I>::list_mirror_watchers() {
251 ldout(m_cct, 20) << dendl;
7c673cae 252
31f18b77
FG
253 librados::ObjectReadOperation op;
254 op.list_watchers(&m_mirror_watchers, &m_ret_val);
255
256 using klass = RemoveRequest<I>;
257 librados::AioCompletion *rados_completion =
258 create_rados_callback<klass, &klass::handle_list_mirror_watchers>(this);
259 m_out_bl.clear();
260 int r = m_image_ctx->md_ctx.aio_operate(RBD_MIRRORING, rados_completion,
261 &op, &m_out_bl);
262 assert(r == 0);
263 rados_completion->release();
264}
265
266template<typename I>
267void RemoveRequest<I>::handle_list_mirror_watchers(int r) {
268 ldout(m_cct, 20) << "r=" << r << dendl;
269
270 if (r == 0 && m_ret_val < 0) {
271 r = m_ret_val;
272 }
273 if (r < 0 && r != -ENOENT) {
274 ldout(m_cct, 5) << "error listing mirror watchers: " << cpp_strerror(r)
275 << dendl;
276 }
277
278 for (auto &watcher : m_mirror_watchers) {
279 m_watchers.remove_if([watcher] (obj_watch_t &w) {
280 return (strncmp(w.addr, watcher.addr, sizeof(w.addr)) == 0);
281 });
7c673cae
FG
282 }
283
31f18b77
FG
284 check_image_watchers();
285}
7c673cae 286
31f18b77
FG
287template<typename I>
288void RemoveRequest<I>::check_image_watchers() {
7c673cae
FG
289 if (m_watchers.size() > 1) {
290 lderr(m_cct) << "image has watchers - not removing" << dendl;
291 send_close_image(-EBUSY);
31f18b77 292 return;
7c673cae
FG
293 }
294
31f18b77 295 check_group();
7c673cae
FG
296}
297
298template<typename I>
31f18b77 299void RemoveRequest<I>::check_group() {
7c673cae
FG
300 ldout(m_cct, 20) << dendl;
301
302 librados::ObjectReadOperation op;
303 librbd::cls_client::image_get_group_start(&op);
304
305 using klass = RemoveRequest<I>;
306 librados::AioCompletion *rados_completion = create_rados_callback<
31f18b77 307 klass, &klass::handle_check_group>(this);
7c673cae
FG
308 m_out_bl.clear();
309 int r = m_image_ctx->md_ctx.aio_operate(m_header_oid, rados_completion, &op,
310 &m_out_bl);
311 assert(r == 0);
312 rados_completion->release();
313}
314
315template<typename I>
31f18b77
FG
316void RemoveRequest<I>::handle_check_group(int r) {
317 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae
FG
318
319 cls::rbd::GroupSpec s;
31f18b77
FG
320 if (r == 0) {
321 bufferlist::iterator it = m_out_bl.begin();
322 r = librbd::cls_client::image_get_group_finish(&it, &s);
323 }
324 if (r < 0 && r != -EOPNOTSUPP) {
325 lderr(m_cct) << "error fetching group for image: "
326 << cpp_strerror(r) << dendl;
327 send_close_image(r);
328 return;
7c673cae 329 }
31f18b77 330
7c673cae
FG
331 if (s.is_valid()) {
332 lderr(m_cct) << "image is in a group - not removing" << dendl;
333 send_close_image(-EMLINK);
31f18b77 334 return;
7c673cae
FG
335 }
336
337 trim_image();
7c673cae
FG
338}
339
340template<typename I>
341void RemoveRequest<I>::trim_image() {
342 ldout(m_cct, 20) << dendl;
343
344 using klass = RemoveRequest<I>;
345 Context *ctx = create_async_context_callback(
346 *m_image_ctx, create_context_callback<
347 klass, &klass::handle_trim_image>(this));
348
349 RWLock::RLocker owner_lock(m_image_ctx->owner_lock);
350 auto req = librbd::operation::TrimRequest<I>::create(
351 *m_image_ctx, ctx, m_image_ctx->size, 0, m_prog_ctx);
352 req->send();
353}
354
355template<typename I>
31f18b77
FG
356void RemoveRequest<I>::handle_trim_image(int r) {
357 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae 358
31f18b77 359 if (r < 0) {
7c673cae 360 lderr(m_cct) << "warning: failed to remove some object(s): "
31f18b77 361 << cpp_strerror(r) << dendl;
7c673cae
FG
362 }
363
364 if (m_old_format) {
31f18b77
FG
365 send_close_image(r);
366 return;
7c673cae
FG
367 }
368
369 remove_child();
7c673cae
FG
370}
371
372template<typename I>
373void RemoveRequest<I>::remove_child() {
374 ldout(m_cct, 20) << dendl;
375
376 m_image_ctx->parent_lock.get_read();
377 ParentInfo parent_info = m_image_ctx->parent_md;
378 m_image_ctx->parent_lock.put_read();
379
380 librados::ObjectWriteOperation op;
381 librbd::cls_client::remove_child(&op, parent_info.spec, m_image_id);
382
383 using klass = RemoveRequest<I>;
384 librados::AioCompletion *rados_completion =
385 create_rados_callback<klass, &klass::handle_remove_child>(this);
386 int r = m_image_ctx->md_ctx.aio_operate(RBD_CHILDREN, rados_completion, &op);
387 assert(r == 0);
388 rados_completion->release();
389}
390
391template<typename I>
31f18b77
FG
392void RemoveRequest<I>::handle_remove_child(int r) {
393 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae 394
31f18b77
FG
395 if (r == -ENOENT) {
396 r = 0;
397 } else if (r < 0) {
7c673cae 398 lderr(m_cct) << "error removing child from children list: "
31f18b77
FG
399 << cpp_strerror(r) << dendl;
400 send_close_image(r);
401 return;
7c673cae
FG
402 }
403
404
405 send_disable_mirror();
7c673cae
FG
406}
407
408template<typename I>
409void RemoveRequest<I>::send_disable_mirror() {
410 ldout(m_cct, 20) << dendl;
411
412 using klass = RemoveRequest<I>;
413 Context *ctx = create_context_callback<
414 klass, &klass::handle_disable_mirror>(this);
415
416 mirror::DisableRequest<I> *req =
417 mirror::DisableRequest<I>::create(m_image_ctx, m_force, !m_force, ctx);
418 req->send();
419}
420
421template<typename I>
31f18b77
FG
422void RemoveRequest<I>::handle_disable_mirror(int r) {
423 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae 424
31f18b77
FG
425 if (r == -EOPNOTSUPP) {
426 r = 0;
427 } else if (r < 0) {
7c673cae 428 lderr(m_cct) << "error disabling image mirroring: "
31f18b77 429 << cpp_strerror(r) << dendl;
7c673cae
FG
430 }
431
31f18b77 432 send_close_image(r);
7c673cae
FG
433}
434
435template<typename I>
436void RemoveRequest<I>::send_close_image(int r) {
437 ldout(m_cct, 20) << dendl;
438
439 m_ret_val = r;
440 using klass = RemoveRequest<I>;
441 Context *ctx = create_context_callback<
442 klass, &klass::handle_send_close_image>(this);
443
444 m_image_ctx->state->close(ctx);
445}
446
447template<typename I>
31f18b77
FG
448void RemoveRequest<I>::handle_send_close_image(int r) {
449 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae 450
31f18b77 451 if (r < 0) {
7c673cae 452 lderr(m_cct) << "error encountered while closing image: "
31f18b77 453 << cpp_strerror(r) << dendl;
7c673cae
FG
454 }
455
456 m_image_ctx->destroy();
457 m_image_ctx = nullptr;
458 if (m_ret_val < 0) {
31f18b77
FG
459 r = m_ret_val;
460 finish(r);
461 return;
7c673cae
FG
462 }
463
464 remove_header();
7c673cae
FG
465}
466
467template<typename I>
468void RemoveRequest<I>::remove_header() {
469 ldout(m_cct, 20) << dendl;
470
471 using klass = RemoveRequest<I>;
472 librados::AioCompletion *rados_completion =
473 create_rados_callback<klass, &klass::handle_remove_header>(this);
474 int r = m_ioctx.aio_remove(m_header_oid, rados_completion);
475 assert(r == 0);
476 rados_completion->release();
477}
478
479template<typename I>
31f18b77
FG
480void RemoveRequest<I>::handle_remove_header(int r) {
481 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae 482
31f18b77
FG
483 if (r < 0 && r != -ENOENT) {
484 lderr(m_cct) << "error removing header: " << cpp_strerror(r) << dendl;
485 m_ret_val = r;
7c673cae
FG
486 }
487
488 remove_image();
7c673cae
FG
489}
490
491template<typename I>
492void RemoveRequest<I>::remove_header_v2() {
493 ldout(m_cct, 20) << dendl;
494
495 if (m_header_oid.empty()) {
496 m_header_oid = util::header_name(m_image_id);
497 }
498
499 using klass = RemoveRequest<I>;
500 librados::AioCompletion *rados_completion =
501 create_rados_callback<klass, &klass::handle_remove_header_v2>(this);
502 int r = m_ioctx.aio_remove(m_header_oid, rados_completion);
503 assert(r == 0);
504 rados_completion->release();
505}
506
507template<typename I>
31f18b77
FG
508void RemoveRequest<I>::handle_remove_header_v2(int r) {
509 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae 510
31f18b77
FG
511 if (r < 0 && r != -ENOENT) {
512 lderr(m_cct) << "error removing header: " << cpp_strerror(r) << dendl;
513 finish(r);
514 return;
7c673cae
FG
515 }
516
517 send_journal_remove();
7c673cae
FG
518}
519
520template<typename I>
521void RemoveRequest<I>::send_journal_remove() {
522 ldout(m_cct, 20) << dendl;
523
524 using klass = RemoveRequest<I>;
525 Context *ctx = create_context_callback<
526 klass, &klass::handle_journal_remove>(this);
527
528 journal::RemoveRequest<I> *req = journal::RemoveRequest<I>::create(
529 m_ioctx, m_image_id, Journal<>::IMAGE_CLIENT_ID, m_op_work_queue, ctx);
530 req->send();
531}
532
533template<typename I>
31f18b77
FG
534void RemoveRequest<I>::handle_journal_remove(int r) {
535 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae 536
31f18b77
FG
537 if (r < 0 && r != -ENOENT) {
538 lderr(m_cct) << "failed to remove image journal: " << cpp_strerror(r)
7c673cae 539 << dendl;
31f18b77
FG
540 finish(r);
541 return;
7c673cae 542 } else {
31f18b77 543 r = 0;
7c673cae
FG
544 }
545
546 send_object_map_remove();
7c673cae
FG
547}
548
549template<typename I>
550void RemoveRequest<I>::send_object_map_remove() {
551 ldout(m_cct, 20) << dendl;
552
553 using klass = RemoveRequest<I>;
554 librados::AioCompletion *rados_completion =
555 create_rados_callback<klass, &klass::handle_object_map_remove>(this);
556
557 int r = ObjectMap<>::aio_remove(m_ioctx,
558 m_image_id,
559 rados_completion);
560 assert(r == 0);
561 rados_completion->release();
562}
563
564template<typename I>
31f18b77
FG
565void RemoveRequest<I>::handle_object_map_remove(int r) {
566 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae 567
31f18b77
FG
568 if (r < 0 && r != -ENOENT) {
569 lderr(m_cct) << "failed to remove image journal: " << cpp_strerror(r)
7c673cae 570 << dendl;
31f18b77
FG
571 finish(r);
572 return;
7c673cae 573 } else {
31f18b77 574 r = 0;
7c673cae
FG
575 }
576
577 mirror_image_remove();
7c673cae
FG
578}
579
580template<typename I>
581void RemoveRequest<I>::mirror_image_remove() {
582 ldout(m_cct, 20) << dendl;
583
584 librados::ObjectWriteOperation op;
585 cls_client::mirror_image_remove(&op, m_image_id);
586
587 using klass = RemoveRequest<I>;
588 librados::AioCompletion *rados_completion =
589 create_rados_callback<klass, &klass::handle_mirror_image_remove>(this);
590 int r = m_ioctx.aio_operate(RBD_MIRRORING, rados_completion, &op);
591 assert(r == 0);
592 rados_completion->release();
593}
594
595template<typename I>
31f18b77
FG
596void RemoveRequest<I>::handle_mirror_image_remove(int r) {
597 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae 598
31f18b77 599 if (r < 0 && r != -ENOENT && r != -EOPNOTSUPP) {
7c673cae 600 lderr(m_cct) << "failed to remove mirror image state: "
31f18b77
FG
601 << cpp_strerror(r) << dendl;
602 finish(r);
603 return;
7c673cae
FG
604 }
605
606 if (m_from_trash_remove) {
607 // both the id object and the directory entry have been removed in
608 // a previous call to trash_move.
31f18b77
FG
609 finish(0);
610 return;
7c673cae
FG
611 }
612
613 remove_id_object();
7c673cae
FG
614}
615
616template<typename I>
617void RemoveRequest<I>::remove_image() {
618 ldout(m_cct, 20) << dendl;
619
620 if (m_old_format || m_unknown_format) {
621 remove_v1_image();
622 } else {
623 remove_v2_image();
624 }
625}
626
627template<typename I>
628void RemoveRequest<I>::remove_v1_image() {
629 ldout(m_cct, 20) << dendl;
630
631 Context *ctx = new FunctionContext([this] (int r) {
632 r = tmap_rm(m_ioctx, m_image_name);
633 handle_remove_v1_image(r);
634 });
635
636 m_op_work_queue->queue(ctx, 0);
637}
638
639template<typename I>
640void RemoveRequest<I>::handle_remove_v1_image(int r) {
31f18b77 641 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae
FG
642
643 m_old_format = (r == 0);
31f18b77
FG
644 if (r == 0 || (r < 0 && !m_unknown_format)) {
645 if (r < 0 && r != -ENOENT) {
7c673cae
FG
646 lderr(m_cct) << "error removing image from v1 directory: "
647 << cpp_strerror(r) << dendl;
648 }
649
650 m_on_finish->complete(r);
651 delete this;
652 return;
653 }
654
655 if (!m_old_format) {
656 remove_v2_image();
657 }
658}
659
660template<typename I>
661void RemoveRequest<I>::remove_v2_image() {
662 ldout(m_cct, 20) << dendl;
663
664 if (m_image_id.empty()) {
665 dir_get_image_id();
666 return;
667 } else if (m_image_name.empty()) {
668 dir_get_image_name();
669 return;
670 }
671
672 remove_header_v2();
673 return;
674}
675
676template<typename I>
677void RemoveRequest<I>::dir_get_image_id() {
678 ldout(m_cct, 20) << dendl;
679
680 librados::ObjectReadOperation op;
681 librbd::cls_client::dir_get_id_start(&op, m_image_name);
682
683 using klass = RemoveRequest<I>;
684 librados::AioCompletion *rados_completion =
685 create_rados_callback<klass, &klass::handle_dir_get_image_id>(this);
686 m_out_bl.clear();
687 int r = m_ioctx.aio_operate(RBD_DIRECTORY, rados_completion, &op, &m_out_bl);
688 assert(r == 0);
689 rados_completion->release();
690}
691
692template<typename I>
31f18b77
FG
693void RemoveRequest<I>::handle_dir_get_image_id(int r) {
694 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae 695
31f18b77
FG
696 if (r < 0 && r != -ENOENT) {
697 lderr(m_cct) << "error fetching image id: " << cpp_strerror(r)
7c673cae 698 << dendl;
31f18b77
FG
699 finish(r);
700 return;
7c673cae
FG
701 }
702
31f18b77 703 if (r == 0) {
7c673cae 704 bufferlist::iterator iter = m_out_bl.begin();
31f18b77
FG
705 r = librbd::cls_client::dir_get_id_finish(&iter, &m_image_id);
706 if (r < 0) {
707 finish(r);
708 return;
7c673cae
FG
709 }
710 }
711
712 remove_header_v2();
7c673cae
FG
713}
714
715template<typename I>
716void RemoveRequest<I>::dir_get_image_name() {
717 ldout(m_cct, 20) << dendl;
718
719 librados::ObjectReadOperation op;
720 librbd::cls_client::dir_get_name_start(&op, m_image_id);
721
722 using klass = RemoveRequest<I>;
723 librados::AioCompletion *rados_completion =
724 create_rados_callback<klass, &klass::handle_dir_get_image_name>(this);
725 m_out_bl.clear();
726 int r = m_ioctx.aio_operate(RBD_DIRECTORY, rados_completion, &op, &m_out_bl);
727 assert(r == 0);
728 rados_completion->release();
729}
730
731template<typename I>
31f18b77
FG
732void RemoveRequest<I>::handle_dir_get_image_name(int r) {
733 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae 734
31f18b77
FG
735 if (r < 0 && r != -ENOENT) {
736 lderr(m_cct) << "error fetching image name: " << cpp_strerror(r)
7c673cae 737 << dendl;
31f18b77
FG
738 finish(r);
739 return;
7c673cae
FG
740 }
741
31f18b77 742 if (r == 0) {
7c673cae 743 bufferlist::iterator iter = m_out_bl.begin();
31f18b77
FG
744 r = librbd::cls_client::dir_get_name_finish(&iter, &m_image_name);
745 if (r < 0) {
746 finish(r);
747 return;
7c673cae
FG
748 }
749 }
750
751 remove_header_v2();
7c673cae
FG
752}
753
754template<typename I>
755void RemoveRequest<I>::remove_id_object() {
756 ldout(m_cct, 20) << dendl;
757
758 using klass = RemoveRequest<I>;
759 librados::AioCompletion *rados_completion =
760 create_rados_callback<klass, &klass::handle_remove_id_object>(this);
761 int r = m_ioctx.aio_remove(util::id_obj_name(m_image_name), rados_completion);
762 assert(r == 0);
763 rados_completion->release();
764}
765
766template<typename I>
31f18b77
FG
767void RemoveRequest<I>::handle_remove_id_object(int r) {
768 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae 769
31f18b77
FG
770 if (r < 0 && r != -ENOENT) {
771 lderr(m_cct) << "error removing id object: " << cpp_strerror(r)
7c673cae 772 << dendl;
31f18b77
FG
773 finish(r);
774 return;
7c673cae
FG
775 }
776
777 dir_remove_image();
7c673cae
FG
778}
779
780template<typename I>
781void RemoveRequest<I>::dir_remove_image() {
782 ldout(m_cct, 20) << dendl;
783
784 librados::ObjectWriteOperation op;
785 librbd::cls_client::dir_remove_image(&op, m_image_name, m_image_id);
786
787 using klass = RemoveRequest<I>;
788 librados::AioCompletion *rados_completion =
789 create_rados_callback<klass, &klass::handle_dir_remove_image>(this);
790 int r = m_ioctx.aio_operate(RBD_DIRECTORY, rados_completion, &op);
791 assert(r == 0);
792 rados_completion->release();
793}
794
795template<typename I>
31f18b77
FG
796void RemoveRequest<I>::handle_dir_remove_image(int r) {
797 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae 798
31f18b77 799 if (r < 0 && r != -ENOENT) {
7c673cae 800 lderr(m_cct) << "error removing image from v2 directory: "
31f18b77 801 << cpp_strerror(r) << dendl;
7c673cae
FG
802 }
803
31f18b77
FG
804 finish(r);
805}
806
807template<typename I>
808void RemoveRequest<I>::finish(int r) {
809 ldout(m_cct, 20) << "r=" << r << dendl;
810
811 m_on_finish->complete(r);
812 delete this;
7c673cae
FG
813}
814
815} // namespace image
816} // namespace librbd
817
818template class librbd::image::RemoveRequest<librbd::ImageCtx>;