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/errno.h"
8 #include "common/WorkQueue.h"
9 #include "journal/Journaler.h"
10 #include "journal/Settings.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"
17 #define dout_context g_ceph_context
18 #define dout_subsys ceph_subsys_rbd_mirror
20 #define dout_prefix *_dout << "rbd::mirror::image_replayer::" \
21 << "PrepareRemoteImageRequest: " << this << " " \
26 namespace image_replayer
{
28 using librbd::util::create_async_context_callback
;
29 using librbd::util::create_context_callback
;
30 using librbd::util::create_rados_callback
;
33 void PrepareRemoteImageRequest
<I
>::send() {
34 get_remote_mirror_uuid();
38 void PrepareRemoteImageRequest
<I
>::get_remote_mirror_uuid() {
41 librados::ObjectReadOperation op
;
42 librbd::cls_client::mirror_uuid_get_start(&op
);
44 librados::AioCompletion
*aio_comp
= create_rados_callback
<
45 PrepareRemoteImageRequest
<I
>,
46 &PrepareRemoteImageRequest
<I
>::handle_get_remote_mirror_uuid
>(this);
47 int r
= m_remote_io_ctx
.aio_operate(RBD_MIRRORING
, aio_comp
, &op
, &m_out_bl
);
53 void PrepareRemoteImageRequest
<I
>::handle_get_remote_mirror_uuid(int r
) {
55 bufferlist::iterator it
= m_out_bl
.begin();
56 r
= librbd::cls_client::mirror_uuid_get_finish(&it
, m_remote_mirror_uuid
);
57 if (r
>= 0 && m_remote_mirror_uuid
->empty()) {
62 dout(20) << "r=" << r
<< dendl
;
65 dout(5) << "remote mirror uuid missing" << dendl
;
67 derr
<< "failed to retrieve remote mirror uuid: " << cpp_strerror(r
)
74 get_remote_image_id();
78 void PrepareRemoteImageRequest
<I
>::get_remote_image_id() {
81 Context
*ctx
= create_context_callback
<
82 PrepareRemoteImageRequest
<I
>,
83 &PrepareRemoteImageRequest
<I
>::handle_get_remote_image_id
>(this);
84 auto req
= GetMirrorImageIdRequest
<I
>::create(m_remote_io_ctx
,
86 m_remote_image_id
, ctx
);
91 void PrepareRemoteImageRequest
<I
>::handle_get_remote_image_id(int r
) {
92 dout(20) << "r=" << r
<< ", "
93 << "remote_image_id=" << *m_remote_image_id
<< dendl
;
103 template <typename I
>
104 void PrepareRemoteImageRequest
<I
>::get_client() {
107 journal::Settings settings
;
108 settings
.commit_interval
= g_ceph_context
->_conf
->get_val
<double>(
109 "rbd_mirror_journal_commit_age");
110 settings
.max_fetch_bytes
= g_ceph_context
->_conf
->get_val
<uint64_t>(
111 "rbd_mirror_journal_max_fetch_bytes");
113 assert(*m_remote_journaler
== nullptr);
114 *m_remote_journaler
= new Journaler(m_threads
->work_queue
, m_threads
->timer
,
115 &m_threads
->timer_lock
, m_remote_io_ctx
,
116 *m_remote_image_id
, m_local_mirror_uuid
,
119 Context
*ctx
= create_async_context_callback(
120 m_threads
->work_queue
, create_context_callback
<
121 PrepareRemoteImageRequest
<I
>,
122 &PrepareRemoteImageRequest
<I
>::handle_get_client
>(this));
123 (*m_remote_journaler
)->get_client(m_local_mirror_uuid
, &m_client
, ctx
);
126 template <typename I
>
127 void PrepareRemoteImageRequest
<I
>::handle_get_client(int r
) {
128 dout(20) << "r=" << r
<< dendl
;
131 dout(10) << "client not registered" << dendl
;
134 derr
<< "failed to retrieve client: " << cpp_strerror(r
) << dendl
;
136 } else if (!decode_client_meta()) {
137 // require operator intervention since the data is corrupt
140 // skip registration if it already exists
141 *m_client_state
= m_client
.state
;
146 template <typename I
>
147 void PrepareRemoteImageRequest
<I
>::register_client() {
150 librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta
{
152 mirror_peer_client_meta
.state
= librbd::journal::MIRROR_PEER_STATE_REPLAYING
;
154 librbd::journal::ClientData client_data
{mirror_peer_client_meta
};
155 bufferlist client_data_bl
;
156 ::encode(client_data
, client_data_bl
);
158 Context
*ctx
= create_async_context_callback(
159 m_threads
->work_queue
, create_context_callback
<
160 PrepareRemoteImageRequest
<I
>,
161 &PrepareRemoteImageRequest
<I
>::handle_register_client
>(this));
162 (*m_remote_journaler
)->register_client(client_data_bl
, ctx
);
165 template <typename I
>
166 void PrepareRemoteImageRequest
<I
>::handle_register_client(int r
) {
167 dout(20) << "r=" << r
<< dendl
;
170 derr
<< "failed to register with remote journal: " << cpp_strerror(r
)
176 *m_client_state
= cls::journal::CLIENT_STATE_CONNECTED
;
177 *m_client_meta
= librbd::journal::MirrorPeerClientMeta(m_local_image_id
);
178 m_client_meta
->state
= librbd::journal::MIRROR_PEER_STATE_REPLAYING
;
183 template <typename I
>
184 bool PrepareRemoteImageRequest
<I
>::decode_client_meta() {
187 librbd::journal::ClientData client_data
;
188 bufferlist::iterator it
= m_client
.data
.begin();
190 ::decode(client_data
, it
);
191 } catch (const buffer::error
&err
) {
192 derr
<< "failed to decode client meta data: " << err
.what() << dendl
;
196 librbd::journal::MirrorPeerClientMeta
*client_meta
=
197 boost::get
<librbd::journal::MirrorPeerClientMeta
>(&client_data
.client_meta
);
198 if (client_meta
== nullptr) {
199 derr
<< "unknown peer registration" << dendl
;
203 *m_client_meta
= *client_meta
;
204 dout(20) << "client found: client_meta=" << *m_client_meta
<< dendl
;
208 template <typename I
>
209 void PrepareRemoteImageRequest
<I
>::finish(int r
) {
210 dout(20) << "r=" << r
<< dendl
;
213 delete *m_remote_journaler
;
214 *m_remote_journaler
= nullptr;
217 m_on_finish
->complete(r
);
221 } // namespace image_replayer
222 } // namespace mirror
225 template class rbd::mirror::image_replayer::PrepareRemoteImageRequest
<librbd::ImageCtx
>;