]>
Commit | Line | Data |
---|---|---|
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 | |
38 | namespace rbd { | |
39 | namespace mirror { | |
40 | namespace image_replayer { | |
41 | ||
42 | using librbd::util::create_context_callback; | |
7c673cae FG |
43 | using librbd::util::unique_lock_name; |
44 | ||
45 | template <typename I> | |
46 | BootstrapRequest<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 |
80 | template <typename I> |
81 | bool 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 |
86 | template <typename I> |
87 | void BootstrapRequest<I>::send() { | |
88 | *m_do_resync = false; | |
89 | ||
9f95a23c | 90 | prepare_local_image(); |
7c673cae FG |
91 | } |
92 | ||
93 | template <typename I> | |
94 | void 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 | ||
105 | template <typename I> | |
9f95a23c TL |
106 | std::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 | ||
111 | template <typename I> | |
9f95a23c TL |
112 | void 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 | ||
130 | template <typename I> | |
131 | void 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 | ||
154 | template <typename I> | |
9f95a23c TL |
155 | void 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 | ||
168 | template <typename I> | |
9f95a23c TL |
169 | void 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 | ||
215 | template <typename I> | |
9f95a23c TL |
216 | void 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 | ||
233 | template <typename I> | |
9f95a23c | 234 | void 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 |
253 | template <typename I> |
254 | void 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 | ||
271 | template <typename I> | |
272 | void 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 | 299 | template <typename I> |
9f95a23c TL |
300 | void 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 | ||
312 | template <typename I> | |
9f95a23c TL |
313 | void 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 | ||
342 | template <typename I> | |
343 | void 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 | ||
357 | template <typename I> | |
358 | void 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 | ||
375 | template <typename I> | |
9f95a23c TL |
376 | void 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 | ||
406 | template <typename I> | |
407 | void 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 | ||
430 | template <typename I> | |
9f95a23c TL |
431 | void 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 | ||
448 | template <typename I> | |
449 | void 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 |
460 | template <typename I> |
461 | void 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 | ||
473 | template class rbd::mirror::image_replayer::BootstrapRequest<librbd::ImageCtx>; |