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/DemoteRequest.h"
5 #include "common/dout.h"
6 #include "common/errno.h"
7 #include "cls/rbd/cls_rbd_client.h"
8 #include "librbd/ExclusiveLock.h"
9 #include "librbd/ImageCtx.h"
10 #include "librbd/ImageState.h"
11 #include "librbd/Journal.h"
12 #include "librbd/Utils.h"
13 #include "librbd/mirror/GetInfoRequest.h"
14 #include "librbd/mirror/snapshot/DemoteRequest.h"
16 #define dout_subsys ceph_subsys_rbd
18 #define dout_prefix *_dout << "librbd::mirror::DemoteRequest: " << this \
19 << " " << __func__ << ": "
24 using librbd::util::create_context_callback
;
27 void DemoteRequest
<I
>::send() {
32 void DemoteRequest
<I
>::get_info() {
33 CephContext
*cct
= m_image_ctx
.cct
;
34 ldout(cct
, 20) << dendl
;
36 auto ctx
= create_context_callback
<
37 DemoteRequest
<I
>, &DemoteRequest
<I
>::handle_get_info
>(this);
38 auto req
= GetInfoRequest
<I
>::create(m_image_ctx
, &m_mirror_image
,
40 &m_primary_mirror_uuid
, ctx
);
45 void DemoteRequest
<I
>::handle_get_info(int r
) {
46 CephContext
*cct
= m_image_ctx
.cct
;
47 ldout(cct
, 20) << "r=" << r
<< dendl
;
49 if (r
< 0 && r
!= -ENOENT
) {
50 lderr(cct
) << "failed to retrieve mirroring state: " << cpp_strerror(r
)
54 } else if (m_mirror_image
.state
!= cls::rbd::MIRROR_IMAGE_STATE_ENABLED
) {
55 lderr(cct
) << "mirroring is not currently enabled" << dendl
;
58 } else if (m_promotion_state
!= PROMOTION_STATE_PRIMARY
) {
59 lderr(cct
) << "image is not primary" << dendl
;
68 void DemoteRequest
<I
>::acquire_lock() {
69 CephContext
*cct
= m_image_ctx
.cct
;
71 m_image_ctx
.owner_lock
.lock_shared();
72 if (m_image_ctx
.exclusive_lock
== nullptr) {
73 m_image_ctx
.owner_lock
.unlock_shared();
74 if (m_mirror_image
.mode
== cls::rbd::MIRROR_IMAGE_MODE_JOURNAL
) {
75 lderr(cct
) << "exclusive lock is not active" << dendl
;
83 // avoid accepting new requests from peers while we demote
85 m_image_ctx
.exclusive_lock
->block_requests(0);
86 m_blocked_requests
= true;
88 if (m_image_ctx
.exclusive_lock
->is_lock_owner()) {
89 m_image_ctx
.owner_lock
.unlock_shared();
94 ldout(cct
, 20) << dendl
;
96 auto ctx
= create_context_callback
<
98 &DemoteRequest
<I
>::handle_acquire_lock
>(this, m_image_ctx
.exclusive_lock
);
99 m_image_ctx
.exclusive_lock
->acquire_lock(ctx
);
100 m_image_ctx
.owner_lock
.unlock_shared();
103 template <typename I
>
104 void DemoteRequest
<I
>::handle_acquire_lock(int r
) {
105 CephContext
*cct
= m_image_ctx
.cct
;
106 ldout(cct
, 20) << "r=" << r
<< dendl
;
109 lderr(cct
) << "failed to lock image: " << cpp_strerror(r
) << dendl
;
114 m_image_ctx
.owner_lock
.lock_shared();
115 if (m_image_ctx
.exclusive_lock
!= nullptr &&
116 !m_image_ctx
.exclusive_lock
->is_lock_owner()) {
117 r
= m_image_ctx
.exclusive_lock
->get_unlocked_op_error();
118 m_image_ctx
.owner_lock
.unlock_shared();
119 lderr(cct
) << "failed to acquire exclusive lock" << dendl
;
123 m_image_ctx
.owner_lock
.unlock_shared();
128 template <typename I
>
129 void DemoteRequest
<I
>::demote() {
130 CephContext
*cct
= m_image_ctx
.cct
;
131 ldout(cct
, 20) << dendl
;
133 auto ctx
= create_context_callback
<
134 DemoteRequest
<I
>, &DemoteRequest
<I
>::handle_demote
>(this);
135 if (m_mirror_image
.mode
== cls::rbd::MIRROR_IMAGE_MODE_JOURNAL
) {
136 Journal
<I
>::demote(&m_image_ctx
, ctx
);
137 } else if (m_mirror_image
.mode
== cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT
) {
138 auto req
= mirror::snapshot::DemoteRequest
<I
>::create(
139 &m_image_ctx
, m_mirror_image
.global_image_id
, ctx
);
142 lderr(cct
) << "unknown image mirror mode: " << m_mirror_image
.mode
<< dendl
;
143 m_ret_val
= -EOPNOTSUPP
;
148 template <typename I
>
149 void DemoteRequest
<I
>::handle_demote(int r
) {
150 CephContext
*cct
= m_image_ctx
.cct
;
151 ldout(cct
, 20) << "r=" << r
<< dendl
;
155 lderr(cct
) << "failed to demote image: " << cpp_strerror(r
) << dendl
;
161 template <typename I
>
162 void DemoteRequest
<I
>::release_lock() {
163 CephContext
*cct
= m_image_ctx
.cct
;
164 ldout(cct
, 20) << dendl
;
166 m_image_ctx
.owner_lock
.lock_shared();
167 if (m_image_ctx
.exclusive_lock
== nullptr) {
168 m_image_ctx
.owner_lock
.unlock_shared();
173 auto ctx
= create_context_callback
<
175 &DemoteRequest
<I
>::handle_release_lock
>(this, m_image_ctx
.exclusive_lock
);
176 m_image_ctx
.exclusive_lock
->release_lock(ctx
);
177 m_image_ctx
.owner_lock
.unlock_shared();
180 template <typename I
>
181 void DemoteRequest
<I
>::handle_release_lock(int r
) {
182 CephContext
*cct
= m_image_ctx
.cct
;
183 ldout(cct
, 20) << "r=" << r
<< dendl
;
186 lderr(cct
) << "failed to release exclusive lock: " << cpp_strerror(r
)
193 template <typename I
>
194 void DemoteRequest
<I
>::finish(int r
) {
200 std::shared_lock owner_locker
{m_image_ctx
.owner_lock
};
201 if (m_blocked_requests
&& m_image_ctx
.exclusive_lock
!= nullptr) {
202 m_image_ctx
.exclusive_lock
->unblock_requests();
206 CephContext
*cct
= m_image_ctx
.cct
;
207 ldout(cct
, 20) << "r=" << r
<< dendl
;
209 m_on_finish
->complete(r
);
213 } // namespace mirror
214 } // namespace librbd
216 template class librbd::mirror::DemoteRequest
<librbd::ImageCtx
>;