]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/DeepCopyRequest.cc
import 15.2.2 octopus source
[ceph.git] / ceph / src / librbd / DeepCopyRequest.cc
CommitLineData
11fdf7f2
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#include "DeepCopyRequest.h"
5#include "common/errno.h"
6#include "librbd/ExclusiveLock.h"
7#include "librbd/ImageCtx.h"
8#include "librbd/ObjectMap.h"
9#include "librbd/Utils.h"
10#include "librbd/deep_copy/ImageCopyRequest.h"
11#include "librbd/deep_copy/MetadataCopyRequest.h"
12#include "librbd/deep_copy/SnapshotCopyRequest.h"
13#include "librbd/internal.h"
14
15#define dout_subsys ceph_subsys_rbd
16#undef dout_prefix
17#define dout_prefix *_dout << "librbd::DeepCopyRequest: " \
18 << this << " " << __func__ << ": "
19
20namespace librbd {
21
22using namespace librbd::deep_copy;
23
24using librbd::util::create_context_callback;
25using librbd::util::create_rados_callback;
26using librbd::util::unique_lock_name;
27
28template <typename I>
29DeepCopyRequest<I>::DeepCopyRequest(I *src_image_ctx, I *dst_image_ctx,
9f95a23c
TL
30 librados::snap_t src_snap_id_start,
31 librados::snap_t src_snap_id_end,
32 librados::snap_t dst_snap_id_start,
33 bool flatten,
11fdf7f2
TL
34 const ObjectNumber &object_number,
35 ContextWQ *work_queue, SnapSeqs *snap_seqs,
1911f103 36 deep_copy::Handler *handler,
11fdf7f2 37 Context *on_finish)
9f95a23c
TL
38 : RefCountedObject(dst_image_ctx->cct), m_src_image_ctx(src_image_ctx),
39 m_dst_image_ctx(dst_image_ctx), m_src_snap_id_start(src_snap_id_start),
40 m_src_snap_id_end(src_snap_id_end), m_dst_snap_id_start(dst_snap_id_start),
41 m_flatten(flatten), m_object_number(object_number),
1911f103 42 m_work_queue(work_queue), m_snap_seqs(snap_seqs), m_handler(handler),
9f95a23c
TL
43 m_on_finish(on_finish), m_cct(dst_image_ctx->cct),
44 m_lock(ceph::make_mutex(unique_lock_name("DeepCopyRequest::m_lock", this))) {
11fdf7f2
TL
45}
46
47template <typename I>
48DeepCopyRequest<I>::~DeepCopyRequest() {
49 ceph_assert(m_snapshot_copy_request == nullptr);
50 ceph_assert(m_image_copy_request == nullptr);
51}
52
53template <typename I>
54void DeepCopyRequest<I>::send() {
eafe8130
TL
55 if (!m_src_image_ctx->data_ctx.is_valid()) {
56 lderr(m_cct) << "missing data pool for source image" << dendl;
57 finish(-ENODEV);
58 return;
59 }
60
61 if (!m_dst_image_ctx->data_ctx.is_valid()) {
62 lderr(m_cct) << "missing data pool for destination image" << dendl;
63 finish(-ENODEV);
64 return;
65 }
66
11fdf7f2
TL
67 int r = validate_copy_points();
68 if (r < 0) {
69 finish(r);
70 return;
71 }
72
73 send_copy_snapshots();
74}
75
76template <typename I>
77void DeepCopyRequest<I>::cancel() {
9f95a23c 78 std::lock_guard locker{m_lock};
11fdf7f2
TL
79
80 ldout(m_cct, 20) << dendl;
81
82 m_canceled = true;
83
84 if (m_snapshot_copy_request != nullptr) {
85 m_snapshot_copy_request->cancel();
86 }
87
88 if (m_image_copy_request != nullptr) {
89 m_image_copy_request->cancel();
90 }
91}
92
93template <typename I>
94void DeepCopyRequest<I>::send_copy_snapshots() {
9f95a23c 95 m_lock.lock();
11fdf7f2 96 if (m_canceled) {
9f95a23c 97 m_lock.unlock();
11fdf7f2
TL
98 finish(-ECANCELED);
99 return;
100 }
101
102 ldout(m_cct, 20) << dendl;
103
104 Context *ctx = create_context_callback<
105 DeepCopyRequest<I>, &DeepCopyRequest<I>::handle_copy_snapshots>(this);
106 m_snapshot_copy_request = SnapshotCopyRequest<I>::create(
9f95a23c
TL
107 m_src_image_ctx, m_dst_image_ctx, m_src_snap_id_start, m_src_snap_id_end,
108 m_dst_snap_id_start, m_flatten, m_work_queue, m_snap_seqs, ctx);
11fdf7f2 109 m_snapshot_copy_request->get();
9f95a23c 110 m_lock.unlock();
11fdf7f2
TL
111
112 m_snapshot_copy_request->send();
113}
114
115template <typename I>
116void DeepCopyRequest<I>::handle_copy_snapshots(int r) {
117 ldout(m_cct, 20) << "r=" << r << dendl;
118
119 {
9f95a23c 120 std::lock_guard locker{m_lock};
11fdf7f2
TL
121 m_snapshot_copy_request->put();
122 m_snapshot_copy_request = nullptr;
123 if (r == 0 && m_canceled) {
124 r = -ECANCELED;
125 }
126 }
127
128 if (r == -ECANCELED) {
129 ldout(m_cct, 10) << "snapshot copy canceled" << dendl;
130 finish(r);
131 return;
132 } else if (r < 0) {
133 lderr(m_cct) << "failed to copy snapshot metadata: " << cpp_strerror(r)
134 << dendl;
135 finish(r);
136 return;
137 }
138
9f95a23c 139 if (m_src_snap_id_end == CEPH_NOSNAP) {
11fdf7f2
TL
140 (*m_snap_seqs)[CEPH_NOSNAP] = CEPH_NOSNAP;
141 }
142
143 send_copy_image();
144}
145
146template <typename I>
147void DeepCopyRequest<I>::send_copy_image() {
9f95a23c 148 m_lock.lock();
11fdf7f2 149 if (m_canceled) {
9f95a23c 150 m_lock.unlock();
11fdf7f2
TL
151 finish(-ECANCELED);
152 return;
153 }
154
155 ldout(m_cct, 20) << dendl;
156
157 Context *ctx = create_context_callback<
158 DeepCopyRequest<I>, &DeepCopyRequest<I>::handle_copy_image>(this);
159 m_image_copy_request = ImageCopyRequest<I>::create(
9f95a23c 160 m_src_image_ctx, m_dst_image_ctx, m_src_snap_id_start, m_src_snap_id_end,
1911f103 161 m_dst_snap_id_start, m_flatten, m_object_number, *m_snap_seqs, m_handler,
9f95a23c 162 ctx);
11fdf7f2 163 m_image_copy_request->get();
9f95a23c 164 m_lock.unlock();
11fdf7f2
TL
165
166 m_image_copy_request->send();
167}
168
169template <typename I>
170void DeepCopyRequest<I>::handle_copy_image(int r) {
171 ldout(m_cct, 20) << "r=" << r << dendl;
172
173 {
9f95a23c 174 std::lock_guard locker{m_lock};
11fdf7f2
TL
175 m_image_copy_request->put();
176 m_image_copy_request = nullptr;
177 if (r == 0 && m_canceled) {
178 r = -ECANCELED;
179 }
180 }
181
182 if (r == -ECANCELED) {
183 ldout(m_cct, 10) << "image copy canceled" << dendl;
184 finish(r);
185 return;
186 } else if (r < 0) {
187 lderr(m_cct) << "failed to copy image: " << cpp_strerror(r) << dendl;
188 finish(r);
189 return;
190 }
191
192 send_copy_object_map();
193}
194
195template <typename I>
196void DeepCopyRequest<I>::send_copy_object_map() {
9f95a23c
TL
197 m_dst_image_ctx->owner_lock.lock_shared();
198 m_dst_image_ctx->image_lock.lock_shared();
11fdf7f2
TL
199
200 if (!m_dst_image_ctx->test_features(RBD_FEATURE_OBJECT_MAP,
9f95a23c
TL
201 m_dst_image_ctx->image_lock)) {
202 m_dst_image_ctx->image_lock.unlock_shared();
203 m_dst_image_ctx->owner_lock.unlock_shared();
11fdf7f2
TL
204 send_copy_metadata();
205 return;
206 }
9f95a23c
TL
207 if (m_src_snap_id_end == CEPH_NOSNAP) {
208 m_dst_image_ctx->image_lock.unlock_shared();
209 m_dst_image_ctx->owner_lock.unlock_shared();
11fdf7f2
TL
210 send_refresh_object_map();
211 return;
212 }
213
214 ceph_assert(m_dst_image_ctx->object_map != nullptr);
215
216 ldout(m_cct, 20) << dendl;
217
218 Context *finish_op_ctx = nullptr;
219 int r;
220 if (m_dst_image_ctx->exclusive_lock != nullptr) {
221 finish_op_ctx = m_dst_image_ctx->exclusive_lock->start_op(&r);
222 }
223 if (finish_op_ctx == nullptr) {
224 lderr(m_cct) << "lost exclusive lock" << dendl;
9f95a23c
TL
225 m_dst_image_ctx->image_lock.unlock_shared();
226 m_dst_image_ctx->owner_lock.unlock_shared();
11fdf7f2
TL
227 finish(r);
228 return;
229 }
230
231 // rollback the object map (copy snapshot object map to HEAD)
9f95a23c 232 auto ctx = new LambdaContext([this, finish_op_ctx](int r) {
11fdf7f2
TL
233 handle_copy_object_map(r);
234 finish_op_ctx->complete(0);
235 });
9f95a23c
TL
236 ceph_assert(m_snap_seqs->count(m_src_snap_id_end) > 0);
237 librados::snap_t copy_snap_id = (*m_snap_seqs)[m_src_snap_id_end];
11fdf7f2 238 m_dst_image_ctx->object_map->rollback(copy_snap_id, ctx);
9f95a23c
TL
239 m_dst_image_ctx->image_lock.unlock_shared();
240 m_dst_image_ctx->owner_lock.unlock_shared();
11fdf7f2
TL
241}
242
243template <typename I>
244void DeepCopyRequest<I>::handle_copy_object_map(int r) {
245 ldout(m_cct, 20) << dendl;
246
247 if (r < 0) {
248 lderr(m_cct) << "failed to roll back object map: " << cpp_strerror(r)
249 << dendl;
250 finish(r);
251 return;
252 }
253
254 send_refresh_object_map();
255}
256
257template <typename I>
258void DeepCopyRequest<I>::send_refresh_object_map() {
259 int r;
260 Context *finish_op_ctx = nullptr;
261 {
9f95a23c 262 std::shared_lock owner_locker{m_dst_image_ctx->owner_lock};
11fdf7f2
TL
263 if (m_dst_image_ctx->exclusive_lock != nullptr) {
264 finish_op_ctx = m_dst_image_ctx->exclusive_lock->start_op(&r);
265 }
266 }
267 if (finish_op_ctx == nullptr) {
268 lderr(m_cct) << "lost exclusive lock" << dendl;
269 finish(r);
270 return;
271 }
272
273 ldout(m_cct, 20) << dendl;
274
9f95a23c 275 auto ctx = new LambdaContext([this, finish_op_ctx](int r) {
11fdf7f2
TL
276 handle_refresh_object_map(r);
277 finish_op_ctx->complete(0);
278 });
279 m_object_map = m_dst_image_ctx->create_object_map(CEPH_NOSNAP);
280 m_object_map->open(ctx);
281}
282
283template <typename I>
284void DeepCopyRequest<I>::handle_refresh_object_map(int r) {
285 ldout(m_cct, 20) << "r=" << r << dendl;
286
287 if (r < 0) {
288 lderr(m_cct) << "failed to open object map: " << cpp_strerror(r)
289 << dendl;
290 delete m_object_map;
291
292 finish(r);
293 return;
294 }
295
296 {
9f95a23c 297 std::unique_lock image_locker{m_dst_image_ctx->image_lock};
11fdf7f2
TL
298 std::swap(m_dst_image_ctx->object_map, m_object_map);
299 }
9f95a23c 300 m_object_map->put();
11fdf7f2
TL
301
302 send_copy_metadata();
303}
304
305template <typename I>
306void DeepCopyRequest<I>::send_copy_metadata() {
307 ldout(m_cct, 20) << dendl;
308
309 Context *ctx = create_context_callback<
310 DeepCopyRequest<I>, &DeepCopyRequest<I>::handle_copy_metadata>(this);
311 auto request = MetadataCopyRequest<I>::create(m_src_image_ctx,
312 m_dst_image_ctx, ctx);
313 request->send();
314}
315
316template <typename I>
317void DeepCopyRequest<I>::handle_copy_metadata(int r) {
318 ldout(m_cct, 20) << "r=" << r << dendl;
319
320 if (r < 0) {
321 lderr(m_cct) << "failed to copy metadata: " << cpp_strerror(r) << dendl;
322 finish(r);
323 return;
324 }
325
326 finish(0);
327}
328
329template <typename I>
330int DeepCopyRequest<I>::validate_copy_points() {
9f95a23c 331 std::shared_lock image_locker{m_src_image_ctx->image_lock};
11fdf7f2 332
9f95a23c
TL
333 if (m_src_snap_id_start != 0 &&
334 m_src_image_ctx->snap_info.find(m_src_snap_id_start) ==
11fdf7f2 335 m_src_image_ctx->snap_info.end()) {
9f95a23c 336 lderr(m_cct) << "invalid start snap_id " << m_src_snap_id_start << dendl;
11fdf7f2
TL
337 return -EINVAL;
338 }
339
9f95a23c
TL
340 if (m_src_snap_id_end != CEPH_NOSNAP &&
341 m_src_image_ctx->snap_info.find(m_src_snap_id_end) ==
11fdf7f2 342 m_src_image_ctx->snap_info.end()) {
9f95a23c 343 lderr(m_cct) << "invalid end snap_id " << m_src_snap_id_end << dendl;
11fdf7f2
TL
344 return -EINVAL;
345 }
346
347 return 0;
348}
349
350template <typename I>
351void DeepCopyRequest<I>::finish(int r) {
352 ldout(m_cct, 20) << "r=" << r << dendl;
353
354 m_on_finish->complete(r);
355 put();
356}
357
358} // namespace librbd
359
360template class librbd::DeepCopyRequest<librbd::ImageCtx>;