]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/mirror/DemoteRequest.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / librbd / mirror / DemoteRequest.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 "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"
15
16 #define dout_subsys ceph_subsys_rbd
17 #undef dout_prefix
18 #define dout_prefix *_dout << "librbd::mirror::DemoteRequest: " << this \
19 << " " << __func__ << ": "
20
21 namespace librbd {
22 namespace mirror {
23
24 using librbd::util::create_context_callback;
25
26 template <typename I>
27 void DemoteRequest<I>::send() {
28 get_info();
29 }
30
31 template <typename I>
32 void DemoteRequest<I>::get_info() {
33 CephContext *cct = m_image_ctx.cct;
34 ldout(cct, 20) << dendl;
35
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,
39 &m_promotion_state,
40 &m_primary_mirror_uuid, ctx);
41 req->send();
42 }
43
44 template <typename I>
45 void DemoteRequest<I>::handle_get_info(int r) {
46 CephContext *cct = m_image_ctx.cct;
47 ldout(cct, 20) << "r=" << r << dendl;
48
49 if (r < 0 && r != -ENOENT) {
50 lderr(cct) << "failed to retrieve mirroring state: " << cpp_strerror(r)
51 << dendl;
52 finish(r);
53 return;
54 } else if (m_mirror_image.state != cls::rbd::MIRROR_IMAGE_STATE_ENABLED) {
55 lderr(cct) << "mirroring is not currently enabled" << dendl;
56 finish(-EINVAL);
57 return;
58 } else if (m_promotion_state != PROMOTION_STATE_PRIMARY) {
59 lderr(cct) << "image is not primary" << dendl;
60 finish(-EINVAL);
61 return;
62 }
63
64 acquire_lock();
65 }
66
67 template <typename I>
68 void DemoteRequest<I>::acquire_lock() {
69 CephContext *cct = m_image_ctx.cct;
70
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;
76 finish(-EINVAL);
77 } else {
78 demote();
79 }
80 return;
81 }
82
83 // avoid accepting new requests from peers while we demote
84 // the image
85 m_image_ctx.exclusive_lock->block_requests(0);
86 m_blocked_requests = true;
87
88 if (m_image_ctx.exclusive_lock->is_lock_owner()) {
89 m_image_ctx.owner_lock.unlock_shared();
90 demote();
91 return;
92 }
93
94 ldout(cct, 20) << dendl;
95
96 auto ctx = create_context_callback<
97 DemoteRequest<I>,
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();
101 }
102
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;
107
108 if (r < 0) {
109 lderr(cct) << "failed to lock image: " << cpp_strerror(r) << dendl;
110 finish(r);
111 return;
112 }
113
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;
120 finish(r);
121 return;
122 }
123 m_image_ctx.owner_lock.unlock_shared();
124
125 demote();
126 }
127
128 template <typename I>
129 void DemoteRequest<I>::demote() {
130 CephContext *cct = m_image_ctx.cct;
131 ldout(cct, 20) << dendl;
132
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);
140 req->send();
141 } else {
142 lderr(cct) << "unknown image mirror mode: " << m_mirror_image.mode << dendl;
143 m_ret_val = -EOPNOTSUPP;
144 release_lock();
145 }
146 }
147
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;
152
153 if (r < 0) {
154 m_ret_val = r;
155 lderr(cct) << "failed to demote image: " << cpp_strerror(r) << dendl;
156 }
157
158 release_lock();
159 }
160
161 template <typename I>
162 void DemoteRequest<I>::release_lock() {
163 CephContext *cct = m_image_ctx.cct;
164 ldout(cct, 20) << dendl;
165
166 m_image_ctx.owner_lock.lock_shared();
167 if (m_image_ctx.exclusive_lock == nullptr) {
168 m_image_ctx.owner_lock.unlock_shared();
169 finish(0);
170 return;
171 }
172
173 auto ctx = create_context_callback<
174 DemoteRequest<I>,
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();
178 }
179
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;
184
185 if (r < 0) {
186 lderr(cct) << "failed to release exclusive lock: " << cpp_strerror(r)
187 << dendl;
188 }
189
190 finish(r);
191 }
192
193 template <typename I>
194 void DemoteRequest<I>::finish(int r) {
195 if (m_ret_val < 0) {
196 r = m_ret_val;
197 }
198
199 {
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();
203 }
204 }
205
206 CephContext *cct = m_image_ctx.cct;
207 ldout(cct, 20) << "r=" << r << dendl;
208
209 m_on_finish->complete(r);
210 delete this;
211 }
212
213 } // namespace mirror
214 } // namespace librbd
215
216 template class librbd::mirror::DemoteRequest<librbd::ImageCtx>;