]> git.proxmox.com Git - ceph.git/blame - ceph/src/tools/rbd_mirror/image_replayer/BootstrapRequest.cc
bump version to 18.2.2-pve1
[ceph.git] / ceph / src / tools / rbd_mirror / image_replayer / BootstrapRequest.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 "include/compat.h"
5#include "BootstrapRequest.h"
7c673cae 6#include "CreateImageRequest.h"
7c673cae
FG
7#include "OpenImageRequest.h"
8#include "OpenLocalImageRequest.h"
9#include "common/debug.h"
10#include "common/dout.h"
11#include "common/errno.h"
7c673cae
FG
12#include "cls/rbd/cls_rbd_client.h"
13#include "journal/Journaler.h"
9f95a23c 14#include "journal/Settings.h"
7c673cae
FG
15#include "librbd/ImageCtx.h"
16#include "librbd/ImageState.h"
17#include "librbd/internal.h"
18#include "librbd/Journal.h"
19#include "librbd/Utils.h"
f67539c2 20#include "librbd/asio/ContextWQ.h"
7c673cae 21#include "librbd/journal/Types.h"
9f95a23c 22#include "tools/rbd_mirror/BaseRequest.h"
31f18b77 23#include "tools/rbd_mirror/ImageSync.h"
9f95a23c 24#include "tools/rbd_mirror/ProgressContext.h"
11fdf7f2 25#include "tools/rbd_mirror/Threads.h"
9f95a23c
TL
26#include "tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.h"
27#include "tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h"
28#include "tools/rbd_mirror/image_replayer/journal/StateBuilder.h"
29#include "tools/rbd_mirror/image_replayer/journal/SyncPointHandler.h"
7c673cae
FG
30
31#define dout_context g_ceph_context
32#define dout_subsys ceph_subsys_rbd_mirror
33#undef dout_prefix
9f95a23c
TL
34#define dout_prefix *_dout << "rbd::mirror::image_replayer::" \
35 << "BootstrapRequest: " << this << " " \
36 << __func__ << ": "
7c673cae
FG
37
38namespace rbd {
39namespace mirror {
40namespace image_replayer {
41
42using librbd::util::create_context_callback;
7c673cae
FG
43using librbd::util::unique_lock_name;
44
45template <typename I>
46BootstrapRequest<I>::BootstrapRequest(
9f95a23c
TL
47 Threads<I>* threads,
48 librados::IoCtx& local_io_ctx,
49 librados::IoCtx& remote_io_ctx,
50 InstanceWatcher<I>* instance_watcher,
51 const std::string& global_image_id,
52 const std::string& local_mirror_uuid,
53 const RemotePoolMeta& remote_pool_meta,
54 ::journal::CacheManagerHandler* cache_manager_handler,
55 PoolMetaCache* pool_meta_cache,
56 ProgressContext* progress_ctx,
57 StateBuilder<I>** state_builder,
58 bool* do_resync,
59 Context* on_finish)
60 : CancelableRequest("rbd::mirror::image_replayer::BootstrapRequest",
61 reinterpret_cast<CephContext*>(local_io_ctx.cct()),
62 on_finish),
63 m_threads(threads),
64 m_local_io_ctx(local_io_ctx),
65 m_remote_io_ctx(remote_io_ctx),
66 m_instance_watcher(instance_watcher),
67 m_global_image_id(global_image_id),
7c673cae 68 m_local_mirror_uuid(local_mirror_uuid),
9f95a23c
TL
69 m_remote_pool_meta(remote_pool_meta),
70 m_cache_manager_handler(cache_manager_handler),
71 m_pool_meta_cache(pool_meta_cache),
72 m_progress_ctx(progress_ctx),
73 m_state_builder(state_builder),
74 m_do_resync(do_resync),
75 m_lock(ceph::make_mutex(unique_lock_name("BootstrapRequest::m_lock",
76 this))) {
11fdf7f2 77 dout(10) << dendl;
7c673cae
FG
78}
79
c07f9fc5
FG
80template <typename I>
81bool BootstrapRequest<I>::is_syncing() const {
9f95a23c 82 std::lock_guard locker{m_lock};
c07f9fc5
FG
83 return (m_image_sync != nullptr);
84}
85
7c673cae
FG
86template <typename I>
87void BootstrapRequest<I>::send() {
88 *m_do_resync = false;
89
9f95a23c 90 prepare_local_image();
7c673cae
FG
91}
92
93template <typename I>
94void BootstrapRequest<I>::cancel() {
11fdf7f2 95 dout(10) << dendl;
7c673cae 96
9f95a23c 97 std::lock_guard locker{m_lock};
7c673cae
FG
98 m_canceled = true;
99
31f18b77
FG
100 if (m_image_sync != nullptr) {
101 m_image_sync->cancel();
102 }
7c673cae
FG
103}
104
105template <typename I>
9f95a23c
TL
106std::string BootstrapRequest<I>::get_local_image_name() const {
107 std::unique_lock locker{m_lock};
108 return m_local_image_name;
7c673cae
FG
109}
110
111template <typename I>
9f95a23c
TL
112void BootstrapRequest<I>::prepare_local_image() {
113 dout(10) << dendl;
114 update_progress("PREPARE_LOCAL_IMAGE");
7c673cae 115
9f95a23c
TL
116 {
117 std::unique_lock locker{m_lock};
118 m_local_image_name = m_global_image_id;
7c673cae
FG
119 }
120
9f95a23c
TL
121 ceph_assert(*m_state_builder == nullptr);
122 auto ctx = create_context_callback<
123 BootstrapRequest, &BootstrapRequest<I>::handle_prepare_local_image>(this);
124 auto req = image_replayer::PrepareLocalImageRequest<I>::create(
125 m_local_io_ctx, m_global_image_id, &m_prepare_local_image_name,
126 m_state_builder, m_threads->work_queue, ctx);
127 req->send();
128}
129
130template <typename I>
131void BootstrapRequest<I>::handle_prepare_local_image(int r) {
132 dout(10) << "r=" << r << dendl;
133
134 ceph_assert(r < 0 || *m_state_builder != nullptr);
135 if (r == -ENOENT) {
136 dout(10) << "local image does not exist" << dendl;
137 } else if (r < 0) {
2a845540 138 derr << "error preparing local image for replay: " << cpp_strerror(r)
7c673cae 139 << dendl;
9f95a23c 140 finish(r);
7c673cae
FG
141 return;
142 }
143
9f95a23c
TL
144 // image replayer will detect the name change (if any) at next
145 // status update
146 if (r >= 0 && !m_prepare_local_image_name.empty()) {
147 std::unique_lock locker{m_lock};
148 m_local_image_name = m_prepare_local_image_name;
7c673cae
FG
149 }
150
9f95a23c 151 prepare_remote_image();
d2e6a577
FG
152}
153
154template <typename I>
9f95a23c
TL
155void BootstrapRequest<I>::prepare_remote_image() {
156 dout(10) << dendl;
157 update_progress("PREPARE_REMOTE_IMAGE");
d2e6a577
FG
158
159 Context *ctx = create_context_callback<
9f95a23c
TL
160 BootstrapRequest, &BootstrapRequest<I>::handle_prepare_remote_image>(this);
161 auto req = image_replayer::PrepareRemoteImageRequest<I>::create(
162 m_threads, m_local_io_ctx, m_remote_io_ctx, m_global_image_id,
163 m_local_mirror_uuid, m_remote_pool_meta, m_cache_manager_handler,
164 m_state_builder, ctx);
165 req->send();
d2e6a577
FG
166}
167
168template <typename I>
9f95a23c
TL
169void BootstrapRequest<I>::handle_prepare_remote_image(int r) {
170 dout(10) << "r=" << r << dendl;
d2e6a577 171
9f95a23c
TL
172 auto state_builder = *m_state_builder;
173 ceph_assert(state_builder == nullptr ||
174 !state_builder->remote_mirror_uuid.empty());
175
176 if (state_builder != nullptr && state_builder->is_local_primary()) {
177 dout(5) << "local image is primary" << dendl;
178 finish(-ENOMSG);
179 return;
9f95a23c
TL
180 } else if (r == -ENOENT || state_builder == nullptr) {
181 dout(10) << "remote image does not exist";
182 if (state_builder != nullptr) {
183 *_dout << ": "
184 << "local_image_id=" << state_builder->local_image_id << ", "
185 << "remote_image_id=" << state_builder->remote_image_id << ", "
186 << "is_linked=" << state_builder->is_linked();
187 }
188 *_dout << dendl;
189
190 // TODO need to support multiple remote images
191 if (state_builder != nullptr &&
192 state_builder->remote_image_id.empty() &&
a4b75251
TL
193 (state_builder->local_image_id.empty() ||
194 state_builder->is_linked())) {
195 // both images doesn't exist or local image exists and is non-primary
196 // and linked to the missing remote image
9f95a23c
TL
197 finish(-ENOLINK);
198 } else {
199 finish(-ENOENT);
200 }
201 return;
202 } else if (r < 0) {
2a845540
TL
203 derr << "error preparing remote image for replay: " << cpp_strerror(r)
204 << dendl;
d2e6a577
FG
205 finish(r);
206 return;
207 }
208
2a845540
TL
209 if (!state_builder->is_remote_primary()) {
210 ceph_assert(!state_builder->remote_image_id.empty());
211 if (state_builder->local_image_id.empty()) {
212 dout(10) << "local image does not exist and remote image is not primary"
213 << dendl;
214 finish(-EREMOTEIO);
215 return;
216 } else if (!state_builder->is_linked()) {
217 dout(10) << "local image is unlinked and remote image is not primary"
218 << dendl;
219 finish(-EREMOTEIO);
220 return;
221 }
222 // if the local image is linked to the remote image, we ignore that
223 // the remote image is not primary so that we can replay demotion
224 }
225
9f95a23c 226 open_remote_image();
7c673cae
FG
227}
228
229template <typename I>
9f95a23c
TL
230void BootstrapRequest<I>::open_remote_image() {
231 ceph_assert(*m_state_builder != nullptr);
232 auto remote_image_id = (*m_state_builder)->remote_image_id;
233 dout(15) << "remote_image_id=" << remote_image_id << dendl;
7c673cae
FG
234
235 update_progress("OPEN_REMOTE_IMAGE");
236
9f95a23c
TL
237 auto ctx = create_context_callback<
238 BootstrapRequest<I>,
239 &BootstrapRequest<I>::handle_open_remote_image>(this);
240 ceph_assert(*m_state_builder != nullptr);
241 OpenImageRequest<I> *request = OpenImageRequest<I>::create(
242 m_remote_io_ctx, &(*m_state_builder)->remote_image_ctx, remote_image_id,
243 false, ctx);
7c673cae
FG
244 request->send();
245}
246
247template <typename I>
9f95a23c 248void BootstrapRequest<I>::handle_open_remote_image(int r) {
11fdf7f2 249 dout(15) << "r=" << r << dendl;
7c673cae 250
9f95a23c
TL
251 ceph_assert(*m_state_builder != nullptr);
252 if (r < 0) {
253 derr << "failed to open remote image: " << cpp_strerror(r) << dendl;
254 ceph_assert((*m_state_builder)->remote_image_ctx == nullptr);
255 finish(r);
7c673cae
FG
256 return;
257 }
258
9f95a23c
TL
259 if ((*m_state_builder)->local_image_id.empty()) {
260 create_local_image();
7c673cae
FG
261 return;
262 }
263
264 open_local_image();
265}
266
7c673cae
FG
267template <typename I>
268void BootstrapRequest<I>::open_local_image() {
9f95a23c
TL
269 ceph_assert(*m_state_builder != nullptr);
270 auto local_image_id = (*m_state_builder)->local_image_id;
271
272 dout(15) << "local_image_id=" << local_image_id << dendl;
7c673cae
FG
273
274 update_progress("OPEN_LOCAL_IMAGE");
275
276 Context *ctx = create_context_callback<
277 BootstrapRequest<I>, &BootstrapRequest<I>::handle_open_local_image>(
278 this);
279 OpenLocalImageRequest<I> *request = OpenLocalImageRequest<I>::create(
9f95a23c
TL
280 m_local_io_ctx, &(*m_state_builder)->local_image_ctx, local_image_id,
281 m_threads->work_queue, ctx);
7c673cae
FG
282 request->send();
283}
284
285template <typename I>
286void BootstrapRequest<I>::handle_open_local_image(int r) {
11fdf7f2 287 dout(15) << "r=" << r << dendl;
7c673cae 288
9f95a23c
TL
289 ceph_assert(*m_state_builder != nullptr);
290 auto local_image_ctx = (*m_state_builder)->local_image_ctx;
291 ceph_assert((r >= 0 && local_image_ctx != nullptr) ||
292 (r < 0 && local_image_ctx == nullptr));
293
7c673cae 294 if (r == -ENOENT) {
11fdf7f2 295 dout(10) << "local image missing" << dendl;
9f95a23c 296 create_local_image();
7c673cae
FG
297 return;
298 } else if (r == -EREMOTEIO) {
7c673cae
FG
299 dout(10) << "local image is primary -- skipping image replay" << dendl;
300 m_ret_val = r;
301 close_remote_image();
302 return;
303 } else if (r < 0) {
11fdf7f2 304 derr << "failed to open local image: " << cpp_strerror(r) << dendl;
7c673cae
FG
305 m_ret_val = r;
306 close_remote_image();
307 return;
308 }
309
9f95a23c 310 prepare_replay();
7c673cae
FG
311}
312
b32b8144 313template <typename I>
9f95a23c
TL
314void BootstrapRequest<I>::prepare_replay() {
315 dout(10) << dendl;
316 update_progress("PREPARE_REPLAY");
b32b8144 317
9f95a23c
TL
318 ceph_assert(*m_state_builder != nullptr);
319 auto ctx = create_context_callback<
320 BootstrapRequest<I>, &BootstrapRequest<I>::handle_prepare_replay>(this);
321 auto request = (*m_state_builder)->create_prepare_replay_request(
322 m_local_mirror_uuid, m_progress_ctx, m_do_resync, &m_syncing, ctx);
323 request->send();
b32b8144
FG
324}
325
326template <typename I>
9f95a23c
TL
327void BootstrapRequest<I>::handle_prepare_replay(int r) {
328 dout(10) << "r=" << r << dendl;
b32b8144
FG
329
330 if (r < 0) {
2a845540 331 derr << "failed to prepare local replay: " << cpp_strerror(r) << dendl;
b32b8144
FG
332 m_ret_val = r;
333 close_remote_image();
334 return;
9f95a23c
TL
335 } else if (*m_do_resync) {
336 dout(10) << "local image resync requested" << dendl;
d2e6a577 337 close_remote_image();
7c673cae 338 return;
9f95a23c
TL
339 } else if ((*m_state_builder)->is_disconnected()) {
340 dout(10) << "client flagged disconnected -- skipping bootstrap" << dendl;
341 // The caller is expected to detect disconnect initializing remote journal.
342 m_ret_val = 0;
d2e6a577 343 close_remote_image();
7c673cae 344 return;
9f95a23c
TL
345 } else if (m_syncing) {
346 dout(10) << "local image still syncing to remote image" << dendl;
347 image_sync();
348 return;
7c673cae
FG
349 }
350
9f95a23c 351 close_remote_image();
d2e6a577
FG
352}
353
354template <typename I>
355void BootstrapRequest<I>::create_local_image() {
9f95a23c 356 dout(10) << dendl;
d2e6a577
FG
357 update_progress("CREATE_LOCAL_IMAGE");
358
9f95a23c
TL
359 ceph_assert(*m_state_builder != nullptr);
360 auto ctx = create_context_callback<
361 BootstrapRequest<I>,
362 &BootstrapRequest<I>::handle_create_local_image>(this);
363 auto request = (*m_state_builder)->create_local_image_request(
364 m_threads, m_local_io_ctx, m_global_image_id, m_pool_meta_cache,
365 m_progress_ctx, ctx);
d2e6a577
FG
366 request->send();
367}
368
369template <typename I>
370void BootstrapRequest<I>::handle_create_local_image(int r) {
11fdf7f2 371 dout(15) << "r=" << r << dendl;
d2e6a577 372
9f95a23c 373 if (r < 0) {
11fdf7f2
TL
374 if (r == -ENOENT) {
375 dout(10) << "parent image does not exist" << dendl;
376 } else {
377 derr << "failed to create local image: " << cpp_strerror(r) << dendl;
378 }
d2e6a577
FG
379 m_ret_val = r;
380 close_remote_image();
381 return;
382 }
383
384 open_local_image();
7c673cae
FG
385}
386
387template <typename I>
9f95a23c
TL
388void BootstrapRequest<I>::image_sync() {
389 std::unique_lock locker{m_lock};
7c673cae 390 if (m_canceled) {
9f95a23c 391 locker.unlock();
7c673cae 392
9f95a23c
TL
393 m_ret_val = -ECANCELED;
394 dout(10) << "request canceled" << dendl;
7c673cae
FG
395 close_remote_image();
396 return;
397 }
398
9f95a23c
TL
399 dout(15) << dendl;
400 ceph_assert(m_image_sync == nullptr);
c07f9fc5 401
9f95a23c
TL
402 auto state_builder = *m_state_builder;
403 auto sync_point_handler = state_builder->create_sync_point_handler();
c07f9fc5 404
9f95a23c
TL
405 Context *ctx = create_context_callback<
406 BootstrapRequest<I>, &BootstrapRequest<I>::handle_image_sync>(this);
407 m_image_sync = ImageSync<I>::create(
408 m_threads, state_builder->local_image_ctx, state_builder->remote_image_ctx,
409 m_local_mirror_uuid, sync_point_handler, m_instance_watcher,
410 m_progress_ctx, ctx);
411 m_image_sync->get();
412 locker.unlock();
7c673cae 413
9f95a23c
TL
414 update_progress("IMAGE_SYNC");
415 m_image_sync->send();
7c673cae
FG
416}
417
418template <typename I>
419void BootstrapRequest<I>::handle_image_sync(int r) {
11fdf7f2 420 dout(15) << "r=" << r << dendl;
7c673cae 421
31f18b77 422 {
9f95a23c 423 std::lock_guard locker{m_lock};
31f18b77
FG
424 m_image_sync->put();
425 m_image_sync = nullptr;
426
9f95a23c
TL
427 (*m_state_builder)->destroy_sync_point_handler();
428 }
31f18b77 429
9f95a23c
TL
430 if (r < 0) {
431 if (r == -ECANCELED) {
432 dout(10) << "request canceled" << dendl;
433 } else {
11fdf7f2 434 derr << "failed to sync remote image: " << cpp_strerror(r) << dendl;
31f18b77 435 }
9f95a23c 436 m_ret_val = r;
7c673cae
FG
437 }
438
439 close_remote_image();
440}
441
442template <typename I>
9f95a23c
TL
443void BootstrapRequest<I>::close_remote_image() {
444 if ((*m_state_builder)->replay_requires_remote_image()) {
445 finish(m_ret_val);
446 return;
7c673cae
FG
447 }
448
11fdf7f2 449 dout(15) << dendl;
7c673cae
FG
450
451 update_progress("CLOSE_REMOTE_IMAGE");
452
9f95a23c
TL
453 auto ctx = create_context_callback<
454 BootstrapRequest<I>,
455 &BootstrapRequest<I>::handle_close_remote_image>(this);
456 ceph_assert(*m_state_builder != nullptr);
457 (*m_state_builder)->close_remote_image(ctx);
7c673cae
FG
458}
459
460template <typename I>
461void BootstrapRequest<I>::handle_close_remote_image(int r) {
11fdf7f2 462 dout(15) << "r=" << r << dendl;
7c673cae
FG
463
464 if (r < 0) {
11fdf7f2 465 derr << "error encountered closing remote image: " << cpp_strerror(r)
7c673cae
FG
466 << dendl;
467 }
468
469 finish(m_ret_val);
470}
471
7c673cae
FG
472template <typename I>
473void BootstrapRequest<I>::update_progress(const std::string &description) {
11fdf7f2 474 dout(15) << description << dendl;
7c673cae
FG
475
476 if (m_progress_ctx) {
477 m_progress_ctx->update_progress(description);
478 }
479}
480
481} // namespace image_replayer
482} // namespace mirror
483} // namespace rbd
484
485template class rbd::mirror::image_replayer::BootstrapRequest<librbd::ImageCtx>;