]>
Commit | Line | Data |
---|---|---|
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 "SnapshotCopyRequest.h" | |
5 | #include "SnapshotCreateRequest.h" | |
6 | #include "common/errno.h" | |
7 | #include "common/WorkQueue.h" | |
8 | #include "journal/Journaler.h" | |
31f18b77 | 9 | #include "librbd/ExclusiveLock.h" |
7c673cae FG |
10 | #include "librbd/Operations.h" |
11 | #include "librbd/Utils.h" | |
12 | #include "librbd/journal/Types.h" | |
13 | ||
14 | #define dout_context g_ceph_context | |
15 | #define dout_subsys ceph_subsys_rbd_mirror | |
16 | #undef dout_prefix | |
17 | #define dout_prefix *_dout << "rbd::mirror::image_sync::SnapshotCopyRequest: " \ | |
18 | << this << " " << __func__ | |
19 | ||
20 | namespace rbd { | |
21 | namespace mirror { | |
22 | namespace image_sync { | |
23 | ||
24 | namespace { | |
25 | ||
26 | template <typename I> | |
27 | const std::string &get_snapshot_name(I *image_ctx, librados::snap_t snap_id) { | |
28 | auto snap_it = std::find_if(image_ctx->snap_ids.begin(), | |
29 | image_ctx->snap_ids.end(), | |
30 | [snap_id]( | |
31 | const std::pair< | |
32 | std::pair<cls::rbd::SnapshotNamespace, | |
33 | std::string>, | |
34 | librados::snap_t> &pair) { | |
35 | return pair.second == snap_id; | |
36 | }); | |
37 | assert(snap_it != image_ctx->snap_ids.end()); | |
38 | return snap_it->first.second; | |
39 | } | |
40 | ||
41 | } // anonymous namespace | |
42 | ||
43 | using librbd::util::create_context_callback; | |
44 | using librbd::util::unique_lock_name; | |
45 | ||
46 | template <typename I> | |
47 | SnapshotCopyRequest<I>::SnapshotCopyRequest(I *local_image_ctx, | |
48 | I *remote_image_ctx, | |
49 | SnapMap *snap_map, | |
50 | Journaler *journaler, | |
51 | librbd::journal::MirrorPeerClientMeta *meta, | |
52 | ContextWQ *work_queue, | |
53 | Context *on_finish) | |
54 | : BaseRequest("rbd::mirror::image_sync::SnapshotCopyRequest", | |
55 | local_image_ctx->cct, on_finish), | |
56 | m_local_image_ctx(local_image_ctx), m_remote_image_ctx(remote_image_ctx), | |
57 | m_snap_map(snap_map), m_journaler(journaler), m_client_meta(meta), | |
58 | m_work_queue(work_queue), m_snap_seqs(meta->snap_seqs), | |
59 | m_lock(unique_lock_name("SnapshotCopyRequest::m_lock", this)) { | |
60 | m_snap_map->clear(); | |
61 | ||
62 | // snap ids ordered from oldest to newest | |
63 | m_remote_snap_ids.insert(remote_image_ctx->snaps.begin(), | |
64 | remote_image_ctx->snaps.end()); | |
65 | m_local_snap_ids.insert(local_image_ctx->snaps.begin(), | |
66 | local_image_ctx->snaps.end()); | |
67 | } | |
68 | ||
69 | template <typename I> | |
70 | void SnapshotCopyRequest<I>::send() { | |
71 | librbd::ParentSpec remote_parent_spec; | |
72 | int r = validate_parent(m_remote_image_ctx, &remote_parent_spec); | |
73 | if (r < 0) { | |
74 | derr << ": remote image parent spec mismatch" << dendl; | |
75 | error(r); | |
76 | return; | |
77 | } | |
78 | ||
79 | r = validate_parent(m_local_image_ctx, &m_local_parent_spec); | |
80 | if (r < 0) { | |
81 | derr << ": local image parent spec mismatch" << dendl; | |
82 | error(r); | |
83 | return; | |
84 | } | |
85 | ||
86 | send_snap_unprotect(); | |
87 | } | |
88 | ||
89 | template <typename I> | |
90 | void SnapshotCopyRequest<I>::cancel() { | |
91 | Mutex::Locker locker(m_lock); | |
92 | ||
93 | dout(20) << dendl; | |
94 | m_canceled = true; | |
95 | } | |
96 | ||
97 | template <typename I> | |
98 | void SnapshotCopyRequest<I>::send_snap_unprotect() { | |
99 | ||
100 | SnapIdSet::iterator snap_id_it = m_local_snap_ids.begin(); | |
101 | if (m_prev_snap_id != CEPH_NOSNAP) { | |
102 | snap_id_it = m_local_snap_ids.upper_bound(m_prev_snap_id); | |
103 | } | |
104 | ||
105 | for (; snap_id_it != m_local_snap_ids.end(); ++snap_id_it) { | |
106 | librados::snap_t local_snap_id = *snap_id_it; | |
107 | ||
108 | m_local_image_ctx->snap_lock.get_read(); | |
109 | ||
110 | bool local_unprotected; | |
111 | int r = m_local_image_ctx->is_snap_unprotected(local_snap_id, | |
112 | &local_unprotected); | |
113 | if (r < 0) { | |
114 | derr << ": failed to retrieve local snap unprotect status: " | |
115 | << cpp_strerror(r) << dendl; | |
116 | m_local_image_ctx->snap_lock.put_read(); | |
117 | finish(r); | |
118 | return; | |
119 | } | |
120 | m_local_image_ctx->snap_lock.put_read(); | |
121 | ||
122 | if (local_unprotected) { | |
123 | // snap is already unprotected -- check next snap | |
124 | continue; | |
125 | } | |
126 | ||
127 | // if local snapshot is protected and (1) it isn't in our mapping | |
128 | // table, or (2) the remote snapshot isn't protected, unprotect it | |
129 | auto snap_seq_it = std::find_if( | |
130 | m_snap_seqs.begin(), m_snap_seqs.end(), | |
131 | [local_snap_id](const SnapSeqs::value_type& pair) { | |
132 | return pair.second == local_snap_id; | |
133 | }); | |
134 | ||
135 | if (snap_seq_it != m_snap_seqs.end()) { | |
136 | m_remote_image_ctx->snap_lock.get_read(); | |
137 | bool remote_unprotected; | |
138 | r = m_remote_image_ctx->is_snap_unprotected(snap_seq_it->first, | |
139 | &remote_unprotected); | |
140 | if (r < 0) { | |
141 | derr << ": failed to retrieve remote snap unprotect status: " | |
142 | << cpp_strerror(r) << dendl; | |
143 | m_remote_image_ctx->snap_lock.put_read(); | |
144 | finish(r); | |
145 | return; | |
146 | } | |
147 | m_remote_image_ctx->snap_lock.put_read(); | |
148 | ||
149 | if (remote_unprotected) { | |
150 | // remote is unprotected -- unprotect local snap | |
151 | break; | |
152 | } | |
153 | } else { | |
154 | // remote snapshot doesn't exist -- unprotect local snap | |
155 | break; | |
156 | } | |
157 | } | |
158 | ||
159 | if (snap_id_it == m_local_snap_ids.end()) { | |
160 | // no local snapshots to unprotect | |
161 | m_prev_snap_id = CEPH_NOSNAP; | |
162 | send_snap_remove(); | |
163 | return; | |
164 | } | |
165 | ||
166 | m_prev_snap_id = *snap_id_it; | |
167 | m_snap_name = get_snapshot_name(m_local_image_ctx, m_prev_snap_id); | |
168 | ||
169 | dout(20) << ": " | |
170 | << "snap_name=" << m_snap_name << ", " | |
171 | << "snap_id=" << m_prev_snap_id << dendl; | |
172 | ||
91327a77 AA |
173 | int r; |
174 | auto finish_op_ctx = start_local_op(&r); | |
31f18b77 FG |
175 | if (finish_op_ctx == nullptr) { |
176 | derr << ": lost exclusive lock" << dendl; | |
91327a77 | 177 | finish(r); |
31f18b77 FG |
178 | return; |
179 | } | |
180 | ||
181 | auto ctx = new FunctionContext([this, finish_op_ctx](int r) { | |
182 | handle_snap_unprotect(r); | |
183 | finish_op_ctx->complete(0); | |
184 | }); | |
7c673cae | 185 | RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock); |
31f18b77 FG |
186 | m_local_image_ctx->operations->execute_snap_unprotect( |
187 | cls::rbd::UserSnapshotNamespace(), m_snap_name.c_str(), ctx); | |
7c673cae FG |
188 | } |
189 | ||
190 | template <typename I> | |
191 | void SnapshotCopyRequest<I>::handle_snap_unprotect(int r) { | |
192 | dout(20) << ": r=" << r << dendl; | |
193 | ||
194 | if (r < 0) { | |
195 | derr << ": failed to unprotect snapshot '" << m_snap_name << "': " | |
196 | << cpp_strerror(r) << dendl; | |
197 | finish(r); | |
198 | return; | |
199 | } | |
200 | if (handle_cancellation()) | |
201 | { | |
202 | return; | |
203 | } | |
204 | ||
205 | send_snap_unprotect(); | |
206 | } | |
207 | ||
208 | template <typename I> | |
209 | void SnapshotCopyRequest<I>::send_snap_remove() { | |
210 | SnapIdSet::iterator snap_id_it = m_local_snap_ids.begin(); | |
211 | if (m_prev_snap_id != CEPH_NOSNAP) { | |
212 | snap_id_it = m_local_snap_ids.upper_bound(m_prev_snap_id); | |
213 | } | |
214 | ||
215 | for (; snap_id_it != m_local_snap_ids.end(); ++snap_id_it) { | |
216 | librados::snap_t local_snap_id = *snap_id_it; | |
217 | ||
218 | cls::rbd::SnapshotNamespace snap_namespace; | |
219 | m_local_image_ctx->snap_lock.get_read(); | |
31f18b77 FG |
220 | int r = m_local_image_ctx->get_snap_namespace(local_snap_id, |
221 | &snap_namespace); | |
7c673cae FG |
222 | m_local_image_ctx->snap_lock.put_read(); |
223 | if (r < 0) { | |
224 | derr << ": failed to retrieve local snap namespace: " << m_snap_name | |
225 | << dendl; | |
226 | finish(r); | |
227 | return; | |
228 | } | |
229 | ||
31f18b77 FG |
230 | if (boost::get<cls::rbd::UserSnapshotNamespace>(&snap_namespace) == |
231 | nullptr) { | |
7c673cae FG |
232 | continue; |
233 | } | |
234 | ||
235 | // if the local snapshot isn't in our mapping table, remove it | |
236 | auto snap_seq_it = std::find_if( | |
237 | m_snap_seqs.begin(), m_snap_seqs.end(), | |
238 | [local_snap_id](const SnapSeqs::value_type& pair) { | |
239 | return pair.second == local_snap_id; | |
240 | }); | |
241 | ||
242 | if (snap_seq_it == m_snap_seqs.end()) { | |
243 | break; | |
244 | } | |
245 | } | |
246 | ||
247 | if (snap_id_it == m_local_snap_ids.end()) { | |
248 | // no local snapshots to delete | |
249 | m_prev_snap_id = CEPH_NOSNAP; | |
250 | send_snap_create(); | |
251 | return; | |
252 | } | |
253 | ||
254 | m_prev_snap_id = *snap_id_it; | |
255 | m_snap_name = get_snapshot_name(m_local_image_ctx, m_prev_snap_id); | |
256 | ||
257 | dout(20) << ": " | |
258 | << "snap_name=" << m_snap_name << ", " | |
259 | << "snap_id=" << m_prev_snap_id << dendl; | |
260 | ||
91327a77 AA |
261 | int r; |
262 | auto finish_op_ctx = start_local_op(&r); | |
31f18b77 FG |
263 | if (finish_op_ctx == nullptr) { |
264 | derr << ": lost exclusive lock" << dendl; | |
91327a77 | 265 | finish(r); |
31f18b77 FG |
266 | return; |
267 | } | |
268 | ||
269 | auto ctx = new FunctionContext([this, finish_op_ctx](int r) { | |
270 | handle_snap_remove(r); | |
271 | finish_op_ctx->complete(0); | |
272 | }); | |
7c673cae | 273 | RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock); |
31f18b77 FG |
274 | m_local_image_ctx->operations->execute_snap_remove( |
275 | cls::rbd::UserSnapshotNamespace(), m_snap_name.c_str(), ctx); | |
7c673cae FG |
276 | } |
277 | ||
278 | template <typename I> | |
279 | void SnapshotCopyRequest<I>::handle_snap_remove(int r) { | |
280 | dout(20) << ": r=" << r << dendl; | |
281 | ||
282 | if (r < 0) { | |
283 | derr << ": failed to remove snapshot '" << m_snap_name << "': " | |
284 | << cpp_strerror(r) << dendl; | |
285 | finish(r); | |
286 | return; | |
287 | } | |
288 | if (handle_cancellation()) | |
289 | { | |
290 | return; | |
291 | } | |
292 | ||
293 | send_snap_remove(); | |
294 | } | |
295 | ||
296 | template <typename I> | |
297 | void SnapshotCopyRequest<I>::send_snap_create() { | |
298 | SnapIdSet::iterator snap_id_it = m_remote_snap_ids.begin(); | |
299 | if (m_prev_snap_id != CEPH_NOSNAP) { | |
300 | snap_id_it = m_remote_snap_ids.upper_bound(m_prev_snap_id); | |
301 | } | |
302 | ||
303 | for (; snap_id_it != m_remote_snap_ids.end(); ++snap_id_it) { | |
304 | librados::snap_t remote_snap_id = *snap_id_it; | |
305 | ||
306 | cls::rbd::SnapshotNamespace snap_namespace; | |
307 | m_remote_image_ctx->snap_lock.get_read(); | |
308 | int r = m_remote_image_ctx->get_snap_namespace(remote_snap_id, &snap_namespace); | |
309 | m_remote_image_ctx->snap_lock.put_read(); | |
310 | if (r < 0) { | |
311 | derr << ": failed to retrieve remote snap namespace: " << m_snap_name | |
312 | << dendl; | |
313 | finish(r); | |
314 | return; | |
315 | } | |
316 | ||
317 | // if the remote snapshot isn't in our mapping table, create it | |
318 | if (m_snap_seqs.find(remote_snap_id) == m_snap_seqs.end() && | |
319 | boost::get<cls::rbd::UserSnapshotNamespace>(&snap_namespace) != nullptr) { | |
320 | break; | |
321 | } | |
322 | } | |
323 | ||
324 | if (snap_id_it == m_remote_snap_ids.end()) { | |
325 | // no remote snapshots to create | |
326 | m_prev_snap_id = CEPH_NOSNAP; | |
327 | send_snap_protect(); | |
328 | return; | |
329 | } | |
330 | ||
331 | m_prev_snap_id = *snap_id_it; | |
332 | m_snap_name = get_snapshot_name(m_remote_image_ctx, m_prev_snap_id); | |
333 | ||
334 | m_remote_image_ctx->snap_lock.get_read(); | |
335 | auto snap_info_it = m_remote_image_ctx->snap_info.find(m_prev_snap_id); | |
336 | if (snap_info_it == m_remote_image_ctx->snap_info.end()) { | |
337 | m_remote_image_ctx->snap_lock.put_read(); | |
338 | derr << ": failed to retrieve remote snap info: " << m_snap_name | |
339 | << dendl; | |
340 | finish(-ENOENT); | |
341 | return; | |
342 | } | |
343 | ||
344 | uint64_t size = snap_info_it->second.size; | |
345 | m_snap_namespace = snap_info_it->second.snap_namespace; | |
346 | librbd::ParentSpec parent_spec; | |
347 | uint64_t parent_overlap = 0; | |
348 | if (snap_info_it->second.parent.spec.pool_id != -1) { | |
349 | parent_spec = m_local_parent_spec; | |
350 | parent_overlap = snap_info_it->second.parent.overlap; | |
351 | } | |
352 | m_remote_image_ctx->snap_lock.put_read(); | |
353 | ||
354 | ||
355 | dout(20) << ": " | |
356 | << "snap_name=" << m_snap_name << ", " | |
357 | << "snap_id=" << m_prev_snap_id << ", " | |
358 | << "size=" << size << ", " | |
359 | << "parent_info=[" | |
360 | << "pool_id=" << parent_spec.pool_id << ", " | |
361 | << "image_id=" << parent_spec.image_id << ", " | |
362 | << "snap_id=" << parent_spec.snap_id << ", " | |
363 | << "overlap=" << parent_overlap << "]" << dendl; | |
364 | ||
91327a77 AA |
365 | int r; |
366 | Context *finish_op_ctx = start_local_op(&r); | |
31f18b77 FG |
367 | if (finish_op_ctx == nullptr) { |
368 | derr << ": lost exclusive lock" << dendl; | |
91327a77 | 369 | finish(r); |
31f18b77 FG |
370 | return; |
371 | } | |
372 | ||
373 | auto ctx = new FunctionContext([this, finish_op_ctx](int r) { | |
374 | handle_snap_create(r); | |
375 | finish_op_ctx->complete(0); | |
376 | }); | |
7c673cae | 377 | SnapshotCreateRequest<I> *req = SnapshotCreateRequest<I>::create( |
31f18b77 FG |
378 | m_local_image_ctx, m_snap_name, m_snap_namespace, size, parent_spec, |
379 | parent_overlap, ctx); | |
7c673cae FG |
380 | req->send(); |
381 | } | |
382 | ||
383 | template <typename I> | |
384 | void SnapshotCopyRequest<I>::handle_snap_create(int r) { | |
385 | dout(20) << ": r=" << r << dendl; | |
386 | ||
387 | if (r < 0) { | |
388 | derr << ": failed to create snapshot '" << m_snap_name << "': " | |
389 | << cpp_strerror(r) << dendl; | |
390 | finish(r); | |
391 | return; | |
392 | } | |
393 | if (handle_cancellation()) | |
394 | { | |
395 | return; | |
396 | } | |
397 | ||
398 | assert(m_prev_snap_id != CEPH_NOSNAP); | |
399 | ||
400 | auto snap_it = m_local_image_ctx->snap_ids.find({cls::rbd::UserSnapshotNamespace(), | |
401 | m_snap_name}); | |
402 | assert(snap_it != m_local_image_ctx->snap_ids.end()); | |
403 | librados::snap_t local_snap_id = snap_it->second; | |
404 | ||
405 | dout(20) << ": mapping remote snap id " << m_prev_snap_id << " to " | |
406 | << local_snap_id << dendl; | |
407 | m_snap_seqs[m_prev_snap_id] = local_snap_id; | |
408 | ||
409 | send_snap_create(); | |
410 | } | |
411 | ||
412 | template <typename I> | |
413 | void SnapshotCopyRequest<I>::send_snap_protect() { | |
414 | SnapIdSet::iterator snap_id_it = m_remote_snap_ids.begin(); | |
415 | if (m_prev_snap_id != CEPH_NOSNAP) { | |
416 | snap_id_it = m_remote_snap_ids.upper_bound(m_prev_snap_id); | |
417 | } | |
418 | ||
419 | for (; snap_id_it != m_remote_snap_ids.end(); ++snap_id_it) { | |
420 | librados::snap_t remote_snap_id = *snap_id_it; | |
421 | ||
422 | m_remote_image_ctx->snap_lock.get_read(); | |
423 | ||
424 | bool remote_protected; | |
425 | int r = m_remote_image_ctx->is_snap_protected(remote_snap_id, | |
426 | &remote_protected); | |
427 | if (r < 0) { | |
428 | derr << ": failed to retrieve remote snap protect status: " | |
429 | << cpp_strerror(r) << dendl; | |
430 | m_remote_image_ctx->snap_lock.put_read(); | |
431 | finish(r); | |
432 | return; | |
433 | } | |
434 | m_remote_image_ctx->snap_lock.put_read(); | |
435 | ||
436 | if (!remote_protected) { | |
437 | // snap is not protected -- check next snap | |
438 | continue; | |
439 | } | |
440 | ||
441 | // if local snapshot is not protected, protect it | |
442 | auto snap_seq_it = m_snap_seqs.find(remote_snap_id); | |
443 | assert(snap_seq_it != m_snap_seqs.end()); | |
444 | ||
445 | m_local_image_ctx->snap_lock.get_read(); | |
446 | bool local_protected; | |
447 | r = m_local_image_ctx->is_snap_protected(snap_seq_it->second, | |
448 | &local_protected); | |
449 | if (r < 0) { | |
450 | derr << ": failed to retrieve local snap protect status: " | |
451 | << cpp_strerror(r) << dendl; | |
452 | m_local_image_ctx->snap_lock.put_read(); | |
453 | finish(r); | |
454 | return; | |
455 | } | |
456 | m_local_image_ctx->snap_lock.put_read(); | |
457 | ||
458 | if (!local_protected) { | |
459 | break; | |
460 | } | |
461 | } | |
462 | ||
463 | if (snap_id_it == m_remote_snap_ids.end()) { | |
464 | // no local snapshots to protect | |
465 | m_prev_snap_id = CEPH_NOSNAP; | |
466 | send_update_client(); | |
467 | return; | |
468 | } | |
469 | ||
470 | m_prev_snap_id = *snap_id_it; | |
471 | m_snap_name = get_snapshot_name(m_remote_image_ctx, m_prev_snap_id); | |
472 | ||
473 | dout(20) << ": " | |
474 | << "snap_name=" << m_snap_name << ", " | |
475 | << "snap_id=" << m_prev_snap_id << dendl; | |
476 | ||
91327a77 AA |
477 | int r; |
478 | auto finish_op_ctx = start_local_op(&r); | |
31f18b77 FG |
479 | if (finish_op_ctx == nullptr) { |
480 | derr << ": lost exclusive lock" << dendl; | |
91327a77 | 481 | finish(r); |
31f18b77 FG |
482 | return; |
483 | } | |
484 | ||
485 | auto ctx = new FunctionContext([this, finish_op_ctx](int r) { | |
486 | handle_snap_protect(r); | |
487 | finish_op_ctx->complete(0); | |
488 | }); | |
7c673cae | 489 | RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock); |
31f18b77 FG |
490 | m_local_image_ctx->operations->execute_snap_protect( |
491 | cls::rbd::UserSnapshotNamespace(), m_snap_name.c_str(), ctx); | |
7c673cae FG |
492 | } |
493 | ||
494 | template <typename I> | |
495 | void SnapshotCopyRequest<I>::handle_snap_protect(int r) { | |
496 | dout(20) << ": r=" << r << dendl; | |
497 | ||
498 | if (r < 0) { | |
499 | derr << ": failed to protect snapshot '" << m_snap_name << "': " | |
500 | << cpp_strerror(r) << dendl; | |
501 | finish(r); | |
502 | return; | |
503 | } | |
504 | if (handle_cancellation()) | |
505 | { | |
506 | return; | |
507 | } | |
508 | ||
509 | send_snap_protect(); | |
510 | } | |
511 | ||
512 | template <typename I> | |
513 | void SnapshotCopyRequest<I>::send_update_client() { | |
514 | dout(20) << dendl; | |
515 | ||
516 | compute_snap_map(); | |
517 | ||
518 | librbd::journal::MirrorPeerClientMeta client_meta(*m_client_meta); | |
519 | client_meta.snap_seqs = m_snap_seqs; | |
520 | ||
521 | librbd::journal::ClientData client_data(client_meta); | |
522 | bufferlist data_bl; | |
523 | ::encode(client_data, data_bl); | |
524 | ||
525 | Context *ctx = create_context_callback< | |
526 | SnapshotCopyRequest<I>, &SnapshotCopyRequest<I>::handle_update_client>( | |
527 | this); | |
528 | m_journaler->update_client(data_bl, ctx); | |
529 | } | |
530 | ||
531 | template <typename I> | |
532 | void SnapshotCopyRequest<I>::handle_update_client(int r) { | |
533 | dout(20) << ": r=" << r << dendl; | |
534 | ||
535 | if (r < 0) { | |
536 | derr << ": failed to update client data: " << cpp_strerror(r) | |
537 | << dendl; | |
538 | finish(r); | |
539 | return; | |
540 | } | |
541 | if (handle_cancellation()) | |
542 | { | |
543 | return; | |
544 | } | |
545 | ||
546 | m_client_meta->snap_seqs = m_snap_seqs; | |
547 | ||
548 | finish(0); | |
549 | } | |
550 | ||
551 | template <typename I> | |
552 | bool SnapshotCopyRequest<I>::handle_cancellation() { | |
553 | { | |
554 | Mutex::Locker locker(m_lock); | |
555 | if (!m_canceled) { | |
556 | return false; | |
557 | } | |
558 | } | |
559 | dout(10) << ": snapshot copy canceled" << dendl; | |
560 | finish(-ECANCELED); | |
561 | return true; | |
562 | } | |
563 | ||
564 | template <typename I> | |
565 | void SnapshotCopyRequest<I>::error(int r) { | |
566 | dout(20) << ": r=" << r << dendl; | |
567 | ||
568 | m_work_queue->queue(new FunctionContext([this, r](int r1) { finish(r); })); | |
569 | } | |
570 | ||
571 | template <typename I> | |
572 | void SnapshotCopyRequest<I>::compute_snap_map() { | |
573 | SnapIds local_snap_ids; | |
574 | for (auto &pair : m_snap_seqs) { | |
575 | local_snap_ids.reserve(1 + local_snap_ids.size()); | |
576 | local_snap_ids.insert(local_snap_ids.begin(), pair.second); | |
577 | m_snap_map->insert(std::make_pair(pair.first, local_snap_ids)); | |
578 | } | |
579 | } | |
580 | ||
581 | template <typename I> | |
582 | int SnapshotCopyRequest<I>::validate_parent(I *image_ctx, | |
583 | librbd::ParentSpec *spec) { | |
584 | RWLock::RLocker owner_locker(image_ctx->owner_lock); | |
585 | RWLock::RLocker snap_locker(image_ctx->snap_lock); | |
586 | ||
587 | // ensure remote image's parent specs are still consistent | |
588 | *spec = image_ctx->parent_md.spec; | |
589 | for (auto &snap_info_pair : image_ctx->snap_info) { | |
590 | auto &parent_spec = snap_info_pair.second.parent.spec; | |
591 | if (parent_spec.pool_id == -1) { | |
592 | continue; | |
593 | } else if (spec->pool_id == -1) { | |
594 | *spec = parent_spec; | |
595 | continue; | |
596 | } | |
597 | ||
598 | if (*spec != parent_spec) { | |
599 | return -EINVAL; | |
600 | } | |
601 | } | |
602 | return 0; | |
603 | } | |
604 | ||
31f18b77 | 605 | template <typename I> |
91327a77 | 606 | Context *SnapshotCopyRequest<I>::start_local_op(int *r) { |
31f18b77 FG |
607 | RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock); |
608 | if (m_local_image_ctx->exclusive_lock == nullptr) { | |
91327a77 | 609 | *r = -EROFS; |
31f18b77 FG |
610 | return nullptr; |
611 | } | |
91327a77 | 612 | return m_local_image_ctx->exclusive_lock->start_op(r); |
31f18b77 FG |
613 | } |
614 | ||
7c673cae FG |
615 | } // namespace image_sync |
616 | } // namespace mirror | |
617 | } // namespace rbd | |
618 | ||
619 | template class rbd::mirror::image_sync::SnapshotCopyRequest<librbd::ImageCtx>; |