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