]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/mirror/GetInfoRequest.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / librbd / mirror / GetInfoRequest.cc
CommitLineData
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 "librbd/mirror/GetInfoRequest.h"
5#include "common/dout.h"
6#include "common/errno.h"
7#include "cls/rbd/cls_rbd_client.h"
8#include "librbd/ImageCtx.h"
9#include "librbd/ImageState.h"
10#include "librbd/Journal.h"
11#include "librbd/Utils.h"
12
13#define dout_subsys ceph_subsys_rbd
14#undef dout_prefix
15#define dout_prefix *_dout << "librbd::mirror::GetInfoRequest: " << this \
16 << " " << __func__ << ": "
17
18namespace librbd {
19namespace mirror {
20
21using librbd::util::create_context_callback;
22using librbd::util::create_rados_callback;
23
9f95a23c
TL
24template <typename I>
25GetInfoRequest<I>::GetInfoRequest(librados::IoCtx& io_ctx,
f67539c2 26 asio::ContextWQ *op_work_queue,
9f95a23c
TL
27 const std::string &image_id,
28 cls::rbd::MirrorImage *mirror_image,
29 PromotionState *promotion_state,
30 std::string* primary_mirror_uuid,
31 Context *on_finish)
32 : m_io_ctx(io_ctx), m_op_work_queue(op_work_queue), m_image_id(image_id),
33 m_mirror_image(mirror_image), m_promotion_state(promotion_state),
34 m_primary_mirror_uuid(primary_mirror_uuid), m_on_finish(on_finish),
35 m_cct(reinterpret_cast<CephContext *>(io_ctx.cct())) {
36}
37
38template <typename I>
39GetInfoRequest<I>::GetInfoRequest(I &image_ctx,
40 cls::rbd::MirrorImage *mirror_image,
41 PromotionState *promotion_state,
42 std::string* primary_mirror_uuid,
43 Context *on_finish)
44 : m_image_ctx(&image_ctx), m_io_ctx(image_ctx.md_ctx),
45 m_op_work_queue(image_ctx.op_work_queue), m_image_id(image_ctx.id),
46 m_mirror_image(mirror_image), m_promotion_state(promotion_state),
47 m_primary_mirror_uuid(primary_mirror_uuid), m_on_finish(on_finish),
48 m_cct(image_ctx.cct) {
49}
50
7c673cae
FG
51template <typename I>
52void GetInfoRequest<I>::send() {
7c673cae
FG
53 get_mirror_image();
54}
55
56template <typename I>
57void GetInfoRequest<I>::get_mirror_image() {
9f95a23c 58 ldout(m_cct, 20) << dendl;
7c673cae
FG
59
60 librados::ObjectReadOperation op;
9f95a23c 61 cls_client::mirror_image_get_start(&op, m_image_id);
7c673cae
FG
62
63 librados::AioCompletion *comp = create_rados_callback<
64 GetInfoRequest<I>, &GetInfoRequest<I>::handle_get_mirror_image>(this);
9f95a23c 65 int r = m_io_ctx.aio_operate(RBD_MIRRORING, comp, &op, &m_out_bl);
11fdf7f2 66 ceph_assert(r == 0);
7c673cae
FG
67 comp->release();
68}
69
70template <typename I>
71void GetInfoRequest<I>::handle_get_mirror_image(int r) {
9f95a23c 72 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae
FG
73
74 m_mirror_image->state = cls::rbd::MIRROR_IMAGE_STATE_DISABLED;
75 *m_promotion_state = PROMOTION_STATE_NON_PRIMARY;
76 if (r == 0) {
11fdf7f2 77 auto iter = m_out_bl.cbegin();
7c673cae
FG
78 r = cls_client::mirror_image_get_finish(&iter, m_mirror_image);
79 }
80
9f95a23c
TL
81 if (r == -ENOENT) {
82 ldout(m_cct, 20) << "mirroring is disabled" << dendl;
83 finish(r);
7c673cae
FG
84 return;
85 } else if (r < 0) {
9f95a23c 86 lderr(m_cct) << "failed to retrieve mirroring state: " << cpp_strerror(r)
7c673cae
FG
87 << dendl;
88 finish(r);
89 return;
90 }
91
9f95a23c
TL
92 if (m_mirror_image->mode == cls::rbd::MIRROR_IMAGE_MODE_JOURNAL) {
93 get_journal_tag_owner();
94 } else if (m_mirror_image->mode == cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT) {
95 get_snapcontext();
96 } else {
97 ldout(m_cct, 20) << "unknown mirror image mode: " << m_mirror_image->mode
98 << dendl;
99 finish(-EOPNOTSUPP);
100 }
7c673cae
FG
101}
102
103template <typename I>
9f95a23c
TL
104void GetInfoRequest<I>::get_journal_tag_owner() {
105 ldout(m_cct, 20) << dendl;
7c673cae
FG
106
107 auto ctx = create_context_callback<
9f95a23c
TL
108 GetInfoRequest<I>, &GetInfoRequest<I>::handle_get_journal_tag_owner>(this);
109 Journal<I>::get_tag_owner(m_io_ctx, m_image_id, &m_mirror_uuid,
110 m_op_work_queue, ctx);
7c673cae
FG
111}
112
113template <typename I>
9f95a23c
TL
114void GetInfoRequest<I>::handle_get_journal_tag_owner(int r) {
115 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae
FG
116
117 if (r < 0) {
9f95a23c
TL
118 lderr(m_cct) << "failed to determine tag ownership: " << cpp_strerror(r)
119 << dendl;
7c673cae
FG
120 finish(r);
121 return;
122 }
123
124 if (m_mirror_uuid == Journal<>::LOCAL_MIRROR_UUID) {
125 *m_promotion_state = PROMOTION_STATE_PRIMARY;
9f95a23c 126 *m_primary_mirror_uuid = "";
7c673cae
FG
127 } else if (m_mirror_uuid == Journal<>::ORPHAN_MIRROR_UUID) {
128 *m_promotion_state = PROMOTION_STATE_ORPHAN;
9f95a23c
TL
129 *m_primary_mirror_uuid = "";
130 } else {
131 *m_primary_mirror_uuid = m_mirror_uuid;
7c673cae
FG
132 }
133
134 finish(0);
135}
136
9f95a23c
TL
137template <typename I>
138void GetInfoRequest<I>::get_snapcontext() {
139 if (m_image_ctx != nullptr) {
140 {
141 std::shared_lock image_locker{m_image_ctx->image_lock};
142 calc_promotion_state(m_image_ctx->snap_info);
143 }
144 finish(0);
145 return;
146 }
147
148 ldout(m_cct, 20) << dendl;
149
150 librados::ObjectReadOperation op;
151 cls_client::get_snapcontext_start(&op);
152
153 librados::AioCompletion *comp = create_rados_callback<
154 GetInfoRequest<I>, &GetInfoRequest<I>::handle_get_snapcontext>(this);
155 m_out_bl.clear();
156 int r = m_io_ctx.aio_operate(util::header_name(m_image_id), comp, &op,
157 &m_out_bl);
158 ceph_assert(r == 0);
159 comp->release();
160}
161
162template <typename I>
163void GetInfoRequest<I>::handle_get_snapcontext(int r) {
164 ldout(m_cct, 20) << "r=" << r << dendl;
165
166 if (r >= 0) {
167 auto it = m_out_bl.cbegin();
168 r = cls_client::get_snapcontext_finish(&it, &m_snapc);
169 }
170
171 if (r == -ENOENT &&
172 m_mirror_image->state == cls::rbd::MIRROR_IMAGE_STATE_CREATING) {
173 // image doesn't exist but we have a mirror image record for it
174 ldout(m_cct, 10) << "image does not exist for mirror image id "
175 << m_image_id << dendl;
176 *m_promotion_state = PROMOTION_STATE_UNKNOWN;
177 *m_primary_mirror_uuid = "";
178 finish(0);
179 return;
180 } else if (r < 0) {
181 lderr(m_cct) << "failed to get snapcontext: " << cpp_strerror(r)
182 << dendl;
183 finish(r);
184 return;
185 }
186
187 get_snapshots();
188}
189
190
191template <typename I>
192void GetInfoRequest<I>::get_snapshots() {
193 ldout(m_cct, 20) << dendl;
194
195 if (m_snapc.snaps.empty()) {
196 handle_get_snapshots(0);
197 return;
198 }
199
200 librados::ObjectReadOperation op;
201 for (auto snap_id : m_snapc.snaps) {
202 cls_client::snapshot_get_start(&op, snap_id);
203 }
204
205 librados::AioCompletion *comp = create_rados_callback<
206 GetInfoRequest<I>, &GetInfoRequest<I>::handle_get_snapshots>(this);
207 m_out_bl.clear();
208 int r = m_io_ctx.aio_operate(util::header_name(m_image_id), comp, &op,
209 &m_out_bl);
210 ceph_assert(r == 0);
211 comp->release();
212}
213
214template <typename I>
215void GetInfoRequest<I>::handle_get_snapshots(int r) {
216 ldout(m_cct, 20) << "r=" << r << dendl;
217
218 std::map<librados::snap_t, SnapInfo> snap_info;
219
220 auto it = m_out_bl.cbegin();
221 for (auto snap_id : m_snapc.snaps) {
222 cls::rbd::SnapshotInfo snap;
223 if (r >= 0) {
224 r = cls_client::snapshot_get_finish(&it, &snap);
225 }
226 snap_info.emplace(
227 snap_id, SnapInfo(snap.name, snap.snapshot_namespace, 0, {}, 0, 0, {}));
228 }
229
230 if (r == -ENOENT) {
231 // restart
232 get_snapcontext();
233 return;
234 }
235
236 if (r < 0) {
237 lderr(m_cct) << "failed to get snapshots: " << cpp_strerror(r)
238 << dendl;
239 finish(r);
240 return;
241 }
242
243 calc_promotion_state(snap_info);
244 finish(0);
245}
246
7c673cae
FG
247template <typename I>
248void GetInfoRequest<I>::finish(int r) {
9f95a23c 249 ldout(m_cct, 20) << "r=" << r << dendl;
7c673cae
FG
250
251 m_on_finish->complete(r);
252 delete this;
253}
254
9f95a23c
TL
255template <typename I>
256void GetInfoRequest<I>::calc_promotion_state(
257 const std::map<librados::snap_t, SnapInfo> &snap_info) {
258 *m_promotion_state = PROMOTION_STATE_UNKNOWN;
259 *m_primary_mirror_uuid = "";
260
261 for (auto it = snap_info.rbegin(); it != snap_info.rend(); it++) {
1e59de90 262 auto mirror_ns = std::get_if<cls::rbd::MirrorSnapshotNamespace>(
9f95a23c
TL
263 &it->second.snap_namespace);
264
265 if (mirror_ns != nullptr) {
266 switch (mirror_ns->state) {
267 case cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY:
268 *m_promotion_state = PROMOTION_STATE_PRIMARY;
269 break;
270 case cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY:
271 *m_promotion_state = PROMOTION_STATE_NON_PRIMARY;
272 *m_primary_mirror_uuid = mirror_ns->primary_mirror_uuid;
273 break;
274 case cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED:
275 case cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED:
276 *m_promotion_state = PROMOTION_STATE_ORPHAN;
277 break;
278 }
279 break;
280 }
281 }
282
283 ldout(m_cct, 10) << "promotion_state=" << *m_promotion_state << ", "
284 << "primary_mirror_uuid=" << *m_primary_mirror_uuid << dendl;
285}
286
7c673cae
FG
287} // namespace mirror
288} // namespace librbd
289
290template class librbd::mirror::GetInfoRequest<librbd::ImageCtx>;