]> git.proxmox.com Git - ceph.git/blob - ceph/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / tools / rbd_mirror / image_replayer / PrepareRemoteImageRequest.cc
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/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"
17
18 #define dout_context g_ceph_context
19 #define dout_subsys ceph_subsys_rbd_mirror
20 #undef dout_prefix
21 #define dout_prefix *_dout << "rbd::mirror::image_replayer::" \
22 << "PrepareRemoteImageRequest: " << this << " " \
23 << __func__ << ": "
24
25 namespace rbd {
26 namespace mirror {
27 namespace image_replayer {
28
29 using librbd::util::create_async_context_callback;
30 using librbd::util::create_context_callback;
31 using librbd::util::create_rados_callback;
32
33 template <typename I>
34 void PrepareRemoteImageRequest<I>::send() {
35 get_remote_mirror_uuid();
36 }
37
38 template <typename I>
39 void PrepareRemoteImageRequest<I>::get_remote_mirror_uuid() {
40 dout(20) << dendl;
41
42 librados::ObjectReadOperation op;
43 librbd::cls_client::mirror_uuid_get_start(&op);
44
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);
49 ceph_assert(r == 0);
50 aio_comp->release();
51 }
52
53 template <typename I>
54 void PrepareRemoteImageRequest<I>::handle_get_remote_mirror_uuid(int r) {
55 if (r >= 0) {
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()) {
59 r = -ENOENT;
60 }
61 }
62
63 dout(20) << "r=" << r << dendl;
64 if (r < 0) {
65 if (r == -ENOENT) {
66 dout(5) << "remote mirror uuid missing" << dendl;
67 } else {
68 derr << "failed to retrieve remote mirror uuid: " << cpp_strerror(r)
69 << dendl;
70 }
71 finish(r);
72 return;
73 }
74
75 get_remote_image_id();
76 }
77
78 template <typename I>
79 void PrepareRemoteImageRequest<I>::get_remote_image_id() {
80 dout(20) << dendl;
81
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,
86 m_global_image_id,
87 m_remote_image_id, ctx);
88 req->send();
89 }
90
91 template <typename I>
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;
95
96 if (r < 0) {
97 finish(r);
98 return;
99 }
100
101 get_client();
102 }
103
104 template <typename I>
105 void PrepareRemoteImageRequest<I>::get_client() {
106 dout(20) << dendl;
107
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,
112 m_journal_settings);
113
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);
119 }
120
121 template <typename I>
122 void PrepareRemoteImageRequest<I>::handle_get_client(int r) {
123 dout(20) << "r=" << r << dendl;
124
125 if (r == -ENOENT) {
126 dout(10) << "client not registered" << dendl;
127 register_client();
128 } else if (r < 0) {
129 derr << "failed to retrieve client: " << cpp_strerror(r) << dendl;
130 finish(r);
131 } else if (!util::decode_client_meta(m_client, m_client_meta)) {
132 // require operator intervention since the data is corrupt
133 finish(-EBADMSG);
134 } else {
135 // skip registration if it already exists
136 *m_client_state = m_client.state;
137 finish(0);
138 }
139 }
140
141 template <typename I>
142 void PrepareRemoteImageRequest<I>::register_client() {
143 dout(20) << dendl;
144
145 librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
146 m_local_image_id};
147 mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
148
149 librbd::journal::ClientData client_data{mirror_peer_client_meta};
150 bufferlist client_data_bl;
151 encode(client_data, client_data_bl);
152
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);
158 }
159
160 template <typename I>
161 void PrepareRemoteImageRequest<I>::handle_register_client(int r) {
162 dout(20) << "r=" << r << dendl;
163
164 if (r < 0) {
165 derr << "failed to register with remote journal: " << cpp_strerror(r)
166 << dendl;
167 finish(r);
168 return;
169 }
170
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;
174
175 finish(0);
176 }
177
178 template <typename I>
179 void PrepareRemoteImageRequest<I>::finish(int r) {
180 dout(20) << "r=" << r << dendl;
181
182 if (r < 0) {
183 delete *m_remote_journaler;
184 *m_remote_journaler = nullptr;
185 }
186
187 m_on_finish->complete(r);
188 delete this;
189 }
190
191 } // namespace image_replayer
192 } // namespace mirror
193 } // namespace rbd
194
195 template class rbd::mirror::image_replayer::PrepareRemoteImageRequest<librbd::ImageCtx>;