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/image/Types.h"
16 #include "librbd/image/ValidatePoolRequest.h"
17 #include "librbd/journal/CreateRequest.h"
18 #include "librbd/journal/RemoveRequest.h"
19 #include "librbd/mirror/EnableRequest.h"
20 #include "journal/Journaler.h"
23 #define dout_subsys ceph_subsys_rbd
25 #define dout_prefix *_dout << "librbd::image::CreateRequest: " << __func__ \
31 using util::create_rados_callback
;
32 using util::create_context_callback
;
36 int validate_features(CephContext
*cct
, uint64_t features
) {
37 if (features
& ~RBD_FEATURES_ALL
) {
38 lderr(cct
) << "librbd does not support requested features." << dendl
;
41 if ((features
& RBD_FEATURE_OPERATIONS
) != 0) {
42 lderr(cct
) << "cannot use internally controlled features" << dendl
;
45 if ((features
& RBD_FEATURE_FAST_DIFF
) != 0 &&
46 (features
& RBD_FEATURE_OBJECT_MAP
) == 0) {
47 lderr(cct
) << "cannot use fast diff without object map" << dendl
;
50 if ((features
& RBD_FEATURE_OBJECT_MAP
) != 0 &&
51 (features
& RBD_FEATURE_EXCLUSIVE_LOCK
) == 0) {
52 lderr(cct
) << "cannot use object map without exclusive lock" << dendl
;
55 if ((features
& RBD_FEATURE_JOURNALING
) != 0 &&
56 (features
& RBD_FEATURE_EXCLUSIVE_LOCK
) == 0) {
57 lderr(cct
) << "cannot use journaling without exclusive lock" << dendl
;
64 int validate_striping(CephContext
*cct
, uint8_t order
, uint64_t stripe_unit
,
65 uint64_t stripe_count
) {
66 if ((stripe_unit
&& !stripe_count
) ||
67 (!stripe_unit
&& stripe_count
)) {
68 lderr(cct
) << "must specify both (or neither) of stripe-unit and "
69 << "stripe-count" << dendl
;
71 } else if (stripe_unit
&& ((1ull << order
) % stripe_unit
|| stripe_unit
> (1ull << order
))) {
72 lderr(cct
) << "stripe unit is not a factor of the object size" << dendl
;
78 bool validate_layout(CephContext
*cct
, uint64_t size
, file_layout_t
&layout
) {
79 if (!librbd::ObjectMap
<>::is_compatible(layout
, size
)) {
80 lderr(cct
) << "image size not compatible with object map" << dendl
;
87 int get_image_option(const ImageOptions
&image_options
, int option
,
90 int r
= image_options
.get(option
, &large_value
);
94 *value
= static_cast<uint8_t>(large_value
);
98 } // anonymous namespace
101 int CreateRequest
<I
>::validate_order(CephContext
*cct
, uint8_t order
) {
102 if (order
> 25 || order
< 12) {
103 lderr(cct
) << "order must be in the range [12, 25]" << dendl
;
110 #define dout_prefix *_dout << "librbd::image::CreateRequest: " << this << " " \
114 CreateRequest
<I
>::CreateRequest(const ConfigProxy
& config
, IoCtx
&ioctx
,
115 const std::string
&image_name
,
116 const std::string
&image_id
, uint64_t size
,
117 const ImageOptions
&image_options
,
118 uint32_t create_flags
,
119 cls::rbd::MirrorImageMode mirror_image_mode
,
120 const std::string
&non_primary_global_image_id
,
121 const std::string
&primary_mirror_uuid
,
122 ContextWQ
*op_work_queue
, Context
*on_finish
)
123 : m_config(config
), m_image_name(image_name
), m_image_id(image_id
),
124 m_size(size
), m_create_flags(create_flags
),
125 m_mirror_image_mode(mirror_image_mode
),
126 m_non_primary_global_image_id(non_primary_global_image_id
),
127 m_primary_mirror_uuid(primary_mirror_uuid
),
128 m_op_work_queue(op_work_queue
), m_on_finish(on_finish
) {
131 m_cct
= reinterpret_cast<CephContext
*>(m_io_ctx
.cct());
133 m_id_obj
= util::id_obj_name(m_image_name
);
134 m_header_obj
= util::header_name(m_image_id
);
135 m_objmap_name
= ObjectMap
<>::object_map_name(m_image_id
, CEPH_NOSNAP
);
136 if (!non_primary_global_image_id
.empty() &&
137 (m_create_flags
& CREATE_FLAG_MIRROR_ENABLE_MASK
) == 0) {
138 m_create_flags
|= CREATE_FLAG_FORCE_MIRROR_ENABLE
;
141 if (image_options
.get(RBD_IMAGE_OPTION_FEATURES
, &m_features
) != 0) {
142 m_features
= librbd::rbd_features_from_string(
143 m_config
.get_val
<std::string
>("rbd_default_features"), nullptr);
144 m_negotiate_features
= true;
147 uint64_t features_clear
= 0;
148 uint64_t features_set
= 0;
149 image_options
.get(RBD_IMAGE_OPTION_FEATURES_CLEAR
, &features_clear
);
150 image_options
.get(RBD_IMAGE_OPTION_FEATURES_SET
, &features_set
);
152 uint64_t features_conflict
= features_clear
& features_set
;
153 features_clear
&= ~features_conflict
;
154 features_set
&= ~features_conflict
;
155 m_features
|= features_set
;
156 m_features
&= ~features_clear
;
158 if ((m_features
& RBD_FEATURE_OBJECT_MAP
) == RBD_FEATURE_OBJECT_MAP
) {
159 m_features
|= RBD_FEATURE_FAST_DIFF
;
162 if (image_options
.get(RBD_IMAGE_OPTION_STRIPE_UNIT
, &m_stripe_unit
) != 0 ||
163 m_stripe_unit
== 0) {
164 m_stripe_unit
= m_config
.get_val
<Option::size_t>("rbd_default_stripe_unit");
166 if (image_options
.get(RBD_IMAGE_OPTION_STRIPE_COUNT
, &m_stripe_count
) != 0 ||
167 m_stripe_count
== 0) {
168 m_stripe_count
= m_config
.get_val
<uint64_t>("rbd_default_stripe_count");
170 if (get_image_option(image_options
, RBD_IMAGE_OPTION_ORDER
, &m_order
) != 0 ||
172 m_order
= config
.get_val
<uint64_t>("rbd_default_order");
174 if (get_image_option(image_options
, RBD_IMAGE_OPTION_JOURNAL_ORDER
,
175 &m_journal_order
) != 0) {
176 m_journal_order
= m_config
.get_val
<uint64_t>("rbd_journal_order");
178 if (get_image_option(image_options
, RBD_IMAGE_OPTION_JOURNAL_SPLAY_WIDTH
,
179 &m_journal_splay_width
) != 0) {
180 m_journal_splay_width
= m_config
.get_val
<uint64_t>(
181 "rbd_journal_splay_width");
183 if (image_options
.get(RBD_IMAGE_OPTION_JOURNAL_POOL
, &m_journal_pool
) != 0) {
184 m_journal_pool
= m_config
.get_val
<std::string
>("rbd_journal_pool");
186 if (image_options
.get(RBD_IMAGE_OPTION_DATA_POOL
, &m_data_pool
) != 0) {
187 m_data_pool
= m_config
.get_val
<std::string
>("rbd_default_data_pool");
190 m_layout
.object_size
= 1ull << m_order
;
191 if (m_stripe_unit
== 0 || m_stripe_count
== 0) {
192 m_layout
.stripe_unit
= m_layout
.object_size
;
193 m_layout
.stripe_count
= 1;
195 m_layout
.stripe_unit
= m_stripe_unit
;
196 m_layout
.stripe_count
= m_stripe_count
;
199 if (!m_data_pool
.empty() && m_data_pool
!= ioctx
.get_pool_name()) {
200 m_features
|= RBD_FEATURE_DATA_POOL
;
203 m_features
&= ~RBD_FEATURE_DATA_POOL
;
206 if ((m_stripe_unit
!= 0 && m_stripe_unit
!= (1ULL << m_order
)) ||
207 (m_stripe_count
!= 0 && m_stripe_count
!= 1)) {
208 m_features
|= RBD_FEATURE_STRIPINGV2
;
210 m_features
&= ~RBD_FEATURE_STRIPINGV2
;
213 ldout(m_cct
, 10) << "name=" << m_image_name
<< ", "
214 << "id=" << m_image_id
<< ", "
215 << "size=" << m_size
<< ", "
216 << "features=" << m_features
<< ", "
217 << "order=" << (uint64_t)m_order
<< ", "
218 << "stripe_unit=" << m_stripe_unit
<< ", "
219 << "stripe_count=" << m_stripe_count
<< ", "
220 << "journal_order=" << (uint64_t)m_journal_order
<< ", "
221 << "journal_splay_width="
222 << (uint64_t)m_journal_splay_width
<< ", "
223 << "journal_pool=" << m_journal_pool
<< ", "
224 << "data_pool=" << m_data_pool
<< dendl
;
228 void CreateRequest
<I
>::send() {
229 ldout(m_cct
, 20) << dendl
;
231 int r
= validate_features(m_cct
, m_features
);
237 r
= validate_order(m_cct
, m_order
);
243 r
= validate_striping(m_cct
, m_order
, m_stripe_unit
, m_stripe_count
);
249 if (((m_features
& RBD_FEATURE_OBJECT_MAP
) != 0) &&
250 (!validate_layout(m_cct
, m_size
, m_layout
))) {
255 validate_data_pool();
258 template <typename I
>
259 void CreateRequest
<I
>::validate_data_pool() {
260 m_data_io_ctx
= m_io_ctx
;
261 if ((m_features
& RBD_FEATURE_DATA_POOL
) != 0) {
262 librados::Rados
rados(m_io_ctx
);
263 int r
= rados
.ioctx_create(m_data_pool
.c_str(), m_data_io_ctx
);
265 lderr(m_cct
) << "data pool " << m_data_pool
<< " does not exist" << dendl
;
269 m_data_pool_id
= m_data_io_ctx
.get_id();
270 m_data_io_ctx
.set_namespace(m_io_ctx
.get_namespace());
273 if (!m_config
.get_val
<bool>("rbd_validate_pool")) {
274 add_image_to_directory();
278 ldout(m_cct
, 15) << dendl
;
280 auto ctx
= create_context_callback
<
281 CreateRequest
<I
>, &CreateRequest
<I
>::handle_validate_data_pool
>(this);
282 auto req
= ValidatePoolRequest
<I
>::create(m_data_io_ctx
, m_op_work_queue
,
287 template <typename I
>
288 void CreateRequest
<I
>::handle_validate_data_pool(int r
) {
289 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
292 lderr(m_cct
) << "pool does not support RBD images" << dendl
;
296 lderr(m_cct
) << "failed to validate pool: " << cpp_strerror(r
) << dendl
;
301 add_image_to_directory();
305 void CreateRequest
<I
>::add_image_to_directory() {
306 ldout(m_cct
, 15) << dendl
;
308 librados::ObjectWriteOperation op
;
309 if (!m_io_ctx
.get_namespace().empty()) {
310 cls_client::dir_state_assert(&op
, cls::rbd::DIRECTORY_STATE_READY
);
312 cls_client::dir_add_image(&op
, m_image_name
, m_image_id
);
314 using klass
= CreateRequest
<I
>;
315 librados::AioCompletion
*comp
=
316 create_rados_callback
<klass
, &klass::handle_add_image_to_directory
>(this);
317 int r
= m_io_ctx
.aio_operate(RBD_DIRECTORY
, comp
, &op
);
323 void CreateRequest
<I
>::handle_add_image_to_directory(int r
) {
324 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
327 ldout(m_cct
, 5) << "directory entry for image " << m_image_name
328 << " already exists" << dendl
;
331 } else if (!m_io_ctx
.get_namespace().empty() && r
== -ENOENT
) {
332 ldout(m_cct
, 5) << "namespace " << m_io_ctx
.get_namespace()
333 << " does not exist" << dendl
;
337 lderr(m_cct
) << "error adding image to directory: " << cpp_strerror(r
)
347 void CreateRequest
<I
>::create_id_object() {
348 ldout(m_cct
, 15) << dendl
;
350 librados::ObjectWriteOperation op
;
352 cls_client::set_id(&op
, m_image_id
);
354 using klass
= CreateRequest
<I
>;
355 librados::AioCompletion
*comp
=
356 create_rados_callback
<klass
, &klass::handle_create_id_object
>(this);
357 int r
= m_io_ctx
.aio_operate(m_id_obj
, comp
, &op
);
363 void CreateRequest
<I
>::handle_create_id_object(int r
) {
364 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
367 ldout(m_cct
, 5) << "id object for " << m_image_name
<< " already exists"
373 lderr(m_cct
) << "error creating RBD id object: " << cpp_strerror(r
)
380 negotiate_features();
384 void CreateRequest
<I
>::negotiate_features() {
385 if (!m_negotiate_features
) {
390 ldout(m_cct
, 15) << dendl
;
392 librados::ObjectReadOperation op
;
393 cls_client::get_all_features_start(&op
);
395 using klass
= CreateRequest
<I
>;
396 librados::AioCompletion
*comp
=
397 create_rados_callback
<klass
, &klass::handle_negotiate_features
>(this);
400 int r
= m_io_ctx
.aio_operate(RBD_DIRECTORY
, comp
, &op
, &m_outbl
);
406 void CreateRequest
<I
>::handle_negotiate_features(int r
) {
407 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
409 uint64_t all_features
;
411 auto it
= m_outbl
.cbegin();
412 r
= cls_client::get_all_features_finish(&it
, &all_features
);
415 ldout(m_cct
, 10) << "error retrieving server supported features set: "
416 << cpp_strerror(r
) << dendl
;
417 } else if ((m_features
& all_features
) != m_features
) {
418 m_features
&= all_features
;
419 ldout(m_cct
, 10) << "limiting default features set to server supported: "
420 << m_features
<< dendl
;
427 void CreateRequest
<I
>::create_image() {
428 ldout(m_cct
, 15) << dendl
;
429 ceph_assert(m_data_pool
.empty() || m_data_pool_id
!= -1);
432 oss
<< RBD_DATA_PREFIX
;
433 if (m_data_pool_id
!= -1) {
434 oss
<< stringify(m_io_ctx
.get_id()) << ".";
437 if (oss
.str().length() > RBD_MAX_BLOCK_NAME_PREFIX_LENGTH
) {
438 lderr(m_cct
) << "object prefix '" << oss
.str() << "' too large" << dendl
;
444 librados::ObjectWriteOperation op
;
446 cls_client::create_image(&op
, m_size
, m_order
, m_features
, oss
.str(),
449 using klass
= CreateRequest
<I
>;
450 librados::AioCompletion
*comp
=
451 create_rados_callback
<klass
, &klass::handle_create_image
>(this);
452 int r
= m_io_ctx
.aio_operate(m_header_obj
, comp
, &op
);
458 void CreateRequest
<I
>::handle_create_image(int r
) {
459 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
462 ldout(m_cct
, 5) << "image id already in-use" << dendl
;
466 lderr(m_cct
) << "error writing header: " << cpp_strerror(r
) << dendl
;
472 set_stripe_unit_count();
476 void CreateRequest
<I
>::set_stripe_unit_count() {
477 if ((!m_stripe_unit
&& !m_stripe_count
) ||
478 ((m_stripe_count
== 1) && (m_stripe_unit
== (1ull << m_order
)))) {
483 ldout(m_cct
, 15) << dendl
;
485 librados::ObjectWriteOperation op
;
486 cls_client::set_stripe_unit_count(&op
, m_stripe_unit
, m_stripe_count
);
488 using klass
= CreateRequest
<I
>;
489 librados::AioCompletion
*comp
=
490 create_rados_callback
<klass
, &klass::handle_set_stripe_unit_count
>(this);
491 int r
= m_io_ctx
.aio_operate(m_header_obj
, comp
, &op
);
497 void CreateRequest
<I
>::handle_set_stripe_unit_count(int r
) {
498 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
501 lderr(m_cct
) << "error setting stripe unit/count: "
502 << cpp_strerror(r
) << dendl
;
504 remove_header_object();
512 void CreateRequest
<I
>::object_map_resize() {
513 if ((m_features
& RBD_FEATURE_OBJECT_MAP
) == 0) {
518 ldout(m_cct
, 15) << dendl
;
520 librados::ObjectWriteOperation op
;
521 cls_client::object_map_resize(&op
, Striper::get_num_objects(m_layout
, m_size
),
524 using klass
= CreateRequest
<I
>;
525 librados::AioCompletion
*comp
=
526 create_rados_callback
<klass
, &klass::handle_object_map_resize
>(this);
527 int r
= m_io_ctx
.aio_operate(m_objmap_name
, comp
, &op
);
533 void CreateRequest
<I
>::handle_object_map_resize(int r
) {
534 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
537 lderr(m_cct
) << "error creating initial object map: "
538 << cpp_strerror(r
) << dendl
;
541 remove_header_object();
549 void CreateRequest
<I
>::fetch_mirror_mode() {
550 if ((m_features
& RBD_FEATURE_JOURNALING
) == 0) {
551 mirror_image_enable();
555 ldout(m_cct
, 15) << dendl
;
557 librados::ObjectReadOperation op
;
558 cls_client::mirror_mode_get_start(&op
);
560 using klass
= CreateRequest
<I
>;
561 librados::AioCompletion
*comp
=
562 create_rados_callback
<klass
, &klass::handle_fetch_mirror_mode
>(this);
564 int r
= m_io_ctx
.aio_operate(RBD_MIRRORING
, comp
, &op
, &m_outbl
);
570 void CreateRequest
<I
>::handle_fetch_mirror_mode(int r
) {
571 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
573 if ((r
< 0) && (r
!= -ENOENT
)) {
574 lderr(m_cct
) << "failed to retrieve mirror mode: " << cpp_strerror(r
)
582 m_mirror_mode
= cls::rbd::MIRROR_MODE_DISABLED
;
584 auto it
= m_outbl
.cbegin();
585 r
= cls_client::mirror_mode_get_finish(&it
, &m_mirror_mode
);
587 lderr(m_cct
) << "Failed to retrieve mirror mode" << dendl
;
599 void CreateRequest
<I
>::journal_create() {
600 ldout(m_cct
, 15) << dendl
;
602 using klass
= CreateRequest
<I
>;
603 Context
*ctx
= create_context_callback
<klass
, &klass::handle_journal_create
>(
606 // only link to remote primary mirror uuid if in journal-based
608 bool use_primary_mirror_uuid
= (
609 !m_non_primary_global_image_id
.empty() &&
610 m_mirror_image_mode
== cls::rbd::MIRROR_IMAGE_MODE_JOURNAL
);
612 librbd::journal::TagData tag_data
;
613 tag_data
.mirror_uuid
= (use_primary_mirror_uuid
? m_primary_mirror_uuid
:
614 librbd::Journal
<I
>::LOCAL_MIRROR_UUID
);
616 auto req
= librbd::journal::CreateRequest
<I
>::create(
617 m_io_ctx
, m_image_id
, m_journal_order
, m_journal_splay_width
,
618 m_journal_pool
, cls::journal::Tag::TAG_CLASS_NEW
, tag_data
,
619 librbd::Journal
<I
>::IMAGE_CLIENT_ID
, m_op_work_queue
, ctx
);
624 void CreateRequest
<I
>::handle_journal_create(int r
) {
625 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
628 lderr(m_cct
) << "error creating journal: " << cpp_strerror(r
)
636 mirror_image_enable();
640 void CreateRequest
<I
>::mirror_image_enable() {
641 auto mirror_enable_flag
= (m_create_flags
& CREATE_FLAG_MIRROR_ENABLE_MASK
);
643 if ((m_mirror_mode
!= cls::rbd::MIRROR_MODE_POOL
&&
644 mirror_enable_flag
!= CREATE_FLAG_FORCE_MIRROR_ENABLE
) ||
645 (mirror_enable_flag
== CREATE_FLAG_SKIP_MIRROR_ENABLE
)) {
650 ldout(m_cct
, 15) << dendl
;
651 auto ctx
= create_context_callback
<
652 CreateRequest
<I
>, &CreateRequest
<I
>::handle_mirror_image_enable
>(this);
654 auto req
= mirror::EnableRequest
<I
>::create(
655 m_io_ctx
, m_image_id
, m_mirror_image_mode
,
656 m_non_primary_global_image_id
, true, m_op_work_queue
, ctx
);
661 void CreateRequest
<I
>::handle_mirror_image_enable(int r
) {
662 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
665 lderr(m_cct
) << "cannot enable mirroring: " << cpp_strerror(r
)
677 void CreateRequest
<I
>::complete(int r
) {
678 ldout(m_cct
, 10) << "r=" << r
<< dendl
;
680 m_data_io_ctx
.close();
681 auto on_finish
= m_on_finish
;
683 on_finish
->complete(r
);
688 void CreateRequest
<I
>::journal_remove() {
689 if ((m_features
& RBD_FEATURE_JOURNALING
) == 0) {
694 ldout(m_cct
, 15) << dendl
;
696 using klass
= CreateRequest
<I
>;
697 Context
*ctx
= create_context_callback
<klass
, &klass::handle_journal_remove
>(
700 librbd::journal::RemoveRequest
<I
> *req
=
701 librbd::journal::RemoveRequest
<I
>::create(
702 m_io_ctx
, m_image_id
, librbd::Journal
<I
>::IMAGE_CLIENT_ID
, m_op_work_queue
,
708 void CreateRequest
<I
>::handle_journal_remove(int r
) {
709 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
712 lderr(m_cct
) << "error cleaning up journal after creation failed: "
713 << cpp_strerror(r
) << dendl
;
720 void CreateRequest
<I
>::remove_object_map() {
721 if ((m_features
& RBD_FEATURE_OBJECT_MAP
) == 0) {
722 remove_header_object();
726 ldout(m_cct
, 15) << dendl
;
728 using klass
= CreateRequest
<I
>;
729 librados::AioCompletion
*comp
=
730 create_rados_callback
<klass
, &klass::handle_remove_object_map
>(this);
731 int r
= m_io_ctx
.aio_remove(m_objmap_name
, comp
);
737 void CreateRequest
<I
>::handle_remove_object_map(int r
) {
738 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
741 lderr(m_cct
) << "error cleaning up object map after creation failed: "
742 << cpp_strerror(r
) << dendl
;
745 remove_header_object();
749 void CreateRequest
<I
>::remove_header_object() {
750 ldout(m_cct
, 15) << dendl
;
752 using klass
= CreateRequest
<I
>;
753 librados::AioCompletion
*comp
=
754 create_rados_callback
<klass
, &klass::handle_remove_header_object
>(this);
755 int r
= m_io_ctx
.aio_remove(m_header_obj
, comp
);
761 void CreateRequest
<I
>::handle_remove_header_object(int r
) {
762 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
765 lderr(m_cct
) << "error cleaning up image header after creation failed: "
766 << cpp_strerror(r
) << dendl
;
773 void CreateRequest
<I
>::remove_id_object() {
774 ldout(m_cct
, 15) << dendl
;
776 using klass
= CreateRequest
<I
>;
777 librados::AioCompletion
*comp
=
778 create_rados_callback
<klass
, &klass::handle_remove_id_object
>(this);
779 int r
= m_io_ctx
.aio_remove(m_id_obj
, comp
);
785 void CreateRequest
<I
>::handle_remove_id_object(int r
) {
786 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
789 lderr(m_cct
) << "error cleaning up id object after creation failed: "
790 << cpp_strerror(r
) << dendl
;
797 void CreateRequest
<I
>::remove_from_dir() {
798 ldout(m_cct
, 15) << dendl
;
800 librados::ObjectWriteOperation op
;
801 cls_client::dir_remove_image(&op
, m_image_name
, m_image_id
);
803 using klass
= CreateRequest
<I
>;
804 librados::AioCompletion
*comp
=
805 create_rados_callback
<klass
, &klass::handle_remove_from_dir
>(this);
806 int r
= m_io_ctx
.aio_operate(RBD_DIRECTORY
, comp
, &op
);
812 void CreateRequest
<I
>::handle_remove_from_dir(int r
) {
813 ldout(m_cct
, 15) << "r=" << r
<< dendl
;
816 lderr(m_cct
) << "error cleaning up image from rbd_directory object "
817 << "after creation failed: " << cpp_strerror(r
) << dendl
;
826 template class librbd::image::CreateRequest
<librbd::ImageCtx
>;