]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/deep_copy/ImageCopyRequest.cc
import ceph nautilus 14.2.2
[ceph.git] / ceph / src / librbd / deep_copy / ImageCopyRequest.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 "ImageCopyRequest.h"
5#include "ObjectCopyRequest.h"
6#include "common/errno.h"
7#include "librbd/Utils.h"
8#include "librbd/deep_copy/Utils.h"
9#include "librbd/image/CloseRequest.h"
10#include "librbd/image/OpenRequest.h"
11#include "osdc/Striper.h"
12
13#define dout_subsys ceph_subsys_rbd
14#undef dout_prefix
15#define dout_prefix *_dout << "librbd::deep_copy::ImageCopyRequest: " \
16 << this << " " << __func__ << ": "
17
18namespace librbd {
19namespace deep_copy {
20
21using librbd::util::create_context_callback;
22using librbd::util::unique_lock_name;
23
24template <typename I>
25ImageCopyRequest<I>::ImageCopyRequest(I *src_image_ctx, I *dst_image_ctx,
26 librados::snap_t snap_id_start,
27 librados::snap_t snap_id_end,
28 bool flatten,
29 const ObjectNumber &object_number,
30 const SnapSeqs &snap_seqs,
31 ProgressContext *prog_ctx,
32 Context *on_finish)
33 : RefCountedObject(dst_image_ctx->cct, 1), m_src_image_ctx(src_image_ctx),
34 m_dst_image_ctx(dst_image_ctx), m_snap_id_start(snap_id_start),
35 m_snap_id_end(snap_id_end), m_flatten(flatten),
36 m_object_number(object_number), m_snap_seqs(snap_seqs),
37 m_prog_ctx(prog_ctx), m_on_finish(on_finish), m_cct(dst_image_ctx->cct),
38 m_lock(unique_lock_name("ImageCopyRequest::m_lock", this)) {
39}
40
41template <typename I>
42void ImageCopyRequest<I>::send() {
43 util::compute_snap_map(m_snap_id_start, m_snap_id_end, m_snap_seqs,
44 &m_snap_map);
45 if (m_snap_map.empty()) {
46 lderr(m_cct) << "failed to map snapshots within boundary" << dendl;
47 finish(-EINVAL);
48 return;
49 }
50
51 send_object_copies();
52}
53
54template <typename I>
55void ImageCopyRequest<I>::cancel() {
56 Mutex::Locker locker(m_lock);
57
58 ldout(m_cct, 20) << dendl;
59 m_canceled = true;
60}
61
62template <typename I>
63void ImageCopyRequest<I>::send_object_copies() {
64 m_object_no = 0;
65 if (m_object_number) {
66 m_object_no = *m_object_number + 1;
67 }
68
69 uint64_t size;
70 {
71 RWLock::RLocker snap_locker(m_src_image_ctx->snap_lock);
72 size = m_src_image_ctx->get_image_size(CEPH_NOSNAP);
73 for (auto snap_id : m_src_image_ctx->snaps) {
74 size = std::max(size, m_src_image_ctx->get_image_size(snap_id));
75 }
76 }
77 m_end_object_no = Striper::get_num_objects(m_dst_image_ctx->layout, size);
78
79 ldout(m_cct, 20) << "start_object=" << m_object_no << ", "
80 << "end_object=" << m_end_object_no << dendl;
81
82 bool complete;
83 {
84 Mutex::Locker locker(m_lock);
85 for (uint64_t i = 0;
86 i < m_src_image_ctx->config.template get_val<uint64_t>("rbd_concurrent_management_ops");
87 ++i) {
88 send_next_object_copy();
89 if (m_ret_val < 0 && m_current_ops == 0) {
90 break;
91 }
92 }
93 complete = (m_current_ops == 0) && !m_updating_progress;
94 }
95
96 if (complete) {
97 finish(m_ret_val);
98 }
99}
100
101template <typename I>
102void ImageCopyRequest<I>::send_next_object_copy() {
103 ceph_assert(m_lock.is_locked());
104
105 if (m_canceled && m_ret_val == 0) {
106 ldout(m_cct, 10) << "image copy canceled" << dendl;
107 m_ret_val = -ECANCELED;
108 }
109
110 if (m_ret_val < 0 || m_object_no >= m_end_object_no) {
111 return;
112 }
113
114 uint64_t ono = m_object_no++;
115
116 ldout(m_cct, 20) << "object_num=" << ono << dendl;
117
118 ++m_current_ops;
119
120 Context *ctx = new FunctionContext(
121 [this, ono](int r) {
122 handle_object_copy(ono, r);
123 });
124 ObjectCopyRequest<I> *req = ObjectCopyRequest<I>::create(
125 m_src_image_ctx, m_dst_image_ctx, m_snap_map, ono, m_flatten, ctx);
126 req->send();
127}
128
129template <typename I>
130void ImageCopyRequest<I>::handle_object_copy(uint64_t object_no, int r) {
131 ldout(m_cct, 20) << "object_no=" << object_no << ", r=" << r << dendl;
132
133 bool complete;
134 {
135 Mutex::Locker locker(m_lock);
136 ceph_assert(m_current_ops > 0);
137 --m_current_ops;
138
139 if (r < 0 && r != -ENOENT) {
140 lderr(m_cct) << "object copy failed: " << cpp_strerror(r) << dendl;
141 if (m_ret_val == 0) {
142 m_ret_val = r;
143 }
144 } else {
145 m_copied_objects.push(object_no);
81eedcae
TL
146 while (!m_updating_progress && !m_copied_objects.empty() &&
147 m_copied_objects.top() ==
148 (m_object_number ? *m_object_number + 1 : 0)) {
11fdf7f2
TL
149 m_object_number = m_copied_objects.top();
150 m_copied_objects.pop();
151 uint64_t progress_object_no = *m_object_number + 1;
152 m_updating_progress = true;
153 m_lock.Unlock();
154 m_prog_ctx->update_progress(progress_object_no, m_end_object_no);
155 m_lock.Lock();
156 ceph_assert(m_updating_progress);
157 m_updating_progress = false;
158 }
159 }
160
161 send_next_object_copy();
162 complete = (m_current_ops == 0) && !m_updating_progress;
163 }
164
165 if (complete) {
166 finish(m_ret_val);
167 }
168}
169
170template <typename I>
171void ImageCopyRequest<I>::finish(int r) {
172 ldout(m_cct, 20) << "r=" << r << dendl;
173
174 m_on_finish->complete(r);
175 put();
176}
177
178} // namespace deep_copy
179} // namespace librbd
180
181template class librbd::deep_copy::ImageCopyRequest<librbd::ImageCtx>;