]> git.proxmox.com Git - ceph.git/blame - ceph/src/tools/rbd_mirror/image_replayer/CreateImageRequest.cc
update sources to v12.1.3
[ceph.git] / ceph / src / tools / rbd_mirror / image_replayer / CreateImageRequest.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 "CreateImageRequest.h"
5#include "CloseImageRequest.h"
6#include "OpenImageRequest.h"
7#include "common/errno.h"
8#include "common/WorkQueue.h"
9#include "cls/rbd/cls_rbd_client.h"
10#include "librbd/ImageCtx.h"
11#include "librbd/ImageState.h"
12#include "librbd/internal.h"
13#include "librbd/Utils.h"
14#include "librbd/image/CreateRequest.h"
15#include "librbd/image/CloneRequest.h"
16
17#define dout_context g_ceph_context
18#define dout_subsys ceph_subsys_rbd_mirror
19#undef dout_prefix
20#define dout_prefix *_dout << "rbd::mirror::image_replayer::CreateImageRequest: " \
21 << this << " " << __func__
22
23using librbd::util::create_context_callback;
24using librbd::util::create_rados_callback;
25
26namespace rbd {
27namespace mirror {
28namespace image_replayer {
29
30template <typename I>
31CreateImageRequest<I>::CreateImageRequest(librados::IoCtx &local_io_ctx,
32 ContextWQ *work_queue,
33 const std::string &global_image_id,
34 const std::string &remote_mirror_uuid,
35 const std::string &local_image_name,
d2e6a577 36 const std::string &local_image_id,
7c673cae 37 I *remote_image_ctx,
7c673cae
FG
38 Context *on_finish)
39 : m_local_io_ctx(local_io_ctx), m_work_queue(work_queue),
40 m_global_image_id(global_image_id),
41 m_remote_mirror_uuid(remote_mirror_uuid),
d2e6a577
FG
42 m_local_image_name(local_image_name), m_local_image_id(local_image_id),
43 m_remote_image_ctx(remote_image_ctx), m_on_finish(on_finish) {
7c673cae
FG
44}
45
46template <typename I>
47void CreateImageRequest<I>::send() {
48 int r = validate_parent();
49 if (r < 0) {
50 error(r);
51 return;
52 }
53
54 if (m_remote_parent_spec.pool_id == -1) {
55 create_image();
56 } else {
57 get_parent_global_image_id();
58 }
59}
60
61template <typename I>
62void CreateImageRequest<I>::create_image() {
63 dout(20) << dendl;
64
65 using klass = CreateImageRequest<I>;
66 Context *ctx = create_context_callback<klass, &klass::handle_create_image>(this);
67
68 RWLock::RLocker snap_locker(m_remote_image_ctx->snap_lock);
69
70 librbd::ImageOptions image_options;
71 image_options.set(RBD_IMAGE_OPTION_FEATURES, m_remote_image_ctx->features);
72 image_options.set(RBD_IMAGE_OPTION_ORDER, m_remote_image_ctx->order);
73 image_options.set(RBD_IMAGE_OPTION_STRIPE_UNIT,
74 m_remote_image_ctx->stripe_unit);
75 image_options.set(RBD_IMAGE_OPTION_STRIPE_COUNT,
76 m_remote_image_ctx->stripe_count);
77
7c673cae 78 librbd::image::CreateRequest<I> *req = librbd::image::CreateRequest<I>::create(
d2e6a577 79 m_local_io_ctx, m_local_image_name, m_local_image_id,
7c673cae
FG
80 m_remote_image_ctx->size, image_options, m_global_image_id,
81 m_remote_mirror_uuid, false, m_remote_image_ctx->op_work_queue, ctx);
82 req->send();
83}
84
85template <typename I>
86void CreateImageRequest<I>::handle_create_image(int r) {
87 dout(20) << ": r=" << r << dendl;
88 if (r < 0) {
89 derr << ": failed to create local image: " << cpp_strerror(r) << dendl;
90 finish(r);
91 return;
92 }
93
94 finish(0);
95}
96
97template <typename I>
98void CreateImageRequest<I>::get_parent_global_image_id() {
99 dout(20) << dendl;
100
101 librados::ObjectReadOperation op;
102 librbd::cls_client::mirror_image_get_start(&op, m_remote_parent_spec.image_id);
103
104 librados::AioCompletion *aio_comp = create_rados_callback<
105 CreateImageRequest<I>,
106 &CreateImageRequest<I>::handle_get_parent_global_image_id>(this);
107 m_out_bl.clear();
108 int r = m_remote_parent_io_ctx.aio_operate(RBD_MIRRORING, aio_comp, &op,
109 &m_out_bl);
110 assert(r == 0);
111 aio_comp->release();
112}
113
114template <typename I>
115void CreateImageRequest<I>::handle_get_parent_global_image_id(int r) {
116 dout(20) << ": r=" << r << dendl;
117 if (r == 0) {
118 cls::rbd::MirrorImage mirror_image;
119 bufferlist::iterator iter = m_out_bl.begin();
120 r = librbd::cls_client::mirror_image_get_finish(&iter, &mirror_image);
121 if (r == 0) {
122 m_parent_global_image_id = mirror_image.global_image_id;
123 dout(20) << ": parent_global_image_id=" << m_parent_global_image_id
124 << dendl;
125 }
126 }
127
128 if (r == -ENOENT) {
129 dout(10) << ": parent image " << m_remote_parent_spec.image_id << " not mirrored"
130 << dendl;
131 finish(r);
132 return;
133 } else if (r < 0) {
134 derr << ": failed to retrieve global image id for parent image "
135 << m_remote_parent_spec.image_id << ": " << cpp_strerror(r) << dendl;
136 finish(r);
137 return;
138 }
139
140 get_local_parent_image_id();
141}
142
143template <typename I>
144void CreateImageRequest<I>::get_local_parent_image_id() {
145 dout(20) << dendl;
146
147 librados::ObjectReadOperation op;
148 librbd::cls_client::mirror_image_get_image_id_start(
149 &op, m_parent_global_image_id);
150
151 librados::AioCompletion *aio_comp = create_rados_callback<
152 CreateImageRequest<I>,
153 &CreateImageRequest<I>::handle_get_local_parent_image_id>(this);
154 m_out_bl.clear();
155 int r = m_local_parent_io_ctx.aio_operate(RBD_MIRRORING, aio_comp, &op,
156 &m_out_bl);
157 assert(r == 0);
158 aio_comp->release();
159}
160
161template <typename I>
162void CreateImageRequest<I>::handle_get_local_parent_image_id(int r) {
163 dout(20) << ": r=" << r << dendl;
164
165 if (r == 0) {
166 bufferlist::iterator iter = m_out_bl.begin();
167 r = librbd::cls_client::mirror_image_get_image_id_finish(
168 &iter, &m_local_parent_spec.image_id);
169 }
170
171 if (r == -ENOENT) {
172 dout(10) << ": parent image " << m_parent_global_image_id << " not "
173 << "registered locally" << dendl;
174 finish(r);
175 return;
176 } else if (r < 0) {
177 derr << ": failed to retrieve local image id for parent image "
178 << m_parent_global_image_id << ": " << cpp_strerror(r) << dendl;
179 finish(r);
180 return;
181 }
182
183 open_remote_parent_image();
184}
185
186template <typename I>
187void CreateImageRequest<I>::open_remote_parent_image() {
188 dout(20) << dendl;
189
190 Context *ctx = create_context_callback<
191 CreateImageRequest<I>,
192 &CreateImageRequest<I>::handle_open_remote_parent_image>(this);
193 OpenImageRequest<I> *request = OpenImageRequest<I>::create(
194 m_remote_parent_io_ctx, &m_remote_parent_image_ctx,
195 m_remote_parent_spec.image_id, true, ctx);
196 request->send();
197}
198
199template <typename I>
200void CreateImageRequest<I>::handle_open_remote_parent_image(int r) {
201 dout(20) << ": r=" << r << dendl;
202 if (r < 0) {
203 derr << ": failed to open remote parent image " << m_parent_pool_name << "/"
204 << m_remote_parent_spec.image_id << dendl;
205 finish(r);
206 return;
207 }
208
209 open_local_parent_image();
210}
211
212template <typename I>
213void CreateImageRequest<I>::open_local_parent_image() {
214 dout(20) << dendl;
215
216 Context *ctx = create_context_callback<
217 CreateImageRequest<I>,
218 &CreateImageRequest<I>::handle_open_local_parent_image>(this);
219 OpenImageRequest<I> *request = OpenImageRequest<I>::create(
220 m_local_parent_io_ctx, &m_local_parent_image_ctx,
221 m_local_parent_spec.image_id, true, ctx);
222 request->send();
223}
224
225template <typename I>
226void CreateImageRequest<I>::handle_open_local_parent_image(int r) {
227 dout(20) << ": r=" << r << dendl;
228 if (r < 0) {
229 derr << ": failed to open local parent image " << m_parent_pool_name << "/"
230 << m_local_parent_spec.image_id << dendl;
231 m_ret_val = r;
232 close_remote_parent_image();
233 return;
234 }
235
236 set_local_parent_snap();
237}
238
239template <typename I>
240void CreateImageRequest<I>::set_local_parent_snap() {
241 dout(20) << dendl;
242
243 {
244 RWLock::RLocker remote_snap_locker(m_remote_parent_image_ctx->snap_lock);
245 auto it = m_remote_parent_image_ctx->snap_info.find(
246 m_remote_parent_spec.snap_id);
247 if (it != m_remote_parent_image_ctx->snap_info.end()) {
248 m_parent_snap_name = it->second.name;
249 }
250 }
251
252 if (m_parent_snap_name.empty()) {
253 m_ret_val = -ENOENT;
254 close_local_parent_image();
255 return;
256 }
257 dout(20) << ": parent_snap_name=" << m_parent_snap_name << dendl;
258
259 Context *ctx = create_context_callback<
260 CreateImageRequest<I>,
261 &CreateImageRequest<I>::handle_set_local_parent_snap>(this);
262 m_local_parent_image_ctx->state->snap_set(cls::rbd::UserSnapshotNamespace(),
263 m_parent_snap_name,
264 ctx);
265}
266
267template <typename I>
268void CreateImageRequest<I>::handle_set_local_parent_snap(int r) {
269 dout(20) << ": r=" << r << dendl;
270 if (r < 0) {
271 derr << ": failed to set parent snapshot " << m_parent_snap_name
272 << ": " << cpp_strerror(r) << dendl;
273 m_ret_val = r;
274 close_local_parent_image();
275 return;
276 }
277
278 clone_image();
279}
280
281template <typename I>
282void CreateImageRequest<I>::clone_image() {
283 dout(20) << dendl;
284
285 librbd::ImageOptions opts;
286 opts.set(RBD_IMAGE_OPTION_FEATURES, m_remote_image_ctx->features);
287 opts.set(RBD_IMAGE_OPTION_ORDER, m_remote_image_ctx->order);
288 opts.set(RBD_IMAGE_OPTION_STRIPE_UNIT, m_remote_image_ctx->stripe_unit);
289 opts.set(RBD_IMAGE_OPTION_STRIPE_COUNT, m_remote_image_ctx->stripe_count);
290
7c673cae
FG
291 using klass = CreateImageRequest<I>;
292 Context *ctx = create_context_callback<klass, &klass::handle_clone_image>(this);
293
294 librbd::image::CloneRequest<I> *req = librbd::image::CloneRequest<I>::create(
295 m_local_parent_image_ctx, m_local_io_ctx, m_local_image_name,
d2e6a577 296 m_local_image_id, opts, m_global_image_id, m_remote_mirror_uuid,
7c673cae
FG
297 m_remote_image_ctx->op_work_queue, ctx);
298 req->send();
299}
300
301template <typename I>
302void CreateImageRequest<I>::handle_clone_image(int r) {
303 dout(20) << ": r=" << r << dendl;
304 if (r < 0) {
305 derr << ": failed to clone image " << m_parent_pool_name << "/"
306 << m_local_parent_image_ctx->name << " to "
307 << m_local_image_name << dendl;
308 m_ret_val = r;
309 }
310
311 close_local_parent_image();
312}
313
314template <typename I>
315void CreateImageRequest<I>::close_local_parent_image() {
316 dout(20) << dendl;
317 Context *ctx = create_context_callback<
318 CreateImageRequest<I>,
319 &CreateImageRequest<I>::handle_close_local_parent_image>(this);
320 CloseImageRequest<I> *request = CloseImageRequest<I>::create(
321 &m_local_parent_image_ctx, ctx);
322 request->send();
323}
324
325template <typename I>
326void CreateImageRequest<I>::handle_close_local_parent_image(int r) {
327 dout(20) << ": r=" << r << dendl;
328 if (r < 0) {
329 derr << ": error encountered closing local parent image: "
330 << cpp_strerror(r) << dendl;
331 }
332
333 close_remote_parent_image();
334}
335
336template <typename I>
337void CreateImageRequest<I>::close_remote_parent_image() {
338 dout(20) << dendl;
339 Context *ctx = create_context_callback<
340 CreateImageRequest<I>,
341 &CreateImageRequest<I>::handle_close_remote_parent_image>(this);
342 CloseImageRequest<I> *request = CloseImageRequest<I>::create(
343 &m_remote_parent_image_ctx, ctx);
344 request->send();
345}
346
347template <typename I>
348void CreateImageRequest<I>::handle_close_remote_parent_image(int r) {
349 dout(20) << ": r=" << r << dendl;
350 if (r < 0) {
351 derr << ": error encountered closing remote parent image: "
352 << cpp_strerror(r) << dendl;
353 }
354
355 finish(m_ret_val);
356}
357
358template <typename I>
359void CreateImageRequest<I>::error(int r) {
360 dout(20) << ": r=" << r << dendl;
361
362 m_work_queue->queue(create_context_callback<
363 CreateImageRequest<I>, &CreateImageRequest<I>::finish>(this), r);
364}
365
366template <typename I>
367void CreateImageRequest<I>::finish(int r) {
368 dout(20) << ": r=" << r << dendl;
369 m_on_finish->complete(r);
370 delete this;
371}
372
373template <typename I>
374int CreateImageRequest<I>::validate_parent() {
375 RWLock::RLocker owner_locker(m_remote_image_ctx->owner_lock);
376 RWLock::RLocker snap_locker(m_remote_image_ctx->snap_lock);
377
378 m_remote_parent_spec = m_remote_image_ctx->parent_md.spec;
379
380 // scan all remote snapshots for a linked parent
381 for (auto &snap_info_pair : m_remote_image_ctx->snap_info) {
382 auto &parent_spec = snap_info_pair.second.parent.spec;
383 if (parent_spec.pool_id == -1) {
384 continue;
385 } else if (m_remote_parent_spec.pool_id == -1) {
386 m_remote_parent_spec = parent_spec;
387 continue;
388 }
389
390 if (m_remote_parent_spec != parent_spec) {
391 derr << ": remote image parent spec mismatch" << dendl;
392 return -EINVAL;
393 }
394 }
395
396 if (m_remote_parent_spec.pool_id == -1) {
397 return 0;
398 }
399
400 // map remote parent pool to local parent pool
401 librados::Rados remote_rados(m_remote_image_ctx->md_ctx);
402 int r = remote_rados.ioctx_create2(m_remote_parent_spec.pool_id,
403 m_remote_parent_io_ctx);
404 if (r < 0) {
405 derr << ": failed to open remote parent pool " << m_remote_parent_spec.pool_id
406 << ": " << cpp_strerror(r) << dendl;
407 return r;
408 }
409
410 m_parent_pool_name = m_remote_parent_io_ctx.get_pool_name();
411
412 librados::Rados local_rados(m_local_io_ctx);
413 r = local_rados.ioctx_create(m_parent_pool_name.c_str(),
414 m_local_parent_io_ctx);
415 if (r < 0) {
416 derr << ": failed to open local parent pool " << m_parent_pool_name << ": "
417 << cpp_strerror(r) << dendl;
418 return r;
419 }
420
421 return 0;
422}
423
424} // namespace image_replayer
425} // namespace mirror
426} // namespace rbd
427
428template class rbd::mirror::image_replayer::CreateImageRequest<librbd::ImageCtx>;