]> git.proxmox.com Git - ceph.git/blame - ceph/src/tools/rbd_mirror/image_replayer/BootstrapRequest.cc
import ceph 16.2.7
[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) {
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;
180 } else if (r == -EREMOTEIO) {
181 dout(10) << "remote-image is non-primary" << cpp_strerror(r) << dendl;
182 finish(r);
183 return;
184 } else if (r == -ENOENT || state_builder == nullptr) {
185 dout(10) << "remote image does not exist";
186 if (state_builder != nullptr) {
187 *_dout << ": "
188 << "local_image_id=" << state_builder->local_image_id << ", "
189 << "remote_image_id=" << state_builder->remote_image_id << ", "
190 << "is_linked=" << state_builder->is_linked();
191 }
192 *_dout << dendl;
193
194 // TODO need to support multiple remote images
195 if (state_builder != nullptr &&
196 state_builder->remote_image_id.empty() &&
a4b75251
TL
197 (state_builder->local_image_id.empty() ||
198 state_builder->is_linked())) {
199 // both images doesn't exist or local image exists and is non-primary
200 // and linked to the missing remote image
9f95a23c
TL
201 finish(-ENOLINK);
202 } else {
203 finish(-ENOENT);
204 }
205 return;
206 } else if (r < 0) {
207 derr << "error retrieving remote image id" << cpp_strerror(r) << dendl;
d2e6a577
FG
208 finish(r);
209 return;
210 }
211
9f95a23c 212 open_remote_image();
7c673cae
FG
213}
214
215template <typename I>
9f95a23c
TL
216void BootstrapRequest<I>::open_remote_image() {
217 ceph_assert(*m_state_builder != nullptr);
218 auto remote_image_id = (*m_state_builder)->remote_image_id;
219 dout(15) << "remote_image_id=" << remote_image_id << dendl;
7c673cae
FG
220
221 update_progress("OPEN_REMOTE_IMAGE");
222
9f95a23c
TL
223 auto ctx = create_context_callback<
224 BootstrapRequest<I>,
225 &BootstrapRequest<I>::handle_open_remote_image>(this);
226 ceph_assert(*m_state_builder != nullptr);
227 OpenImageRequest<I> *request = OpenImageRequest<I>::create(
228 m_remote_io_ctx, &(*m_state_builder)->remote_image_ctx, remote_image_id,
229 false, ctx);
7c673cae
FG
230 request->send();
231}
232
233template <typename I>
9f95a23c 234void BootstrapRequest<I>::handle_open_remote_image(int r) {
11fdf7f2 235 dout(15) << "r=" << r << dendl;
7c673cae 236
9f95a23c
TL
237 ceph_assert(*m_state_builder != nullptr);
238 if (r < 0) {
239 derr << "failed to open remote image: " << cpp_strerror(r) << dendl;
240 ceph_assert((*m_state_builder)->remote_image_ctx == nullptr);
241 finish(r);
7c673cae
FG
242 return;
243 }
244
9f95a23c
TL
245 if ((*m_state_builder)->local_image_id.empty()) {
246 create_local_image();
7c673cae
FG
247 return;
248 }
249
250 open_local_image();
251}
252
7c673cae
FG
253template <typename I>
254void BootstrapRequest<I>::open_local_image() {
9f95a23c
TL
255 ceph_assert(*m_state_builder != nullptr);
256 auto local_image_id = (*m_state_builder)->local_image_id;
257
258 dout(15) << "local_image_id=" << local_image_id << dendl;
7c673cae
FG
259
260 update_progress("OPEN_LOCAL_IMAGE");
261
262 Context *ctx = create_context_callback<
263 BootstrapRequest<I>, &BootstrapRequest<I>::handle_open_local_image>(
264 this);
265 OpenLocalImageRequest<I> *request = OpenLocalImageRequest<I>::create(
9f95a23c
TL
266 m_local_io_ctx, &(*m_state_builder)->local_image_ctx, local_image_id,
267 m_threads->work_queue, ctx);
7c673cae
FG
268 request->send();
269}
270
271template <typename I>
272void BootstrapRequest<I>::handle_open_local_image(int r) {
11fdf7f2 273 dout(15) << "r=" << r << dendl;
7c673cae 274
9f95a23c
TL
275 ceph_assert(*m_state_builder != nullptr);
276 auto local_image_ctx = (*m_state_builder)->local_image_ctx;
277 ceph_assert((r >= 0 && local_image_ctx != nullptr) ||
278 (r < 0 && local_image_ctx == nullptr));
279
7c673cae 280 if (r == -ENOENT) {
11fdf7f2 281 dout(10) << "local image missing" << dendl;
9f95a23c 282 create_local_image();
7c673cae
FG
283 return;
284 } else if (r == -EREMOTEIO) {
7c673cae
FG
285 dout(10) << "local image is primary -- skipping image replay" << dendl;
286 m_ret_val = r;
287 close_remote_image();
288 return;
289 } else if (r < 0) {
11fdf7f2 290 derr << "failed to open local image: " << cpp_strerror(r) << dendl;
7c673cae
FG
291 m_ret_val = r;
292 close_remote_image();
293 return;
294 }
295
9f95a23c 296 prepare_replay();
7c673cae
FG
297}
298
b32b8144 299template <typename I>
9f95a23c
TL
300void BootstrapRequest<I>::prepare_replay() {
301 dout(10) << dendl;
302 update_progress("PREPARE_REPLAY");
b32b8144 303
9f95a23c
TL
304 ceph_assert(*m_state_builder != nullptr);
305 auto ctx = create_context_callback<
306 BootstrapRequest<I>, &BootstrapRequest<I>::handle_prepare_replay>(this);
307 auto request = (*m_state_builder)->create_prepare_replay_request(
308 m_local_mirror_uuid, m_progress_ctx, m_do_resync, &m_syncing, ctx);
309 request->send();
b32b8144
FG
310}
311
312template <typename I>
9f95a23c
TL
313void BootstrapRequest<I>::handle_prepare_replay(int r) {
314 dout(10) << "r=" << r << dendl;
b32b8144
FG
315
316 if (r < 0) {
9f95a23c
TL
317 if (r != -EREMOTEIO) {
318 derr << "failed to prepare local replay: " << cpp_strerror(r) << dendl;
319 }
b32b8144
FG
320 m_ret_val = r;
321 close_remote_image();
322 return;
9f95a23c
TL
323 } else if (*m_do_resync) {
324 dout(10) << "local image resync requested" << dendl;
d2e6a577 325 close_remote_image();
7c673cae 326 return;
9f95a23c
TL
327 } else if ((*m_state_builder)->is_disconnected()) {
328 dout(10) << "client flagged disconnected -- skipping bootstrap" << dendl;
329 // The caller is expected to detect disconnect initializing remote journal.
330 m_ret_val = 0;
d2e6a577 331 close_remote_image();
7c673cae 332 return;
9f95a23c
TL
333 } else if (m_syncing) {
334 dout(10) << "local image still syncing to remote image" << dendl;
335 image_sync();
336 return;
7c673cae
FG
337 }
338
9f95a23c 339 close_remote_image();
d2e6a577
FG
340}
341
342template <typename I>
343void BootstrapRequest<I>::create_local_image() {
9f95a23c 344 dout(10) << dendl;
d2e6a577
FG
345 update_progress("CREATE_LOCAL_IMAGE");
346
9f95a23c
TL
347 ceph_assert(*m_state_builder != nullptr);
348 auto ctx = create_context_callback<
349 BootstrapRequest<I>,
350 &BootstrapRequest<I>::handle_create_local_image>(this);
351 auto request = (*m_state_builder)->create_local_image_request(
352 m_threads, m_local_io_ctx, m_global_image_id, m_pool_meta_cache,
353 m_progress_ctx, ctx);
d2e6a577
FG
354 request->send();
355}
356
357template <typename I>
358void BootstrapRequest<I>::handle_create_local_image(int r) {
11fdf7f2 359 dout(15) << "r=" << r << dendl;
d2e6a577 360
9f95a23c 361 if (r < 0) {
11fdf7f2
TL
362 if (r == -ENOENT) {
363 dout(10) << "parent image does not exist" << dendl;
364 } else {
365 derr << "failed to create local image: " << cpp_strerror(r) << dendl;
366 }
d2e6a577
FG
367 m_ret_val = r;
368 close_remote_image();
369 return;
370 }
371
372 open_local_image();
7c673cae
FG
373}
374
375template <typename I>
9f95a23c
TL
376void BootstrapRequest<I>::image_sync() {
377 std::unique_lock locker{m_lock};
7c673cae 378 if (m_canceled) {
9f95a23c 379 locker.unlock();
7c673cae 380
9f95a23c
TL
381 m_ret_val = -ECANCELED;
382 dout(10) << "request canceled" << dendl;
7c673cae
FG
383 close_remote_image();
384 return;
385 }
386
9f95a23c
TL
387 dout(15) << dendl;
388 ceph_assert(m_image_sync == nullptr);
c07f9fc5 389
9f95a23c
TL
390 auto state_builder = *m_state_builder;
391 auto sync_point_handler = state_builder->create_sync_point_handler();
c07f9fc5 392
9f95a23c
TL
393 Context *ctx = create_context_callback<
394 BootstrapRequest<I>, &BootstrapRequest<I>::handle_image_sync>(this);
395 m_image_sync = ImageSync<I>::create(
396 m_threads, state_builder->local_image_ctx, state_builder->remote_image_ctx,
397 m_local_mirror_uuid, sync_point_handler, m_instance_watcher,
398 m_progress_ctx, ctx);
399 m_image_sync->get();
400 locker.unlock();
7c673cae 401
9f95a23c
TL
402 update_progress("IMAGE_SYNC");
403 m_image_sync->send();
7c673cae
FG
404}
405
406template <typename I>
407void BootstrapRequest<I>::handle_image_sync(int r) {
11fdf7f2 408 dout(15) << "r=" << r << dendl;
7c673cae 409
31f18b77 410 {
9f95a23c 411 std::lock_guard locker{m_lock};
31f18b77
FG
412 m_image_sync->put();
413 m_image_sync = nullptr;
414
9f95a23c
TL
415 (*m_state_builder)->destroy_sync_point_handler();
416 }
31f18b77 417
9f95a23c
TL
418 if (r < 0) {
419 if (r == -ECANCELED) {
420 dout(10) << "request canceled" << dendl;
421 } else {
11fdf7f2 422 derr << "failed to sync remote image: " << cpp_strerror(r) << dendl;
31f18b77 423 }
9f95a23c 424 m_ret_val = r;
7c673cae
FG
425 }
426
427 close_remote_image();
428}
429
430template <typename I>
9f95a23c
TL
431void BootstrapRequest<I>::close_remote_image() {
432 if ((*m_state_builder)->replay_requires_remote_image()) {
433 finish(m_ret_val);
434 return;
7c673cae
FG
435 }
436
11fdf7f2 437 dout(15) << dendl;
7c673cae
FG
438
439 update_progress("CLOSE_REMOTE_IMAGE");
440
9f95a23c
TL
441 auto ctx = create_context_callback<
442 BootstrapRequest<I>,
443 &BootstrapRequest<I>::handle_close_remote_image>(this);
444 ceph_assert(*m_state_builder != nullptr);
445 (*m_state_builder)->close_remote_image(ctx);
7c673cae
FG
446}
447
448template <typename I>
449void BootstrapRequest<I>::handle_close_remote_image(int r) {
11fdf7f2 450 dout(15) << "r=" << r << dendl;
7c673cae
FG
451
452 if (r < 0) {
11fdf7f2 453 derr << "error encountered closing remote image: " << cpp_strerror(r)
7c673cae
FG
454 << dendl;
455 }
456
457 finish(m_ret_val);
458}
459
7c673cae
FG
460template <typename I>
461void BootstrapRequest<I>::update_progress(const std::string &description) {
11fdf7f2 462 dout(15) << description << dendl;
7c673cae
FG
463
464 if (m_progress_ctx) {
465 m_progress_ctx->update_progress(description);
466 }
467}
468
469} // namespace image_replayer
470} // namespace mirror
471} // namespace rbd
472
473template class rbd::mirror::image_replayer::BootstrapRequest<librbd::ImageCtx>;