]> git.proxmox.com Git - ceph.git/blame - ceph/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.cc
update sources to v12.2.3
[ceph.git] / ceph / src / tools / rbd_mirror / image_replayer / PrepareRemoteImageRequest.cc
CommitLineData
d2e6a577
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 "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"
b32b8144
FG
8#include "common/WorkQueue.h"
9#include "journal/Journaler.h"
10#include "journal/Settings.h"
d2e6a577
FG
11#include "librbd/ImageCtx.h"
12#include "librbd/Utils.h"
b32b8144
FG
13#include "librbd/journal/Types.h"
14#include "tools/rbd_mirror/Threads.h"
d2e6a577
FG
15#include "tools/rbd_mirror/image_replayer/GetMirrorImageIdRequest.h"
16
17#define dout_context g_ceph_context
18#define dout_subsys ceph_subsys_rbd_mirror
19#undef dout_prefix
20#define dout_prefix *_dout << "rbd::mirror::image_replayer::" \
21 << "PrepareRemoteImageRequest: " << this << " " \
22 << __func__ << ": "
23
24namespace rbd {
25namespace mirror {
26namespace image_replayer {
27
b32b8144 28using librbd::util::create_async_context_callback;
d2e6a577
FG
29using librbd::util::create_context_callback;
30using librbd::util::create_rados_callback;
31
32template <typename I>
33void PrepareRemoteImageRequest<I>::send() {
34 get_remote_mirror_uuid();
35}
36
37template <typename I>
38void PrepareRemoteImageRequest<I>::get_remote_mirror_uuid() {
39 dout(20) << dendl;
40
41 librados::ObjectReadOperation op;
42 librbd::cls_client::mirror_uuid_get_start(&op);
43
44 librados::AioCompletion *aio_comp = create_rados_callback<
45 PrepareRemoteImageRequest<I>,
46 &PrepareRemoteImageRequest<I>::handle_get_remote_mirror_uuid>(this);
b32b8144 47 int r = m_remote_io_ctx.aio_operate(RBD_MIRRORING, aio_comp, &op, &m_out_bl);
d2e6a577
FG
48 assert(r == 0);
49 aio_comp->release();
50}
51
52template <typename I>
53void PrepareRemoteImageRequest<I>::handle_get_remote_mirror_uuid(int r) {
54 if (r >= 0) {
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()) {
58 r = -ENOENT;
59 }
60 }
61
62 dout(20) << "r=" << r << dendl;
63 if (r < 0) {
64 if (r == -ENOENT) {
65 dout(5) << "remote mirror uuid missing" << dendl;
66 } else {
67 derr << "failed to retrieve remote mirror uuid: " << cpp_strerror(r)
68 << dendl;
69 }
70 finish(r);
71 return;
72 }
73
74 get_remote_image_id();
75}
76
77template <typename I>
78void PrepareRemoteImageRequest<I>::get_remote_image_id() {
79 dout(20) << dendl;
80
81 Context *ctx = create_context_callback<
82 PrepareRemoteImageRequest<I>,
83 &PrepareRemoteImageRequest<I>::handle_get_remote_image_id>(this);
b32b8144
FG
84 auto req = GetMirrorImageIdRequest<I>::create(m_remote_io_ctx,
85 m_global_image_id,
d2e6a577
FG
86 m_remote_image_id, ctx);
87 req->send();
88}
89
90template <typename I>
91void PrepareRemoteImageRequest<I>::handle_get_remote_image_id(int r) {
92 dout(20) << "r=" << r << ", "
93 << "remote_image_id=" << *m_remote_image_id << dendl;
94
95 if (r < 0) {
96 finish(r);
97 return;
98 }
99
b32b8144
FG
100 get_client();
101}
102
103template <typename I>
104void PrepareRemoteImageRequest<I>::get_client() {
105 dout(20) << dendl;
106
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");
112
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,
117 settings);
118
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);
124}
125
126template <typename I>
127void PrepareRemoteImageRequest<I>::handle_get_client(int r) {
128 dout(20) << "r=" << r << dendl;
129
130 if (r == -ENOENT) {
131 dout(10) << "client not registered" << dendl;
132 register_client();
133 } else if (r < 0) {
134 derr << "failed to retrieve client: " << cpp_strerror(r) << dendl;
135 finish(r);
136 } else if (!decode_client_meta()) {
137 // require operator intervention since the data is corrupt
138 finish(-EBADMSG);
139 } else {
140 // skip registration if it already exists
141 *m_client_state = m_client.state;
142 finish(0);
143 }
144}
145
146template <typename I>
147void PrepareRemoteImageRequest<I>::register_client() {
148 dout(20) << dendl;
149
150 librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
151 m_local_image_id};
152 mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
153
154 librbd::journal::ClientData client_data{mirror_peer_client_meta};
155 bufferlist client_data_bl;
156 ::encode(client_data, client_data_bl);
157
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);
163}
164
165template <typename I>
166void PrepareRemoteImageRequest<I>::handle_register_client(int r) {
167 dout(20) << "r=" << r << dendl;
168
169 if (r < 0) {
170 derr << "failed to register with remote journal: " << cpp_strerror(r)
171 << dendl;
172 finish(r);
173 return;
174 }
175
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;
179
d2e6a577
FG
180 finish(0);
181}
182
b32b8144
FG
183template <typename I>
184bool PrepareRemoteImageRequest<I>::decode_client_meta() {
185 dout(20) << dendl;
186
187 librbd::journal::ClientData client_data;
188 bufferlist::iterator it = m_client.data.begin();
189 try {
190 ::decode(client_data, it);
191 } catch (const buffer::error &err) {
192 derr << "failed to decode client meta data: " << err.what() << dendl;
193 return false;
194 }
195
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;
200 return false;
201 }
202
203 *m_client_meta = *client_meta;
204 dout(20) << "client found: client_meta=" << *m_client_meta << dendl;
205 return true;
206}
207
d2e6a577
FG
208template <typename I>
209void PrepareRemoteImageRequest<I>::finish(int r) {
210 dout(20) << "r=" << r << dendl;
211
b32b8144
FG
212 if (r < 0) {
213 delete *m_remote_journaler;
214 *m_remote_journaler = nullptr;
215 }
216
d2e6a577
FG
217 m_on_finish->complete(r);
218 delete this;
219}
220
221} // namespace image_replayer
222} // namespace mirror
223} // namespace rbd
224
225template class rbd::mirror::image_replayer::PrepareRemoteImageRequest<librbd::ImageCtx>;