1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "librbd/image/CreateRequest.h"
5 #include "include/ceph_assert.h"
6 #include "common/dout.h"
7 #include "common/errno.h"
8 #include "common/ceph_context.h"
9 #include "cls/rbd/cls_rbd_client.h"
10 #include "osdc/Striper.h"
11 #include "librbd/Features.h"
12 #include "librbd/Journal.h"
13 #include "librbd/ObjectMap.h"
14 #include "librbd/Utils.h"
15 #include "librbd/asio/ContextWQ.h"
16 #include "librbd/image/Types.h"
17 #include "librbd/image/ValidatePoolRequest.h"
18 #include "librbd/journal/CreateRequest.h"
19 #include "librbd/journal/RemoveRequest.h"
20 #include "librbd/journal/TypeTraits.h"
21 #include "librbd/mirror/EnableRequest.h"
22 #include "journal/Journaler.h"
25 #define dout_subsys ceph_subsys_rbd
27 #define dout_prefix *_dout << "librbd::image::CreateRequest: " << __func__ \
33 using util::create_rados_callback
;
34 using util::create_context_callback
;
38 int validate_features(CephContext
*cct
, uint64_t features
) {
39 if (features
& ~RBD_FEATURES_ALL
) {
40 lderr(cct
) << "librbd does not support requested features." << dendl
;
43 if ((features
& RBD_FEATURES_INTERNAL
) != 0) {
44 lderr(cct
) << "cannot use internally controlled features" << dendl
;
47 if ((features
& RBD_FEATURE_FAST_DIFF
) != 0 &&
48 (features
& RBD_FEATURE_OBJECT_MAP
) == 0) {
49 lderr(cct
) << "cannot use fast diff without object map" << dendl
;
52 if ((features
& RBD_FEATURE_OBJECT_MAP
) != 0 &&
53 (features
& RBD_FEATURE_EXCLUSIVE_LOCK
) == 0) {
54 lderr(cct
) << "cannot use object map without exclusive lock" << dendl
;
57 if ((features
& RBD_FEATURE_JOURNALING
) != 0 &&
58 (features
& RBD_FEATURE_EXCLUSIVE_LOCK
) == 0) {
59 lderr(cct
) << "cannot use journaling without exclusive lock" << dendl
;
66 int validate_striping(CephContext
*cct
, uint8_t order
, uint64_t stripe_unit
,
67 uint64_t stripe_count
) {
68 if ((stripe_unit
&& !stripe_count
) ||
69 (!stripe_unit
&& stripe_count
)) {
70 lderr(cct
) << "must specify both (or neither) of stripe-unit and "
71 << "stripe-count" << dendl
;
73 } else if (stripe_unit
&& ((1ull << order
) % stripe_unit
|| stripe_unit
> (1ull << order
))) {
74 lderr(cct
) << "stripe unit is not a factor of the object size" << dendl
;
76 } else if (stripe_unit
!= 0 && stripe_unit
< 512) {
77 lderr(cct
) << "stripe unit must be at least 512 bytes" << dendl
;
83 bool validate_layout(CephContext
*cct
, uint64_t size
, file_layout_t
&layout
) {
84 if (!librbd::ObjectMap
<>::is_compatible(layout
, size
)) {
85 lderr(cct
) << "image size not compatible with object map" << dendl
;
92 int get_image_option(const ImageOptions
&image_options
, int option
,
95 int r
= image_options
.get(option
, &large_value
);
99 *value
= static_cast<uint8_t>(large_value
);
103 } // anonymous namespace
106 int CreateRequest
<I
>::validate_order(CephContext
*cct
, uint8_t order
) {
107 if (order
> 25 || order
< 12) {
108 lderr(cct
) << "order must be in the range [12, 25]" << dendl
;
115 #define dout_prefix *_dout << "librbd::image::CreateRequest: " << this << " " \
119 CreateRequest
<I
>::CreateRequest(const ConfigProxy
& config
, IoCtx
&ioctx
,
120 const std::string
&image_name
,
121 const std::string
&image_id
, uint64_t size
,
122 const ImageOptions
&image_options
,
123 uint32_t create_flags
,
124 cls::rbd::MirrorImageMode mirror_image_mode
,
125 const std::string
&non_primary_global_image_id
,
126 const std::string
&primary_mirror_uuid
,
127 asio::ContextWQ
*op_work_queue
,
129 : m_config(config
), m_image_name(image_name
), m_image_id(image_id
),
130 m_size(size
), m_create_flags(create_flags
),
131 m_mirror_image_mode(mirror_image_mode
),
132 m_non_primary_global_image_id(non_primary_global_image_id
),
133 m_primary_mirror_uuid(primary_mirror_uuid
),
134 m_op_work_queue(op_work_queue
), m_on_finish(on_finish
) {
137 m_cct
= reinterpret_cast<CephContext
*>(m_io_ctx
.cct());
139 m_id_obj
= util::id_obj_name(m_image_name
);
140 m_header_obj
= util::header_name(m_image_id
);
141 m_objmap_name
= ObjectMap
<>::object_map_name(m_image_id
, CEPH_NOSNAP
);
142 if (!non_primary_global_image_id
.empty() &&
143 (m_create_flags
& CREATE_FLAG_MIRROR_ENABLE_MASK
) == 0) {
144 m_create_flags
|= CREATE_FLAG_FORCE_MIRROR_ENABLE
;
147 if (image_options
.get(RBD_IMAGE_OPTION_FEATURES
, &m_features
) != 0) {
148 m_features
= librbd::rbd_features_from_string(
149 m_config
.get_val
<std::string
>("rbd_default_features"), nullptr);
150 m_negotiate_features
= true;
153 uint64_t features_clear
= 0;
154 uint64_t features_set
= 0;
155 image_options
.get(RBD_IMAGE_OPTION_FEATURES_CLEAR
, &features_clear
);
156 image_options
.get(RBD_IMAGE_OPTION_FEATURES_SET
, &features_set
);
158 uint64_t features_conflict
= features_clear
& features_set
;
159 features_clear
&= ~features_conflict
;
160 features_set
&= ~features_conflict
;
161 m_features
|= features_set
;
162 m_features
&= ~features_clear
;
164 m_features
&= ~RBD_FEATURES_IMPLICIT_ENABLE
;
165 if ((m_features
& RBD_FEATURE_OBJECT_MAP
) == RBD_FEATURE_OBJECT_MAP
) {
166 m_features
|= RBD_FEATURE_FAST_DIFF
;
169 if (image_options
.get(RBD_IMAGE_OPTION_STRIPE_UNIT
, &m_stripe_unit
) != 0 ||
170 m_stripe_unit
== 0) {
171 m_stripe_unit
= m_config
.get_val
<Option::size_t>("rbd_default_stripe_unit");
173 if (image_options
.get(RBD_IMAGE_OPTION_STRIPE_COUNT
, &m_stripe_count
) != 0 ||
174 m_stripe_count
== 0) {
175 m_stripe_count
= m_config
.get_val
<uint64_t>("rbd_default_stripe_count");
177 if (get_image_option(image_options
, RBD_IMAGE_OPTION_ORDER
, &m_order
) != 0 ||
179 m_order
= config
.get_val
<uint64_t>("rbd_default_order");
181 if (get_image_option(image_options
, RBD_IMAGE_OPTION_JOURNAL_ORDER
,
182 &m_journal_order
) != 0) {
183 m_journal_order
= m_config
.get_val
<uint64_t>("rbd_journal_order");
185 if (get_image_option(image_options
, RBD_IMAGE_OPTION_JOURNAL_SPLAY_WIDTH
,
186 &m_journal_splay_width
) != 0) {
187 m_journal_splay_width
= m_config
.get_val
<uint64_t>(
188 "rbd_journal_splay_width");
190 if (image_options
.get(RBD_IMAGE_OPTION_JOURNAL_POOL
, &m_journal_pool
) != 0) {
191 m_journal_pool
= m_config
.get_val
<std::string
>("rbd_journal_pool");
193 if (image_options
.get(RBD_IMAGE_OPTION_DATA_POOL
, &m_data_pool
) != 0) {
194 m_data_pool
= m_config
.get_val
<std::string
>("rbd_default_data_pool");
197 m_layout
.object_size
= 1ull << m_order
;
198 if (m_stripe_unit
== 0 || m_stripe_count
== 0) {
199 m_layout
.stripe_unit
= m_layout
.object_size
;
200 m_layout
.stripe_count
= 1;
202 m_layout
.stripe_unit
= m_stripe_unit
;
203 m_layout
.stripe_count
= m_stripe_count
;
206 if (!m_data_pool
.empty() && m_data_pool
!= ioctx
.get_pool_name()) {
207 m_features
|= RBD_FEATURE_DATA_POOL
;
212 if ((m_stripe_unit
!= 0 && m_stripe_unit
!= (1ULL << m_order
)) ||
213 (m_stripe_count
!= 0 && m_stripe_count
!= 1)) {
214 m_features
|= RBD_FEATURE_STRIPINGV2
;
217 ldout(m_cct
, 10) << "name=" << m_image_name
<< ", "
218 << "id=" << m_image_id
<< ", "
219 << "size=" << m_size
<< ", "
220 << "features=" << m_features
<< ", "
221 << "order=" << (uint64_t)m_order
<< ", "
222 << "stripe_unit=" << m_stripe_unit
<< ", "
223 << "stripe_count=" << m_stripe_count
<< ", "
224 << "journal_order=" << (uint64_t)m_journal_order
<< ", "
225 << "journal_splay_width="
226 << (uint64_t)m_journal_splay_width
<< ", "
227 << "journal_pool=" << m_journal_pool
<< ", "
228 << "data_pool=" << m_data_pool
<< dendl
;
232 void CreateRequest
<I
>::send() {
233 ldout(m_cct
, 20) << dendl
;
235 int r
= validate_features(m_cct
, m_features
);
241 r
= validate_order(m_cct
, m_order
);
247 r
= validate_striping(m_cct
, m_order
, m_stripe_unit
, m_stripe_count
);
253 if (((m_features
& RBD_FEATURE_OBJECT_MAP
) != 0) &&
254 (!validate_layout(m_cct
, m_size
, m_layout
))) {
259 validate_data_pool();
262 template <typename I
>
263 void CreateRequest
<I
>::validate_data_pool() {
264 m_data_io_ctx
= m_io_ctx
;
265 if ((m_features
& RBD_FEATURE_DATA_POOL
) != 0) {
266 librados::Rados
rados(m_io_ctx
);
267 int r
= rados
.ioctx_create(m_data_pool
.c_str(), m_data_io_ctx
);
269 lderr(m_cct
) << "data pool " << m_data_pool
<< " does not exist" << dendl
;
273 m_data_pool_id
= m_data_io_ctx
.get_id();
274 m_data_io_ctx
.set_namespace(m_io_ctx
.get_namespace());
277 if (!m_config
.get_val
<bool>("rbd_validate_pool")) {
278 add_image_to_directory();
282 ldout(m_cct
, 15) << dendl
;
284 auto ctx
= create_context_callback
<
285 CreateRequest
<I
>, &CreateRequest
<I
>::handle_validate_data_pool
>(this);
286 auto req
= ValidatePoolRequest
<I
>::create(m_data_io_ctx
, ctx
);
290 template <typename I
>
291 void CreateRequest
<I
>::handle_validate_data_pool(int r
) {
292 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
295 lderr(m_cct
) << "pool does not support RBD images" << dendl
;
299 lderr(m_cct
) << "failed to validate pool: " << cpp_strerror(r
) << dendl
;
304 add_image_to_directory();
308 void CreateRequest
<I
>::add_image_to_directory() {
309 ldout(m_cct
, 15) << dendl
;
311 librados::ObjectWriteOperation op
;
312 if (!m_io_ctx
.get_namespace().empty()) {
313 cls_client::dir_state_assert(&op
, cls::rbd::DIRECTORY_STATE_READY
);
315 cls_client::dir_add_image(&op
, m_image_name
, m_image_id
);
317 using klass
= CreateRequest
<I
>;
318 librados::AioCompletion
*comp
=
319 create_rados_callback
<klass
, &klass::handle_add_image_to_directory
>(this);
320 int r
= m_io_ctx
.aio_operate(RBD_DIRECTORY
, comp
, &op
);
326 void CreateRequest
<I
>::handle_add_image_to_directory(int r
) {
327 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
330 ldout(m_cct
, 5) << "directory entry for image " << m_image_name
331 << " already exists" << dendl
;
334 } else if (!m_io_ctx
.get_namespace().empty() && r
== -ENOENT
) {
335 ldout(m_cct
, 5) << "namespace " << m_io_ctx
.get_namespace()
336 << " does not exist" << dendl
;
340 lderr(m_cct
) << "error adding image to directory: " << cpp_strerror(r
)
350 void CreateRequest
<I
>::create_id_object() {
351 ldout(m_cct
, 15) << dendl
;
353 librados::ObjectWriteOperation op
;
355 cls_client::set_id(&op
, m_image_id
);
357 using klass
= CreateRequest
<I
>;
358 librados::AioCompletion
*comp
=
359 create_rados_callback
<klass
, &klass::handle_create_id_object
>(this);
360 int r
= m_io_ctx
.aio_operate(m_id_obj
, comp
, &op
);
366 void CreateRequest
<I
>::handle_create_id_object(int r
) {
367 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
370 ldout(m_cct
, 5) << "id object for " << m_image_name
<< " already exists"
376 lderr(m_cct
) << "error creating RBD id object: " << cpp_strerror(r
)
383 negotiate_features();
387 void CreateRequest
<I
>::negotiate_features() {
388 if (!m_negotiate_features
) {
393 ldout(m_cct
, 15) << dendl
;
395 librados::ObjectReadOperation op
;
396 cls_client::get_all_features_start(&op
);
398 using klass
= CreateRequest
<I
>;
399 librados::AioCompletion
*comp
=
400 create_rados_callback
<klass
, &klass::handle_negotiate_features
>(this);
403 int r
= m_io_ctx
.aio_operate(RBD_DIRECTORY
, comp
, &op
, &m_outbl
);
409 void CreateRequest
<I
>::handle_negotiate_features(int r
) {
410 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
412 uint64_t all_features
;
414 auto it
= m_outbl
.cbegin();
415 r
= cls_client::get_all_features_finish(&it
, &all_features
);
418 ldout(m_cct
, 10) << "error retrieving server supported features set: "
419 << cpp_strerror(r
) << dendl
;
420 } else if ((m_features
& all_features
) != m_features
) {
421 m_features
&= all_features
;
422 ldout(m_cct
, 10) << "limiting default features set to server supported: "
423 << m_features
<< dendl
;
430 void CreateRequest
<I
>::create_image() {
431 ldout(m_cct
, 15) << dendl
;
432 ceph_assert(m_data_pool
.empty() || m_data_pool_id
!= -1);
434 std::ostringstream oss
;
435 oss
<< RBD_DATA_PREFIX
;
436 if (m_data_pool_id
!= -1) {
437 oss
<< stringify(m_io_ctx
.get_id()) << ".";
440 if (oss
.str().length() > RBD_MAX_BLOCK_NAME_PREFIX_LENGTH
) {
441 lderr(m_cct
) << "object prefix '" << oss
.str() << "' too large" << dendl
;
447 librados::ObjectWriteOperation op
;
449 cls_client::create_image(&op
, m_size
, m_order
, m_features
, oss
.str(),
452 using klass
= CreateRequest
<I
>;
453 librados::AioCompletion
*comp
=
454 create_rados_callback
<klass
, &klass::handle_create_image
>(this);
455 int r
= m_io_ctx
.aio_operate(m_header_obj
, comp
, &op
);
461 void CreateRequest
<I
>::handle_create_image(int r
) {
462 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
465 ldout(m_cct
, 5) << "image id already in-use" << dendl
;
469 lderr(m_cct
) << "error writing header: " << cpp_strerror(r
) << dendl
;
475 set_stripe_unit_count();
479 void CreateRequest
<I
>::set_stripe_unit_count() {
480 if ((!m_stripe_unit
&& !m_stripe_count
) ||
481 ((m_stripe_count
== 1) && (m_stripe_unit
== (1ull << m_order
)))) {
486 ldout(m_cct
, 15) << dendl
;
488 librados::ObjectWriteOperation op
;
489 cls_client::set_stripe_unit_count(&op
, m_stripe_unit
, m_stripe_count
);
491 using klass
= CreateRequest
<I
>;
492 librados::AioCompletion
*comp
=
493 create_rados_callback
<klass
, &klass::handle_set_stripe_unit_count
>(this);
494 int r
= m_io_ctx
.aio_operate(m_header_obj
, comp
, &op
);
500 void CreateRequest
<I
>::handle_set_stripe_unit_count(int r
) {
501 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
504 lderr(m_cct
) << "error setting stripe unit/count: "
505 << cpp_strerror(r
) << dendl
;
507 remove_header_object();
515 void CreateRequest
<I
>::object_map_resize() {
516 if ((m_features
& RBD_FEATURE_OBJECT_MAP
) == 0) {
521 ldout(m_cct
, 15) << dendl
;
523 librados::ObjectWriteOperation op
;
524 cls_client::object_map_resize(&op
, Striper::get_num_objects(m_layout
, m_size
),
527 using klass
= CreateRequest
<I
>;
528 librados::AioCompletion
*comp
=
529 create_rados_callback
<klass
, &klass::handle_object_map_resize
>(this);
530 int r
= m_io_ctx
.aio_operate(m_objmap_name
, comp
, &op
);
536 void CreateRequest
<I
>::handle_object_map_resize(int r
) {
537 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
540 lderr(m_cct
) << "error creating initial object map: "
541 << cpp_strerror(r
) << dendl
;
544 remove_header_object();
552 void CreateRequest
<I
>::fetch_mirror_mode() {
553 if ((m_features
& RBD_FEATURE_JOURNALING
) == 0) {
554 mirror_image_enable();
558 ldout(m_cct
, 15) << dendl
;
560 librados::ObjectReadOperation op
;
561 cls_client::mirror_mode_get_start(&op
);
563 using klass
= CreateRequest
<I
>;
564 librados::AioCompletion
*comp
=
565 create_rados_callback
<klass
, &klass::handle_fetch_mirror_mode
>(this);
567 int r
= m_io_ctx
.aio_operate(RBD_MIRRORING
, comp
, &op
, &m_outbl
);
573 void CreateRequest
<I
>::handle_fetch_mirror_mode(int r
) {
574 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
576 if ((r
< 0) && (r
!= -ENOENT
)) {
577 lderr(m_cct
) << "failed to retrieve mirror mode: " << cpp_strerror(r
)
585 m_mirror_mode
= cls::rbd::MIRROR_MODE_DISABLED
;
587 auto it
= m_outbl
.cbegin();
588 r
= cls_client::mirror_mode_get_finish(&it
, &m_mirror_mode
);
590 lderr(m_cct
) << "Failed to retrieve mirror mode" << dendl
;
602 void CreateRequest
<I
>::journal_create() {
603 ldout(m_cct
, 15) << dendl
;
605 using klass
= CreateRequest
<I
>;
606 Context
*ctx
= create_context_callback
<klass
, &klass::handle_journal_create
>(
609 // only link to remote primary mirror uuid if in journal-based
611 bool use_primary_mirror_uuid
= (
612 !m_non_primary_global_image_id
.empty() &&
613 m_mirror_image_mode
== cls::rbd::MIRROR_IMAGE_MODE_JOURNAL
);
615 librbd::journal::TagData tag_data
;
616 tag_data
.mirror_uuid
= (use_primary_mirror_uuid
? m_primary_mirror_uuid
:
617 librbd::Journal
<I
>::LOCAL_MIRROR_UUID
);
619 typename
journal::TypeTraits
<I
>::ContextWQ
* context_wq
;
620 Journal
<>::get_work_queue(m_cct
, &context_wq
);
622 auto req
= librbd::journal::CreateRequest
<I
>::create(
623 m_io_ctx
, m_image_id
, m_journal_order
, m_journal_splay_width
,
624 m_journal_pool
, cls::journal::Tag::TAG_CLASS_NEW
, tag_data
,
625 librbd::Journal
<I
>::IMAGE_CLIENT_ID
, context_wq
, ctx
);
630 void CreateRequest
<I
>::handle_journal_create(int r
) {
631 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
634 lderr(m_cct
) << "error creating journal: " << cpp_strerror(r
)
642 mirror_image_enable();
646 void CreateRequest
<I
>::mirror_image_enable() {
647 auto mirror_enable_flag
= (m_create_flags
& CREATE_FLAG_MIRROR_ENABLE_MASK
);
649 if ((m_mirror_mode
!= cls::rbd::MIRROR_MODE_POOL
&&
650 mirror_enable_flag
!= CREATE_FLAG_FORCE_MIRROR_ENABLE
) ||
651 (mirror_enable_flag
== CREATE_FLAG_SKIP_MIRROR_ENABLE
)) {
656 ldout(m_cct
, 15) << dendl
;
657 auto ctx
= create_context_callback
<
658 CreateRequest
<I
>, &CreateRequest
<I
>::handle_mirror_image_enable
>(this);
660 auto req
= mirror::EnableRequest
<I
>::create(
661 m_io_ctx
, m_image_id
, m_mirror_image_mode
,
662 m_non_primary_global_image_id
, true, m_op_work_queue
, ctx
);
667 void CreateRequest
<I
>::handle_mirror_image_enable(int r
) {
668 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
671 lderr(m_cct
) << "cannot enable mirroring: " << cpp_strerror(r
)
683 void CreateRequest
<I
>::complete(int r
) {
684 ldout(m_cct
, 10) << "r=" << r
<< dendl
;
686 m_data_io_ctx
.close();
687 auto on_finish
= m_on_finish
;
689 on_finish
->complete(r
);
694 void CreateRequest
<I
>::journal_remove() {
695 if ((m_features
& RBD_FEATURE_JOURNALING
) == 0) {
700 ldout(m_cct
, 15) << dendl
;
702 using klass
= CreateRequest
<I
>;
703 Context
*ctx
= create_context_callback
<klass
, &klass::handle_journal_remove
>(
706 typename
journal::TypeTraits
<I
>::ContextWQ
* context_wq
;
707 Journal
<>::get_work_queue(m_cct
, &context_wq
);
709 librbd::journal::RemoveRequest
<I
> *req
=
710 librbd::journal::RemoveRequest
<I
>::create(
711 m_io_ctx
, m_image_id
, librbd::Journal
<I
>::IMAGE_CLIENT_ID
, context_wq
,
717 void CreateRequest
<I
>::handle_journal_remove(int r
) {
718 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
721 lderr(m_cct
) << "error cleaning up journal after creation failed: "
722 << cpp_strerror(r
) << dendl
;
729 void CreateRequest
<I
>::remove_object_map() {
730 if ((m_features
& RBD_FEATURE_OBJECT_MAP
) == 0) {
731 remove_header_object();
735 ldout(m_cct
, 15) << dendl
;
737 using klass
= CreateRequest
<I
>;
738 librados::AioCompletion
*comp
=
739 create_rados_callback
<klass
, &klass::handle_remove_object_map
>(this);
740 int r
= m_io_ctx
.aio_remove(m_objmap_name
, comp
);
746 void CreateRequest
<I
>::handle_remove_object_map(int r
) {
747 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
750 lderr(m_cct
) << "error cleaning up object map after creation failed: "
751 << cpp_strerror(r
) << dendl
;
754 remove_header_object();
758 void CreateRequest
<I
>::remove_header_object() {
759 ldout(m_cct
, 15) << dendl
;
761 using klass
= CreateRequest
<I
>;
762 librados::AioCompletion
*comp
=
763 create_rados_callback
<klass
, &klass::handle_remove_header_object
>(this);
764 int r
= m_io_ctx
.aio_remove(m_header_obj
, comp
);
770 void CreateRequest
<I
>::handle_remove_header_object(int r
) {
771 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
774 lderr(m_cct
) << "error cleaning up image header after creation failed: "
775 << cpp_strerror(r
) << dendl
;
782 void CreateRequest
<I
>::remove_id_object() {
783 ldout(m_cct
, 15) << dendl
;
785 using klass
= CreateRequest
<I
>;
786 librados::AioCompletion
*comp
=
787 create_rados_callback
<klass
, &klass::handle_remove_id_object
>(this);
788 int r
= m_io_ctx
.aio_remove(m_id_obj
, comp
);
794 void CreateRequest
<I
>::handle_remove_id_object(int r
) {
795 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
798 lderr(m_cct
) << "error cleaning up id object after creation failed: "
799 << cpp_strerror(r
) << dendl
;
806 void CreateRequest
<I
>::remove_from_dir() {
807 ldout(m_cct
, 15) << dendl
;
809 librados::ObjectWriteOperation op
;
810 cls_client::dir_remove_image(&op
, m_image_name
, m_image_id
);
812 using klass
= CreateRequest
<I
>;
813 librados::AioCompletion
*comp
=
814 create_rados_callback
<klass
, &klass::handle_remove_from_dir
>(this);
815 int r
= m_io_ctx
.aio_operate(RBD_DIRECTORY
, comp
, &op
);
821 void CreateRequest
<I
>::handle_remove_from_dir(int r
) {
822 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
825 lderr(m_cct
) << "error cleaning up image from rbd_directory object "
826 << "after creation failed: " << cpp_strerror(r
) << dendl
;
835 template class librbd::image::CreateRequest
<librbd::ImageCtx
>;