1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
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"
13 #define dout_subsys ceph_subsys_rbd
15 #define dout_prefix *_dout << "librbd::mirror::GetInfoRequest: " << this \
16 << " " << __func__ << ": "
21 using librbd::util::create_context_callback
;
22 using librbd::util::create_rados_callback
;
25 GetInfoRequest
<I
>::GetInfoRequest(librados::IoCtx
& io_ctx
,
26 asio::ContextWQ
*op_work_queue
,
27 const std::string
&image_id
,
28 cls::rbd::MirrorImage
*mirror_image
,
29 PromotionState
*promotion_state
,
30 std::string
* primary_mirror_uuid
,
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())) {
39 GetInfoRequest
<I
>::GetInfoRequest(I
&image_ctx
,
40 cls::rbd::MirrorImage
*mirror_image
,
41 PromotionState
*promotion_state
,
42 std::string
* primary_mirror_uuid
,
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
) {
52 void GetInfoRequest
<I
>::send() {
57 void GetInfoRequest
<I
>::get_mirror_image() {
58 ldout(m_cct
, 20) << dendl
;
60 librados::ObjectReadOperation op
;
61 cls_client::mirror_image_get_start(&op
, m_image_id
);
63 librados::AioCompletion
*comp
= create_rados_callback
<
64 GetInfoRequest
<I
>, &GetInfoRequest
<I
>::handle_get_mirror_image
>(this);
65 int r
= m_io_ctx
.aio_operate(RBD_MIRRORING
, comp
, &op
, &m_out_bl
);
71 void GetInfoRequest
<I
>::handle_get_mirror_image(int r
) {
72 ldout(m_cct
, 20) << "r=" << r
<< dendl
;
74 m_mirror_image
->state
= cls::rbd::MIRROR_IMAGE_STATE_DISABLED
;
75 *m_promotion_state
= PROMOTION_STATE_NON_PRIMARY
;
77 auto iter
= m_out_bl
.cbegin();
78 r
= cls_client::mirror_image_get_finish(&iter
, m_mirror_image
);
82 ldout(m_cct
, 20) << "mirroring is disabled" << dendl
;
86 lderr(m_cct
) << "failed to retrieve mirroring state: " << cpp_strerror(r
)
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
) {
97 ldout(m_cct
, 20) << "unknown mirror image mode: " << m_mirror_image
->mode
103 template <typename I
>
104 void GetInfoRequest
<I
>::get_journal_tag_owner() {
105 ldout(m_cct
, 20) << dendl
;
107 auto ctx
= create_context_callback
<
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
);
113 template <typename I
>
114 void GetInfoRequest
<I
>::handle_get_journal_tag_owner(int r
) {
115 ldout(m_cct
, 20) << "r=" << r
<< dendl
;
118 lderr(m_cct
) << "failed to determine tag ownership: " << cpp_strerror(r
)
124 if (m_mirror_uuid
== Journal
<>::LOCAL_MIRROR_UUID
) {
125 *m_promotion_state
= PROMOTION_STATE_PRIMARY
;
126 *m_primary_mirror_uuid
= "";
127 } else if (m_mirror_uuid
== Journal
<>::ORPHAN_MIRROR_UUID
) {
128 *m_promotion_state
= PROMOTION_STATE_ORPHAN
;
129 *m_primary_mirror_uuid
= "";
131 *m_primary_mirror_uuid
= m_mirror_uuid
;
137 template <typename I
>
138 void GetInfoRequest
<I
>::get_snapcontext() {
139 if (m_image_ctx
!= nullptr) {
141 std::shared_lock image_locker
{m_image_ctx
->image_lock
};
142 calc_promotion_state(m_image_ctx
->snap_info
);
148 ldout(m_cct
, 20) << dendl
;
150 librados::ObjectReadOperation op
;
151 cls_client::get_snapcontext_start(&op
);
153 librados::AioCompletion
*comp
= create_rados_callback
<
154 GetInfoRequest
<I
>, &GetInfoRequest
<I
>::handle_get_snapcontext
>(this);
156 int r
= m_io_ctx
.aio_operate(util::header_name(m_image_id
), comp
, &op
,
162 template <typename I
>
163 void GetInfoRequest
<I
>::handle_get_snapcontext(int r
) {
164 ldout(m_cct
, 20) << "r=" << r
<< dendl
;
167 auto it
= m_out_bl
.cbegin();
168 r
= cls_client::get_snapcontext_finish(&it
, &m_snapc
);
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
= "";
181 lderr(m_cct
) << "failed to get snapcontext: " << cpp_strerror(r
)
191 template <typename I
>
192 void GetInfoRequest
<I
>::get_snapshots() {
193 ldout(m_cct
, 20) << dendl
;
195 if (m_snapc
.snaps
.empty()) {
196 handle_get_snapshots(0);
200 librados::ObjectReadOperation op
;
201 for (auto snap_id
: m_snapc
.snaps
) {
202 cls_client::snapshot_get_start(&op
, snap_id
);
205 librados::AioCompletion
*comp
= create_rados_callback
<
206 GetInfoRequest
<I
>, &GetInfoRequest
<I
>::handle_get_snapshots
>(this);
208 int r
= m_io_ctx
.aio_operate(util::header_name(m_image_id
), comp
, &op
,
214 template <typename I
>
215 void GetInfoRequest
<I
>::handle_get_snapshots(int r
) {
216 ldout(m_cct
, 20) << "r=" << r
<< dendl
;
218 std::map
<librados::snap_t
, SnapInfo
> snap_info
;
220 auto it
= m_out_bl
.cbegin();
221 for (auto snap_id
: m_snapc
.snaps
) {
222 cls::rbd::SnapshotInfo snap
;
224 r
= cls_client::snapshot_get_finish(&it
, &snap
);
227 snap_id
, SnapInfo(snap
.name
, snap
.snapshot_namespace
, 0, {}, 0, 0, {}));
237 lderr(m_cct
) << "failed to get snapshots: " << cpp_strerror(r
)
243 calc_promotion_state(snap_info
);
247 template <typename I
>
248 void GetInfoRequest
<I
>::finish(int r
) {
249 ldout(m_cct
, 20) << "r=" << r
<< dendl
;
251 m_on_finish
->complete(r
);
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
= "";
261 for (auto it
= snap_info
.rbegin(); it
!= snap_info
.rend(); it
++) {
262 auto mirror_ns
= boost::get
<cls::rbd::MirrorSnapshotNamespace
>(
263 &it
->second
.snap_namespace
);
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
;
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
;
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
;
283 ldout(m_cct
, 10) << "promotion_state=" << *m_promotion_state
<< ", "
284 << "primary_mirror_uuid=" << *m_primary_mirror_uuid
<< dendl
;
287 } // namespace mirror
288 } // namespace librbd
290 template class librbd::mirror::GetInfoRequest
<librbd::ImageCtx
>;