]>
Commit | Line | Data |
---|---|---|
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 | ||
18 | namespace librbd { | |
19 | namespace mirror { | |
20 | ||
21 | using librbd::util::create_context_callback; | |
22 | using librbd::util::create_rados_callback; | |
23 | ||
9f95a23c TL |
24 | template <typename I> |
25 | GetInfoRequest<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 | ||
38 | template <typename I> | |
39 | GetInfoRequest<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 |
51 | template <typename I> |
52 | void GetInfoRequest<I>::send() { | |
7c673cae FG |
53 | get_mirror_image(); |
54 | } | |
55 | ||
56 | template <typename I> | |
57 | void 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 | ||
70 | template <typename I> | |
71 | void 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 | ||
103 | template <typename I> | |
9f95a23c TL |
104 | void 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 | ||
113 | template <typename I> | |
9f95a23c TL |
114 | void 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 |
137 | template <typename I> |
138 | void 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 | ||
162 | template <typename I> | |
163 | void 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 | ||
191 | template <typename I> | |
192 | void 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 | ||
214 | template <typename I> | |
215 | void 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 |
247 | template <typename I> |
248 | void 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 |
255 | template <typename I> |
256 | void 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 | ||
290 | template class librbd::mirror::GetInfoRequest<librbd::ImageCtx>; |