1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h"
5 #include "include/rados/librados.hpp"
6 #include "cls/rbd/cls_rbd_client.h"
7 #include "common/debug.h"
8 #include "common/errno.h"
9 #include "common/WorkQueue.h"
10 #include "journal/Journaler.h"
11 #include "librbd/ImageCtx.h"
12 #include "librbd/Utils.h"
13 #include "librbd/journal/Types.h"
14 #include "tools/rbd_mirror/Threads.h"
15 #include "tools/rbd_mirror/image_replayer/GetMirrorImageIdRequest.h"
16 #include "tools/rbd_mirror/image_replayer/Utils.h"
18 #define dout_context g_ceph_context
19 #define dout_subsys ceph_subsys_rbd_mirror
21 #define dout_prefix *_dout << "rbd::mirror::image_replayer::" \
22 << "PrepareRemoteImageRequest: " << this << " " \
27 namespace image_replayer
{
29 using librbd::util::create_async_context_callback
;
30 using librbd::util::create_context_callback
;
31 using librbd::util::create_rados_callback
;
34 void PrepareRemoteImageRequest
<I
>::send() {
35 get_remote_mirror_uuid();
39 void PrepareRemoteImageRequest
<I
>::get_remote_mirror_uuid() {
42 librados::ObjectReadOperation op
;
43 librbd::cls_client::mirror_uuid_get_start(&op
);
45 librados::AioCompletion
*aio_comp
= create_rados_callback
<
46 PrepareRemoteImageRequest
<I
>,
47 &PrepareRemoteImageRequest
<I
>::handle_get_remote_mirror_uuid
>(this);
48 int r
= m_remote_io_ctx
.aio_operate(RBD_MIRRORING
, aio_comp
, &op
, &m_out_bl
);
54 void PrepareRemoteImageRequest
<I
>::handle_get_remote_mirror_uuid(int r
) {
56 auto it
= m_out_bl
.cbegin();
57 r
= librbd::cls_client::mirror_uuid_get_finish(&it
, m_remote_mirror_uuid
);
58 if (r
>= 0 && m_remote_mirror_uuid
->empty()) {
63 dout(20) << "r=" << r
<< dendl
;
66 dout(5) << "remote mirror uuid missing" << dendl
;
68 derr
<< "failed to retrieve remote mirror uuid: " << cpp_strerror(r
)
75 get_remote_image_id();
79 void PrepareRemoteImageRequest
<I
>::get_remote_image_id() {
82 Context
*ctx
= create_context_callback
<
83 PrepareRemoteImageRequest
<I
>,
84 &PrepareRemoteImageRequest
<I
>::handle_get_remote_image_id
>(this);
85 auto req
= GetMirrorImageIdRequest
<I
>::create(m_remote_io_ctx
,
87 m_remote_image_id
, ctx
);
92 void PrepareRemoteImageRequest
<I
>::handle_get_remote_image_id(int r
) {
93 dout(20) << "r=" << r
<< ", "
94 << "remote_image_id=" << *m_remote_image_id
<< dendl
;
104 template <typename I
>
105 void PrepareRemoteImageRequest
<I
>::get_client() {
108 ceph_assert(*m_remote_journaler
== nullptr);
109 *m_remote_journaler
= new Journaler(m_threads
->work_queue
, m_threads
->timer
,
110 &m_threads
->timer_lock
, m_remote_io_ctx
,
111 *m_remote_image_id
, m_local_mirror_uuid
,
114 Context
*ctx
= create_async_context_callback(
115 m_threads
->work_queue
, create_context_callback
<
116 PrepareRemoteImageRequest
<I
>,
117 &PrepareRemoteImageRequest
<I
>::handle_get_client
>(this));
118 (*m_remote_journaler
)->get_client(m_local_mirror_uuid
, &m_client
, ctx
);
121 template <typename I
>
122 void PrepareRemoteImageRequest
<I
>::handle_get_client(int r
) {
123 dout(20) << "r=" << r
<< dendl
;
126 dout(10) << "client not registered" << dendl
;
129 derr
<< "failed to retrieve client: " << cpp_strerror(r
) << dendl
;
131 } else if (!util::decode_client_meta(m_client
, m_client_meta
)) {
132 // require operator intervention since the data is corrupt
135 // skip registration if it already exists
136 *m_client_state
= m_client
.state
;
141 template <typename I
>
142 void PrepareRemoteImageRequest
<I
>::register_client() {
145 librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta
{
147 mirror_peer_client_meta
.state
= librbd::journal::MIRROR_PEER_STATE_REPLAYING
;
149 librbd::journal::ClientData client_data
{mirror_peer_client_meta
};
150 bufferlist client_data_bl
;
151 encode(client_data
, client_data_bl
);
153 Context
*ctx
= create_async_context_callback(
154 m_threads
->work_queue
, create_context_callback
<
155 PrepareRemoteImageRequest
<I
>,
156 &PrepareRemoteImageRequest
<I
>::handle_register_client
>(this));
157 (*m_remote_journaler
)->register_client(client_data_bl
, ctx
);
160 template <typename I
>
161 void PrepareRemoteImageRequest
<I
>::handle_register_client(int r
) {
162 dout(20) << "r=" << r
<< dendl
;
165 derr
<< "failed to register with remote journal: " << cpp_strerror(r
)
171 *m_client_state
= cls::journal::CLIENT_STATE_CONNECTED
;
172 *m_client_meta
= librbd::journal::MirrorPeerClientMeta(m_local_image_id
);
173 m_client_meta
->state
= librbd::journal::MIRROR_PEER_STATE_REPLAYING
;
178 template <typename I
>
179 void PrepareRemoteImageRequest
<I
>::finish(int r
) {
180 dout(20) << "r=" << r
<< dendl
;
183 delete *m_remote_journaler
;
184 *m_remote_journaler
= nullptr;
187 m_on_finish
->complete(r
);
191 } // namespace image_replayer
192 } // namespace mirror
195 template class rbd::mirror::image_replayer::PrepareRemoteImageRequest
<librbd::ImageCtx
>;