]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/mirror/EnableRequest.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / librbd / mirror / EnableRequest.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/EnableRequest.h"
5#include "common/dout.h"
6#include "common/errno.h"
7#include "cls/rbd/cls_rbd_client.h"
8#include "librbd/ImageState.h"
9#include "librbd/Journal.h"
7c673cae 10#include "librbd/Utils.h"
9f95a23c
TL
11#include "librbd/mirror/ImageStateUpdateRequest.h"
12#include "librbd/mirror/snapshot/CreatePrimaryRequest.h"
7c673cae
FG
13
14#define dout_subsys ceph_subsys_rbd
15#undef dout_prefix
9f95a23c
TL
16#define dout_prefix *_dout << "librbd::mirror::EnableRequest: " \
17 << this << " " << __func__ << ": "
7c673cae
FG
18
19namespace librbd {
20namespace mirror {
21
22using util::create_context_callback;
23using util::create_rados_callback;
24
25template <typename I>
26EnableRequest<I>::EnableRequest(librados::IoCtx &io_ctx,
27 const std::string &image_id,
9f95a23c
TL
28 I* image_ctx,
29 cls::rbd::MirrorImageMode mode,
7c673cae
FG
30 const std::string &non_primary_global_image_id,
31 ContextWQ *op_work_queue, Context *on_finish)
9f95a23c
TL
32 : m_io_ctx(io_ctx), m_image_id(image_id), m_image_ctx(image_ctx),
33 m_mode(mode), m_non_primary_global_image_id(non_primary_global_image_id),
7c673cae
FG
34 m_op_work_queue(op_work_queue), m_on_finish(on_finish),
35 m_cct(reinterpret_cast<CephContext*>(io_ctx.cct())) {
36}
37
38template <typename I>
39void EnableRequest<I>::send() {
9f95a23c 40 get_mirror_image();
7c673cae
FG
41}
42
43template <typename I>
9f95a23c
TL
44void EnableRequest<I>::get_mirror_image() {
45 ldout(m_cct, 10) << dendl;
7c673cae
FG
46
47 librados::ObjectReadOperation op;
48 cls_client::mirror_image_get_start(&op, m_image_id);
49
50 using klass = EnableRequest<I>;
51 librados::AioCompletion *comp =
52 create_rados_callback<klass, &klass::handle_get_mirror_image>(this);
53 m_out_bl.clear();
54 int r = m_io_ctx.aio_operate(RBD_MIRRORING, comp, &op, &m_out_bl);
11fdf7f2 55 ceph_assert(r == 0);
7c673cae
FG
56 comp->release();
57}
58
59template <typename I>
9f95a23c
TL
60void EnableRequest<I>::handle_get_mirror_image(int r) {
61 ldout(m_cct, 10) << "r=" << r << dendl;
7c673cae 62
9f95a23c 63 if (r == 0) {
11fdf7f2 64 auto iter = m_out_bl.cbegin();
9f95a23c 65 r = cls_client::mirror_image_get_finish(&iter, &m_mirror_image);
7c673cae
FG
66 }
67
9f95a23c
TL
68 if (r == 0 && m_mirror_image.state == cls::rbd::MIRROR_IMAGE_STATE_CREATING &&
69 !m_non_primary_global_image_id.empty()) {
70 // special case where rbd-mirror injects a disabled record to record the
71 // local image id prior to creating ther image
72 ldout(m_cct, 10) << "enabling mirroring on in-progress image replication"
73 << dendl;
74 } else if (r == 0) {
75 if (m_mirror_image.mode != m_mode) {
76 lderr(m_cct) << "invalid current image mirror mode" << dendl;
77 r = -EINVAL;
78 } else if (m_mirror_image.state == cls::rbd::MIRROR_IMAGE_STATE_ENABLED) {
79 ldout(m_cct, 10) << "mirroring is already enabled" << dendl;
7c673cae
FG
80 } else {
81 lderr(m_cct) << "currently disabling" << dendl;
9f95a23c 82 r = -EINVAL;
7c673cae 83 }
9f95a23c
TL
84 finish(r);
85 return;
86 } else if (r != -ENOENT) {
87 lderr(m_cct) << "failed to retrieve mirror image: " << cpp_strerror(r)
7c673cae 88 << dendl;
9f95a23c
TL
89 finish(r);
90 return;
7c673cae
FG
91 }
92
9f95a23c
TL
93 r = 0;
94 m_mirror_image.mode = m_mode;
7c673cae
FG
95 if (m_non_primary_global_image_id.empty()) {
96 uuid_d uuid_gen;
97 uuid_gen.generate_random();
98 m_mirror_image.global_image_id = uuid_gen.to_string();
99 } else {
100 m_mirror_image.global_image_id = m_non_primary_global_image_id;
101 }
102
9f95a23c 103 get_tag_owner();
11fdf7f2
TL
104}
105
106template <typename I>
9f95a23c
TL
107void EnableRequest<I>::get_tag_owner() {
108 if (m_mirror_image.mode == cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT) {
109 create_primary_snapshot();
110 return;
111 } else if (!m_non_primary_global_image_id.empty()) {
112 image_state_update();
11fdf7f2
TL
113 return;
114 }
9f95a23c
TL
115
116 ldout(m_cct, 10) << dendl;
11fdf7f2
TL
117
118 using klass = EnableRequest<I>;
119 Context *ctx = create_context_callback<
120 klass, &klass::handle_get_tag_owner>(this);
121 librbd::Journal<>::is_tag_owner(m_io_ctx, m_image_id, &m_is_primary,
122 m_op_work_queue, ctx);
123}
124
125template <typename I>
9f95a23c
TL
126void EnableRequest<I>::handle_get_tag_owner(int r) {
127 ldout(m_cct, 10) << "r=" << r << dendl;
11fdf7f2 128
9f95a23c
TL
129 if (r < 0) {
130 lderr(m_cct) << "failed to check tag ownership: " << cpp_strerror(r)
11fdf7f2 131 << dendl;
9f95a23c
TL
132 finish(r);
133 return;
11fdf7f2
TL
134 }
135
136 if (!m_is_primary) {
137 lderr(m_cct) << "last journal tag not owned by local cluster" << dendl;
9f95a23c
TL
138 finish(-EINVAL);
139 return;
11fdf7f2
TL
140 }
141
9f95a23c 142 image_state_update();
7c673cae
FG
143}
144
145template <typename I>
9f95a23c
TL
146void EnableRequest<I>::create_primary_snapshot() {
147 if (!m_non_primary_global_image_id.empty()) {
148 // special case for rbd-mirror creating a non-primary image
149 enable_non_primary_feature();
150 return;
151 }
7c673cae 152
9f95a23c 153 ldout(m_cct, 10) << dendl;
7c673cae 154
9f95a23c
TL
155 ceph_assert(m_image_ctx != nullptr);
156 auto ctx = create_context_callback<
157 EnableRequest<I>,
158 &EnableRequest<I>::handle_create_primary_snapshot>(this);
159 auto req = snapshot::CreatePrimaryRequest<I>::create(
160 m_image_ctx, m_mirror_image.global_image_id,
161 snapshot::CREATE_PRIMARY_FLAG_IGNORE_EMPTY_PEERS, &m_snap_id, ctx);
162 req->send();
7c673cae
FG
163}
164
165template <typename I>
9f95a23c
TL
166void EnableRequest<I>::handle_create_primary_snapshot(int r) {
167 ldout(m_cct, 10) << "r=" << r << dendl;
7c673cae 168
9f95a23c
TL
169 if (r < 0) {
170 lderr(m_cct) << "failed to create initial primary snapshot: "
171 << cpp_strerror(r) << dendl;
172 finish(r);
173 return;
174 }
175
176 image_state_update();
177}
178
179template <typename I>
180void EnableRequest<I>::enable_non_primary_feature() {
181 if (m_mirror_image.mode != cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT) {
182 image_state_update();
183 return;
7c673cae
FG
184 }
185
9f95a23c
TL
186 ldout(m_cct, 10) << dendl;
187
188 // ensure image is flagged with non-primary feature so that
189 // standard RBD clients cannot write to it.
190 librados::ObjectWriteOperation op;
191 cls_client::set_features(&op, RBD_FEATURE_NON_PRIMARY,
192 RBD_FEATURE_NON_PRIMARY);
193
194 auto aio_comp = create_rados_callback<
195 EnableRequest<I>,
196 &EnableRequest<I>::handle_enable_non_primary_feature>(this);
197 int r = m_io_ctx.aio_operate(util::header_name(m_image_id), aio_comp, &op);
198 ceph_assert(r == 0);
199 aio_comp->release();
7c673cae
FG
200}
201
202template <typename I>
9f95a23c
TL
203void EnableRequest<I>::handle_enable_non_primary_feature(int r) {
204 ldout(m_cct, 10) << "r=" << r << dendl;
7c673cae 205
9f95a23c
TL
206 if (r < 0) {
207 lderr(m_cct) << "failed to enable non-primary feature: "
208 << cpp_strerror(r) << dendl;
209 finish(r);
210 return;
211 }
7c673cae 212
9f95a23c
TL
213 image_state_update();
214}
215
216template <typename I>
217void EnableRequest<I>::image_state_update() {
218 ldout(m_cct, 10) << dendl;
219
220 auto ctx = create_context_callback<
221 EnableRequest<I>, &EnableRequest<I>::handle_image_state_update>(this);
222 auto req = ImageStateUpdateRequest<I>::create(
223 m_io_ctx, m_image_id, cls::rbd::MIRROR_IMAGE_STATE_ENABLED,
224 m_mirror_image, ctx);
225 req->send();
7c673cae
FG
226}
227
228template <typename I>
9f95a23c
TL
229void EnableRequest<I>::handle_image_state_update(int r) {
230 ldout(m_cct, 10) << "r=" << r << dendl;
7c673cae 231
9f95a23c
TL
232 if (r < 0) {
233 lderr(m_cct) << "failed to enable mirroring: " << cpp_strerror(r)
234 << dendl;
7c673cae
FG
235 }
236
9f95a23c
TL
237 finish(r);
238}
239
240template <typename I>
241void EnableRequest<I>::finish(int r) {
242 ldout(m_cct, 10) << "r=" << r << dendl;
243
244 m_on_finish->complete(r);
245 delete this;
7c673cae
FG
246}
247
248} // namespace mirror
249} // namespace librbd
250
251template class librbd::mirror::EnableRequest<librbd::ImageCtx>;