]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/image/CreateRequest.cc
update sources to 12.2.10
[ceph.git] / ceph / src / librbd / image / CreateRequest.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/image/CreateRequest.h"
5#include "common/dout.h"
6#include "common/errno.h"
7#include "cls/rbd/cls_rbd_client.h"
8#include "include/assert.h"
9#include "librbd/Utils.h"
10#include "common/ceph_context.h"
11#include "librbd/Journal.h"
12#include "librbd/MirroringWatcher.h"
13#include "librbd/journal/CreateRequest.h"
14#include "librbd/journal/RemoveRequest.h"
15#include "librbd/mirror/EnableRequest.h"
16#include "librbd/io/AioCompletion.h"
17#include "journal/Journaler.h"
18
19#define dout_subsys ceph_subsys_rbd
20#undef dout_prefix
21#define dout_prefix *_dout << "librbd::image::CreateRequest: " << __func__ \
22 << ": "
23
24namespace librbd {
25namespace image {
26
27using util::create_rados_callback;
28using util::create_context_callback;
29
30namespace {
31
32int validate_features(CephContext *cct, uint64_t features,
33 bool force_non_primary) {
34 if (features & ~RBD_FEATURES_ALL) {
35 lderr(cct) << "librbd does not support requested features." << dendl;
36 return -ENOSYS;
37 }
38 if ((features & RBD_FEATURE_FAST_DIFF) != 0 &&
39 (features & RBD_FEATURE_OBJECT_MAP) == 0) {
40 lderr(cct) << "cannot use fast diff without object map" << dendl;
41 return -EINVAL;
42 }
43 if ((features & RBD_FEATURE_OBJECT_MAP) != 0 &&
44 (features & RBD_FEATURE_EXCLUSIVE_LOCK) == 0) {
45 lderr(cct) << "cannot use object map without exclusive lock" << dendl;
46 return -EINVAL;
47 }
48 if ((features & RBD_FEATURE_JOURNALING) != 0) {
49 if ((features & RBD_FEATURE_EXCLUSIVE_LOCK) == 0) {
50 lderr(cct) << "cannot use journaling without exclusive lock" << dendl;
51 return -EINVAL;
52 }
53 } else if (force_non_primary) {
54 assert(false);
55 }
56
57 return 0;
58}
59
60int validate_striping(CephContext *cct, uint8_t order, uint64_t stripe_unit,
61 uint64_t stripe_count) {
62 if ((stripe_unit && !stripe_count) ||
63 (!stripe_unit && stripe_count)) {
64 lderr(cct) << "must specify both (or neither) of stripe-unit and "
65 << "stripe-count" << dendl;
66 return -EINVAL;
67 } else if (stripe_unit || stripe_count) {
68 if ((1ull << order) % stripe_unit || stripe_unit > (1ull << order)) {
69 lderr(cct) << "stripe unit is not a factor of the object size" << dendl;
70 return -EINVAL;
71 }
72 }
73 return 0;
74}
75
7c673cae
FG
76bool validate_layout(CephContext *cct, uint64_t size, file_layout_t &layout) {
77 if (!librbd::ObjectMap<>::is_compatible(layout, size)) {
78 lderr(cct) << "image size not compatible with object map" << dendl;
79 return false;
80 }
81
82 return true;
83}
84
85int get_image_option(const ImageOptions &image_options, int option,
86 uint8_t *value) {
87 uint64_t large_value;
88 int r = image_options.get(option, &large_value);
89 if (r < 0) {
90 return r;
91 }
92 *value = static_cast<uint8_t>(large_value);
93 return 0;
94}
95
96} // anonymous namespace
97
98template<typename I>
99int CreateRequest<I>::validate_order(CephContext *cct, uint8_t order) {
100 if (order > 25 || order < 12) {
101 lderr(cct) << "order must be in the range [12, 25]" << dendl;
102 return -EDOM;
103 }
104 return 0;
105}
106
107#undef dout_prefix
108#define dout_prefix *_dout << "librbd::image::CreateRequest: " << this << " " \
109 << __func__ << ": "
110
111template<typename I>
112CreateRequest<I>::CreateRequest(IoCtx &ioctx, const std::string &image_name,
113 const std::string &image_id, uint64_t size,
114 const ImageOptions &image_options,
115 const std::string &non_primary_global_image_id,
116 const std::string &primary_mirror_uuid,
117 bool skip_mirror_enable,
118 ContextWQ *op_work_queue, Context *on_finish)
119 : m_ioctx(ioctx), m_image_name(image_name), m_image_id(image_id),
120 m_size(size), m_non_primary_global_image_id(non_primary_global_image_id),
121 m_primary_mirror_uuid(primary_mirror_uuid),
122 m_skip_mirror_enable(skip_mirror_enable),
123 m_op_work_queue(op_work_queue), m_on_finish(on_finish) {
124 m_cct = reinterpret_cast<CephContext *>(m_ioctx.cct());
125
126 m_id_obj = util::id_obj_name(m_image_name);
127 m_header_obj = util::header_name(m_image_id);
128 m_objmap_name = ObjectMap<>::object_map_name(m_image_id, CEPH_NOSNAP);
129
130 if (image_options.get(RBD_IMAGE_OPTION_FEATURES, &m_features) != 0) {
131 m_features = util::get_rbd_default_features(m_cct);
132 m_negotiate_features = true;
133 }
134
135 uint64_t features_clear = 0;
136 uint64_t features_set = 0;
137 image_options.get(RBD_IMAGE_OPTION_FEATURES_CLEAR, &features_clear);
138 image_options.get(RBD_IMAGE_OPTION_FEATURES_SET, &features_set);
139
140 uint64_t features_conflict = features_clear & features_set;
141 features_clear &= ~features_conflict;
142 features_set &= ~features_conflict;
143 m_features |= features_set;
144 m_features &= ~features_clear;
145
146 if (image_options.get(RBD_IMAGE_OPTION_STRIPE_UNIT, &m_stripe_unit) != 0 ||
147 m_stripe_unit == 0) {
181888fb 148 m_stripe_unit = m_cct->_conf->get_val<uint64_t>("rbd_default_stripe_unit");
7c673cae
FG
149 }
150 if (image_options.get(RBD_IMAGE_OPTION_STRIPE_COUNT, &m_stripe_count) != 0 ||
151 m_stripe_count == 0) {
181888fb 152 m_stripe_count = m_cct->_conf->get_val<uint64_t>("rbd_default_stripe_count");
7c673cae
FG
153 }
154 if (get_image_option(image_options, RBD_IMAGE_OPTION_ORDER, &m_order) != 0 ||
155 m_order == 0) {
181888fb 156 m_order = m_cct->_conf->get_val<int64_t>("rbd_default_order");
7c673cae
FG
157 }
158 if (get_image_option(image_options, RBD_IMAGE_OPTION_JOURNAL_ORDER,
159 &m_journal_order) != 0) {
181888fb 160 m_journal_order = m_cct->_conf->get_val<uint64_t>("rbd_journal_order");
7c673cae
FG
161 }
162 if (get_image_option(image_options, RBD_IMAGE_OPTION_JOURNAL_SPLAY_WIDTH,
163 &m_journal_splay_width) != 0) {
181888fb 164 m_journal_splay_width = m_cct->_conf->get_val<uint64_t>("rbd_journal_splay_width");
7c673cae
FG
165 }
166 if (image_options.get(RBD_IMAGE_OPTION_JOURNAL_POOL, &m_journal_pool) != 0) {
181888fb 167 m_journal_pool = m_cct->_conf->get_val<std::string>("rbd_journal_pool");
7c673cae
FG
168 }
169 if (image_options.get(RBD_IMAGE_OPTION_DATA_POOL, &m_data_pool) != 0) {
181888fb 170 m_data_pool = m_cct->_conf->get_val<std::string>("rbd_default_data_pool");
7c673cae
FG
171 }
172
173 m_layout.object_size = 1ull << m_order;
174 if (m_stripe_unit == 0 || m_stripe_count == 0) {
175 m_layout.stripe_unit = m_layout.object_size;
176 m_layout.stripe_count = 1;
177 } else {
178 m_layout.stripe_unit = m_stripe_unit;
179 m_layout.stripe_count = m_stripe_count;
180 }
181
182 m_force_non_primary = !non_primary_global_image_id.empty();
183
184 if (!m_data_pool.empty() && m_data_pool != ioctx.get_pool_name()) {
185 m_features |= RBD_FEATURE_DATA_POOL;
186 } else {
187 m_data_pool.clear();
188 m_features &= ~RBD_FEATURE_DATA_POOL;
189 }
190
191 if ((m_stripe_unit != 0 && m_stripe_unit != (1ULL << m_order)) ||
192 (m_stripe_count != 0 && m_stripe_count != 1)) {
193 m_features |= RBD_FEATURE_STRIPINGV2;
194 } else {
195 m_features &= ~RBD_FEATURE_STRIPINGV2;
196 }
197
198 ldout(m_cct, 20) << "name=" << m_image_name << ", "
199 << "id=" << m_image_id << ", "
200 << "size=" << m_size << ", "
201 << "features=" << m_features << ", "
202 << "order=" << (uint64_t)m_order << ", "
203 << "stripe_unit=" << m_stripe_unit << ", "
204 << "stripe_count=" << m_stripe_count << ", "
205 << "journal_order=" << (uint64_t)m_journal_order << ", "
206 << "journal_splay_width="
207 << (uint64_t)m_journal_splay_width << ", "
208 << "journal_pool=" << m_journal_pool << ", "
209 << "data_pool=" << m_data_pool << dendl;
210}
211
212template<typename I>
213void CreateRequest<I>::send() {
214 ldout(m_cct, 20) << dendl;
215
216 int r = validate_features(m_cct, m_features, m_force_non_primary);
217 if (r < 0) {
218 complete(r);
219 return;
220 }
221
222 r = validate_order(m_cct, m_order);
223 if (r < 0) {
224 complete(r);
225 return;
226 }
227
228 r = validate_striping(m_cct, m_order, m_stripe_unit, m_stripe_count);
229 if (r < 0) {
230 complete(r);
231 return;
232 }
233
c07f9fc5
FG
234 if (((m_features & RBD_FEATURE_OBJECT_MAP) != 0) &&
235 (!validate_layout(m_cct, m_size, m_layout))) {
7c673cae
FG
236 complete(-EINVAL);
237 return;
238 }
239
91327a77 240 validate_data_pool();
7c673cae
FG
241}
242
91327a77
AA
243template <typename I>
244void CreateRequest<I>::validate_data_pool() {
245 m_data_io_ctx = m_ioctx;
246 if ((m_features & RBD_FEATURE_DATA_POOL) != 0) {
247 librados::Rados rados(m_ioctx);
248 int r = rados.ioctx_create(m_data_pool.c_str(), m_data_io_ctx);
249 if (r < 0) {
250 lderr(m_cct) << "data pool " << m_data_pool << " does not exist" << dendl;
251 complete(r);
252 return;
253 }
254 m_data_pool_id = m_data_io_ctx.get_id();
255 }
256
181888fb 257 if (!m_cct->_conf->get_val<bool>("rbd_validate_pool")) {
7c673cae
FG
258 create_id_object();
259 return;
260 }
261
262 ldout(m_cct, 20) << dendl;
263
264 using klass = CreateRequest<I>;
265 librados::AioCompletion *comp =
91327a77 266 create_rados_callback<klass, &klass::handle_validate_data_pool>(this);
7c673cae
FG
267
268 librados::ObjectReadOperation op;
91327a77 269 op.read(0, 0, nullptr, nullptr);
7c673cae
FG
270
271 m_outbl.clear();
91327a77 272 int r = m_data_io_ctx.aio_operate(RBD_INFO, comp, &op, &m_outbl);
7c673cae
FG
273 assert(r == 0);
274 comp->release();
275}
276
91327a77
AA
277template <typename I>
278void CreateRequest<I>::handle_validate_data_pool(int r) {
7c673cae
FG
279 ldout(m_cct, 20) << "r=" << r << dendl;
280
91327a77
AA
281 bufferlist bl;
282 bl.append("overwrite validated");
283
284 if (r >= 0 && m_outbl.contents_equal(bl)) {
285 create_id_object();
7c673cae
FG
286 return;
287 } else if ((r < 0) && (r != -ENOENT)) {
91327a77 288 lderr(m_cct) << "failed to read RBD info: " << cpp_strerror(r) << dendl;
7c673cae
FG
289 complete(r);
290 return;
291 }
292
293 // allocate a self-managed snapshot id if this a new pool to force
294 // self-managed snapshot mode
295 // This call is executed just once per (fresh) pool, hence we do not
296 // try hard to make it asynchronous (and it's pretty safe not to cause
297 // deadlocks).
298
91327a77
AA
299 ldout(m_cct, 10) << "validating self-managed RBD snapshot support" << dendl;
300
7c673cae 301 uint64_t snap_id;
91327a77 302 r = m_data_io_ctx.selfmanaged_snap_create(&snap_id);
7c673cae
FG
303 if (r == -EINVAL) {
304 lderr(m_cct) << "pool not configured for self-managed RBD snapshot support"
305 << dendl;
306 complete(r);
307 return;
308 } else if (r < 0) {
309 lderr(m_cct) << "failed to allocate self-managed snapshot: "
310 << cpp_strerror(r) << dendl;
311 complete(r);
312 return;
313 }
314
91327a77 315 r = m_data_io_ctx.selfmanaged_snap_remove(snap_id);
7c673cae
FG
316 if (r < 0) {
317 // we've already switched to self-managed snapshots -- no need to
318 // error out in case of failure here.
319 ldout(m_cct, 10) << "failed to release self-managed snapshot " << snap_id
320 << ": " << cpp_strerror(r) << dendl;
321 }
322
7c673cae 323 ldout(m_cct, 10) << "validating overwrite support" << dendl;
91327a77 324
7c673cae
FG
325 bufferlist initial_bl;
326 initial_bl.append("validate");
327 r = m_data_io_ctx.write(RBD_INFO, initial_bl, initial_bl.length(), 0);
328 if (r >= 0) {
329 r = m_data_io_ctx.write(RBD_INFO, bl, bl.length(), 0);
330 }
331 if (r == -EOPNOTSUPP) {
332 lderr(m_cct) << "pool missing required overwrite support" << dendl;
333 complete(-EINVAL);
334 return;
335 } else if (r < 0) {
336 lderr(m_cct) << "failed to validate overwrite support: " << cpp_strerror(r)
337 << dendl;
338 complete(r);
339 return;
340 }
341
342 create_id_object();
343}
344
345template<typename I>
346void CreateRequest<I>::create_id_object() {
347 ldout(m_cct, 20) << dendl;
348
349 librados::ObjectWriteOperation op;
350 op.create(true);
351 cls_client::set_id(&op, m_image_id);
352
353 using klass = CreateRequest<I>;
354 librados::AioCompletion *comp =
355 create_rados_callback<klass, &klass::handle_create_id_object>(this);
356 int r = m_ioctx.aio_operate(m_id_obj, comp, &op);
357 assert(r == 0);
358 comp->release();
359}
360
361template<typename I>
362void CreateRequest<I>::handle_create_id_object(int r) {
363 ldout(m_cct, 20) << "r=" << r << dendl;
364
365 if (r < 0) {
366 lderr(m_cct) << "error creating RBD id object: " << cpp_strerror(r)
367 << dendl;
368 complete(r);
369 return;
370 }
371
372 add_image_to_directory();
373}
374
375template<typename I>
376void CreateRequest<I>::add_image_to_directory() {
377 ldout(m_cct, 20) << dendl;
378
379 librados::ObjectWriteOperation op;
380 cls_client::dir_add_image(&op, m_image_name, m_image_id);
381
382 using klass = CreateRequest<I>;
383 librados::AioCompletion *comp =
384 create_rados_callback<klass, &klass::handle_add_image_to_directory>(this);
385 int r = m_ioctx.aio_operate(RBD_DIRECTORY, comp, &op);
386 assert(r == 0);
387 comp->release();
388}
389
390template<typename I>
391void CreateRequest<I>::handle_add_image_to_directory(int r) {
392 ldout(m_cct, 20) << "r=" << r << dendl;
393
394 if (r < 0) {
395 lderr(m_cct) << "error adding image to directory: " << cpp_strerror(r)
396 << dendl;
397
398 m_r_saved = r;
399 remove_id_object();
400 }
401
402 negotiate_features();
403}
404
405template<typename I>
406void CreateRequest<I>::negotiate_features() {
407 if (!m_negotiate_features) {
408 create_image();
409 return;
410 }
411
412 ldout(m_cct, 20) << dendl;
413
414 librados::ObjectReadOperation op;
415 cls_client::get_all_features_start(&op);
416
417 using klass = CreateRequest<I>;
418 librados::AioCompletion *comp =
419 create_rados_callback<klass, &klass::handle_negotiate_features>(this);
420
421 m_outbl.clear();
422 int r = m_ioctx.aio_operate(RBD_DIRECTORY, comp, &op, &m_outbl);
423 assert(r == 0);
424 comp->release();
425}
426
427template<typename I>
428void CreateRequest<I>::handle_negotiate_features(int r) {
429 ldout(m_cct, 20) << "r=" << r << dendl;
430
431 uint64_t all_features;
432 if (r >= 0) {
433 bufferlist::iterator it = m_outbl.begin();
434 r = cls_client::get_all_features_finish(&it, &all_features);
435 }
436 if (r < 0) {
437 ldout(m_cct, 10) << "error retrieving server supported features set: "
438 << cpp_strerror(r) << dendl;
439 } else if ((m_features & all_features) != m_features) {
440 m_features &= all_features;
441 ldout(m_cct, 10) << "limiting default features set to server supported: "
442 << m_features << dendl;
443 }
444
445 create_image();
446}
447
448template<typename I>
449void CreateRequest<I>::create_image() {
450 ldout(m_cct, 20) << dendl;
451 assert(m_data_pool.empty() || m_data_pool_id != -1);
452
453 ostringstream oss;
454 oss << RBD_DATA_PREFIX;
455 if (m_data_pool_id != -1) {
456 oss << stringify(m_ioctx.get_id()) << ".";
457 }
458 oss << m_image_id;
459 if (oss.str().length() > RBD_MAX_BLOCK_NAME_PREFIX_LENGTH) {
460 lderr(m_cct) << "object prefix '" << oss.str() << "' too large" << dendl;
461 complete(-EINVAL);
462 return;
463 }
464
465 librados::ObjectWriteOperation op;
466 op.create(true);
467 cls_client::create_image(&op, m_size, m_order, m_features, oss.str(),
468 m_data_pool_id);
469
470 using klass = CreateRequest<I>;
471 librados::AioCompletion *comp =
472 create_rados_callback<klass, &klass::handle_create_image>(this);
473 int r = m_ioctx.aio_operate(m_header_obj, comp, &op);
474 assert(r == 0);
475 comp->release();
476}
477
478template<typename I>
479void CreateRequest<I>::handle_create_image(int r) {
480 ldout(m_cct, 20) << "r=" << r << dendl;
481
482 if (r < 0) {
483 lderr(m_cct) << "error writing header: " << cpp_strerror(r) << dendl;
484 m_r_saved = r;
485 remove_from_dir();
486 return;
487 }
488
489 set_stripe_unit_count();
490}
491
492template<typename I>
493void CreateRequest<I>::set_stripe_unit_count() {
494 if ((!m_stripe_unit && !m_stripe_count) ||
495 ((m_stripe_count == 1) && (m_stripe_unit == (1ull << m_order)))) {
496 object_map_resize();
497 return;
498 }
499
500 ldout(m_cct, 20) << dendl;
501
502 librados::ObjectWriteOperation op;
503 cls_client::set_stripe_unit_count(&op, m_stripe_unit, m_stripe_count);
504
505 using klass = CreateRequest<I>;
506 librados::AioCompletion *comp =
507 create_rados_callback<klass, &klass::handle_set_stripe_unit_count>(this);
508 int r = m_ioctx.aio_operate(m_header_obj, comp, &op);
509 assert(r == 0);
510 comp->release();
511}
512
513template<typename I>
514void CreateRequest<I>::handle_set_stripe_unit_count(int r) {
515 ldout(m_cct, 20) << "r=" << r << dendl;
516
517 if (r < 0) {
518 lderr(m_cct) << "error setting stripe unit/count: "
519 << cpp_strerror(r) << dendl;
520 m_r_saved = r;
521 remove_header_object();
522 return;
523 }
524
525 object_map_resize();
526}
527
528template<typename I>
529void CreateRequest<I>::object_map_resize() {
530 if ((m_features & RBD_FEATURE_OBJECT_MAP) == 0) {
531 fetch_mirror_mode();
532 return;
533 }
534
535 ldout(m_cct, 20) << dendl;
536
537 librados::ObjectWriteOperation op;
538 cls_client::object_map_resize(&op, Striper::get_num_objects(m_layout, m_size),
539 OBJECT_NONEXISTENT);
540
541 using klass = CreateRequest<I>;
542 librados::AioCompletion *comp =
543 create_rados_callback<klass, &klass::handle_object_map_resize>(this);
544 int r = m_ioctx.aio_operate(m_objmap_name, comp, &op);
545 assert(r == 0);
546 comp->release();
547}
548
549template<typename I>
550void CreateRequest<I>::handle_object_map_resize(int r) {
551 ldout(m_cct, 20) << "r=" << r << dendl;
552
553 if (r < 0) {
554 lderr(m_cct) << "error creating initial object map: "
555 << cpp_strerror(r) << dendl;
556
557 m_r_saved = r;
558 remove_header_object();
559 return;
560 }
561
562 fetch_mirror_mode();
563}
564
565template<typename I>
566void CreateRequest<I>::fetch_mirror_mode() {
567 if ((m_features & RBD_FEATURE_JOURNALING) == 0) {
568 complete(0);
569 return;
570 }
571
572 ldout(m_cct, 20) << dendl;
573
574 librados::ObjectReadOperation op;
575 cls_client::mirror_mode_get_start(&op);
576
577 using klass = CreateRequest<I>;
578 librados::AioCompletion *comp =
579 create_rados_callback<klass, &klass::handle_fetch_mirror_mode>(this);
580 m_outbl.clear();
581 int r = m_ioctx.aio_operate(RBD_MIRRORING, comp, &op, &m_outbl);
582 assert(r == 0);
583 comp->release();
584}
585
586template<typename I>
587void CreateRequest<I>::handle_fetch_mirror_mode(int r) {
588 ldout(m_cct, 20) << "r=" << r << dendl;
589
590 if ((r < 0) && (r != -ENOENT)) {
591 lderr(m_cct) << "failed to retrieve mirror mode: " << cpp_strerror(r)
592 << dendl;
593
594 m_r_saved = r;
595 remove_object_map();
596 return;
597 }
598
599 cls::rbd::MirrorMode mirror_mode_internal = cls::rbd::MIRROR_MODE_DISABLED;
600 if (r == 0) {
601 bufferlist::iterator it = m_outbl.begin();
602 r = cls_client::mirror_mode_get_finish(&it, &mirror_mode_internal);
603 if (r < 0) {
604 lderr(m_cct) << "Failed to retrieve mirror mode" << dendl;
605
606 m_r_saved = r;
607 remove_object_map();
608 return;
609 }
610 }
611
612 // TODO: remove redundant code...
613 switch (mirror_mode_internal) {
614 case cls::rbd::MIRROR_MODE_DISABLED:
615 case cls::rbd::MIRROR_MODE_IMAGE:
616 case cls::rbd::MIRROR_MODE_POOL:
617 m_mirror_mode = static_cast<rbd_mirror_mode_t>(mirror_mode_internal);
618 break;
619 default:
620 lderr(m_cct) << "Unknown mirror mode ("
621 << static_cast<uint32_t>(mirror_mode_internal) << ")" << dendl;
622 r = -EINVAL;
623 remove_object_map();
624 return;
625 }
626
627 journal_create();
628}
629
630template<typename I>
631void CreateRequest<I>::journal_create() {
632 ldout(m_cct, 20) << dendl;
633
634 using klass = CreateRequest<I>;
635 Context *ctx = create_context_callback<klass, &klass::handle_journal_create>(
636 this);
637
638 librbd::journal::TagData tag_data;
639 tag_data.mirror_uuid = (m_force_non_primary ? m_primary_mirror_uuid :
640 librbd::Journal<I>::LOCAL_MIRROR_UUID);
641
642 librbd::journal::CreateRequest<I> *req =
643 librbd::journal::CreateRequest<I>::create(
644 m_ioctx, m_image_id, m_journal_order, m_journal_splay_width,
645 m_journal_pool, cls::journal::Tag::TAG_CLASS_NEW, tag_data,
646 librbd::Journal<I>::IMAGE_CLIENT_ID, m_op_work_queue, ctx);
647 req->send();
648}
649
650template<typename I>
651void CreateRequest<I>::handle_journal_create(int r) {
652 ldout(m_cct, 20) << "r=" << r << dendl;
653
654 if (r < 0) {
655 lderr(m_cct) << "error creating journal: " << cpp_strerror(r)
656 << dendl;
657
658 m_r_saved = r;
659 remove_object_map();
660 return;
661 }
662
663 mirror_image_enable();
664}
665
666template<typename I>
667void CreateRequest<I>::mirror_image_enable() {
668 if (((m_mirror_mode != RBD_MIRROR_MODE_POOL) && !m_force_non_primary) ||
669 m_skip_mirror_enable) {
670 complete(0);
671 return;
672 }
673
674 ldout(m_cct, 20) << dendl;
675 auto ctx = create_context_callback<
676 CreateRequest<I>, &CreateRequest<I>::handle_mirror_image_enable>(this);
677 auto req = mirror::EnableRequest<I>::create(m_ioctx, m_image_id,
678 m_non_primary_global_image_id,
679 m_op_work_queue, ctx);
680 req->send();
681}
682
683template<typename I>
684void CreateRequest<I>::handle_mirror_image_enable(int r) {
685 ldout(m_cct, 20) << "r=" << r << dendl;
686
687 if (r < 0) {
688 lderr(m_cct) << "cannot enable mirroring: " << cpp_strerror(r)
689 << dendl;
690
691 m_r_saved = r;
692 journal_remove();
693 return;
694 }
695
696 complete(0);
697}
698
699template<typename I>
700void CreateRequest<I>::complete(int r) {
701 ldout(m_cct, 20) << dendl;
702
703 if (r == 0) {
704 ldout(m_cct, 20) << "done." << dendl;
705 }
706
707 m_data_io_ctx.close();
91327a77 708 auto on_finish = m_on_finish;
7c673cae 709 delete this;
91327a77 710 on_finish->complete(r);
7c673cae
FG
711}
712
713// cleanup
714template<typename I>
715void CreateRequest<I>::journal_remove() {
716 if ((m_features & RBD_FEATURE_JOURNALING) == 0) {
717 remove_object_map();
718 return;
719 }
720
721 ldout(m_cct, 20) << dendl;
722
723 using klass = CreateRequest<I>;
724 Context *ctx = create_context_callback<klass, &klass::handle_journal_remove>(
725 this);
726
727 librbd::journal::RemoveRequest<I> *req =
728 librbd::journal::RemoveRequest<I>::create(
729 m_ioctx, m_image_id, librbd::Journal<I>::IMAGE_CLIENT_ID, m_op_work_queue,
730 ctx);
731 req->send();
732}
733
734template<typename I>
735void CreateRequest<I>::handle_journal_remove(int r) {
736 ldout(m_cct, 20) << "r=" << r << dendl;
737
738 if (r < 0) {
739 lderr(m_cct) << "error cleaning up journal after creation failed: "
740 << cpp_strerror(r) << dendl;
741 }
742
743 remove_object_map();
744}
745
746template<typename I>
747void CreateRequest<I>::remove_object_map() {
748 if ((m_features & RBD_FEATURE_OBJECT_MAP) == 0) {
749 remove_header_object();
750 return;
751 }
752
753 ldout(m_cct, 20) << dendl;
754
755 using klass = CreateRequest<I>;
756 librados::AioCompletion *comp =
757 create_rados_callback<klass, &klass::handle_remove_object_map>(this);
758 int r = m_ioctx.aio_remove(m_objmap_name, comp);
759 assert(r == 0);
760 comp->release();
761}
762
763template<typename I>
764void CreateRequest<I>::handle_remove_object_map(int r) {
765 ldout(m_cct, 20) << "r=" << r << dendl;
766
767 if (r < 0) {
768 lderr(m_cct) << "error cleaning up object map after creation failed: "
769 << cpp_strerror(r) << dendl;
770 }
771
772 remove_header_object();
773}
774
775template<typename I>
776void CreateRequest<I>::remove_header_object() {
777 ldout(m_cct, 20) << dendl;
778
779 using klass = CreateRequest<I>;
780 librados::AioCompletion *comp =
781 create_rados_callback<klass, &klass::handle_remove_header_object>(this);
782 int r = m_ioctx.aio_remove(m_header_obj, comp);
783 assert(r == 0);
784 comp->release();
785}
786
787template<typename I>
788void CreateRequest<I>::handle_remove_header_object(int r) {
789 ldout(m_cct, 20) << "r=" << r << dendl;
790
791 if (r < 0) {
792 lderr(m_cct) << "error cleaning up image header after creation failed: "
793 << cpp_strerror(r) << dendl;
794 }
795
796 remove_from_dir();
797}
798
799template<typename I>
800void CreateRequest<I>::remove_from_dir() {
801 ldout(m_cct, 20) << dendl;
802
803 librados::ObjectWriteOperation op;
804 cls_client::dir_remove_image(&op, m_image_name, m_image_id);
805
806 using klass = CreateRequest<I>;
807 librados::AioCompletion *comp =
808 create_rados_callback<klass, &klass::handle_remove_from_dir>(this);
809 int r = m_ioctx.aio_operate(RBD_DIRECTORY, comp, &op);
810 assert(r == 0);
811 comp->release();
812}
813
814template<typename I>
815void CreateRequest<I>::handle_remove_from_dir(int r) {
816 ldout(m_cct, 20) << "r=" << r << dendl;
817
818 if (r < 0) {
819 lderr(m_cct) << "error cleaning up image from rbd_directory object "
820 << "after creation failed: " << cpp_strerror(r) << dendl;
821 }
822
823 remove_id_object();
824}
825
826template<typename I>
827void CreateRequest<I>::remove_id_object() {
828 ldout(m_cct, 20) << dendl;
829
830 using klass = CreateRequest<I>;
831 librados::AioCompletion *comp =
832 create_rados_callback<klass, &klass::handle_remove_id_object>(this);
833 int r = m_ioctx.aio_remove(m_id_obj, comp);
834 assert(r == 0);
835 comp->release();
836}
837
838template<typename I>
839void CreateRequest<I>::handle_remove_id_object(int r) {
840 ldout(m_cct, 20) << "r=" << r << dendl;
841
842 if (r < 0) {
843 lderr(m_cct) << "error cleaning up id object after creation failed: "
844 << cpp_strerror(r) << dendl;
845 }
846
847 complete(m_r_saved);
848}
849
850} //namespace image
851} //namespace librbd
852
853template class librbd::image::CreateRequest<librbd::ImageCtx>;