]>
git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/deep_copy/ImageCopyRequest.cc
17aaa533efa4b4f73730c3c04db411f2a7b45bec
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "ImageCopyRequest.h"
5 #include "ObjectCopyRequest.h"
6 #include "common/errno.h"
7 #include "librbd/Utils.h"
8 #include "librbd/deep_copy/Handler.h"
9 #include "librbd/deep_copy/Utils.h"
10 #include "librbd/image/CloseRequest.h"
11 #include "librbd/image/OpenRequest.h"
12 #include "librbd/object_map/DiffRequest.h"
13 #include "osdc/Striper.h"
15 #define dout_subsys ceph_subsys_rbd
17 #define dout_prefix *_dout << "librbd::deep_copy::ImageCopyRequest: " \
18 << this << " " << __func__ << ": "
23 using librbd::util::create_context_callback
;
24 using librbd::util::unique_lock_name
;
27 ImageCopyRequest
<I
>::ImageCopyRequest(I
*src_image_ctx
, I
*dst_image_ctx
,
28 librados::snap_t src_snap_id_start
,
29 librados::snap_t src_snap_id_end
,
30 librados::snap_t dst_snap_id_start
,
32 const ObjectNumber
&object_number
,
33 const SnapSeqs
&snap_seqs
,
36 : RefCountedObject(dst_image_ctx
->cct
), m_src_image_ctx(src_image_ctx
),
37 m_dst_image_ctx(dst_image_ctx
), m_src_snap_id_start(src_snap_id_start
),
38 m_src_snap_id_end(src_snap_id_end
), m_dst_snap_id_start(dst_snap_id_start
),
39 m_flatten(flatten
), m_object_number(object_number
), m_snap_seqs(snap_seqs
),
40 m_handler(handler
), m_on_finish(on_finish
), m_cct(dst_image_ctx
->cct
),
41 m_lock(ceph::make_mutex(unique_lock_name("ImageCopyRequest::m_lock", this))) {
45 void ImageCopyRequest
<I
>::send() {
46 m_dst_image_ctx
->image_lock
.lock_shared();
47 util::compute_snap_map(m_dst_image_ctx
->cct
, m_src_snap_id_start
,
48 m_src_snap_id_end
, m_dst_image_ctx
->snaps
, m_snap_seqs
,
50 m_dst_image_ctx
->image_lock
.unlock_shared();
52 if (m_snap_map
.empty()) {
53 lderr(m_cct
) << "failed to map snapshots within boundary" << dendl
;
62 void ImageCopyRequest
<I
>::cancel() {
63 std::lock_guard locker
{m_lock
};
65 ldout(m_cct
, 20) << dendl
;
70 void ImageCopyRequest
<I
>::map_src_objects(uint64_t dst_object
,
71 std::set
<uint64_t> *src_objects
) {
72 std::vector
<std::pair
<uint64_t, uint64_t>> image_extents
;
73 Striper::extent_to_file(m_cct
, &m_dst_image_ctx
->layout
, dst_object
, 0,
74 m_dst_image_ctx
->layout
.object_size
, image_extents
);
76 for (auto &e
: image_extents
) {
77 std::map
<object_t
, std::vector
<ObjectExtent
>> src_object_extents
;
78 Striper::file_to_extents(m_cct
, m_src_image_ctx
->format_string
,
79 &m_src_image_ctx
->layout
, e
.first
, e
.second
, 0,
81 for (auto &p
: src_object_extents
) {
82 for (auto &s
: p
.second
) {
83 src_objects
->insert(s
.objectno
);
88 ceph_assert(!src_objects
->empty());
90 ldout(m_cct
, 20) << dst_object
<< " -> " << *src_objects
<< dendl
;
94 void ImageCopyRequest
<I
>::compute_diff() {
100 ldout(m_cct
, 10) << dendl
;
102 auto ctx
= create_context_callback
<
103 ImageCopyRequest
<I
>, &ImageCopyRequest
<I
>::handle_compute_diff
>(this);
104 auto req
= object_map::DiffRequest
<I
>::create(m_src_image_ctx
, m_src_snap_id_start
,
105 m_src_snap_id_end
, &m_object_diff_state
,
110 template <typename I
>
111 void ImageCopyRequest
<I
>::handle_compute_diff(int r
) {
112 ldout(m_cct
, 10) << "r=" << r
<< dendl
;
115 ldout(m_cct
, 10) << "fast-diff optimization disabled" << dendl
;
116 m_object_diff_state
.resize(0);
119 send_object_copies();
122 template <typename I
>
123 void ImageCopyRequest
<I
>::send_object_copies() {
125 if (m_object_number
) {
126 m_object_no
= *m_object_number
+ 1;
131 std::shared_lock image_locker
{m_src_image_ctx
->image_lock
};
132 size
= m_src_image_ctx
->get_image_size(CEPH_NOSNAP
);
133 for (auto snap_id
: m_src_image_ctx
->snaps
) {
134 size
= std::max(size
, m_src_image_ctx
->get_image_size(snap_id
));
137 m_end_object_no
= Striper::get_num_objects(m_dst_image_ctx
->layout
, size
);
139 ldout(m_cct
, 20) << "start_object=" << m_object_no
<< ", "
140 << "end_object=" << m_end_object_no
<< dendl
;
144 std::lock_guard locker
{m_lock
};
145 auto max_ops
= m_src_image_ctx
->config
.template get_val
<uint64_t>(
146 "rbd_concurrent_management_ops");
148 // attempt to schedule at least 'max_ops' initial requests where
149 // some objects might be skipped if fast-diff notes no change
150 while (m_current_ops
< max_ops
) {
151 int r
= send_next_object_copy();
157 complete
= (m_current_ops
== 0) && !m_updating_progress
;
165 template <typename I
>
166 int ImageCopyRequest
<I
>::send_next_object_copy() {
167 ceph_assert(ceph_mutex_is_locked(m_lock
));
169 if (m_canceled
&& m_ret_val
== 0) {
170 ldout(m_cct
, 10) << "image copy canceled" << dendl
;
171 m_ret_val
= -ECANCELED
;
176 } else if (m_object_no
>= m_end_object_no
) {
180 uint64_t ono
= m_object_no
++;
182 if (m_object_diff_state
.size() > 0) {
183 std::set
<uint64_t> src_objects
;
184 map_src_objects(ono
, &src_objects
);
187 for (auto src_ono
: src_objects
) {
188 if (src_ono
>= m_object_diff_state
.size() ||
189 m_object_diff_state
[src_ono
] != object_map::DIFF_STATE_NONE
) {
196 ldout(m_cct
, 20) << "skipping clean object " << ono
<< dendl
;
201 ldout(m_cct
, 20) << "object_num=" << ono
<< dendl
;
204 Context
*ctx
= new LambdaContext(
206 handle_object_copy(ono
, r
);
208 auto req
= ObjectCopyRequest
<I
>::create(
209 m_src_image_ctx
, m_dst_image_ctx
, m_src_snap_id_start
, m_dst_snap_id_start
,
210 m_snap_map
, ono
, m_flatten
, m_handler
, ctx
);
215 template <typename I
>
216 void ImageCopyRequest
<I
>::handle_object_copy(uint64_t object_no
, int r
) {
217 ldout(m_cct
, 20) << "object_no=" << object_no
<< ", r=" << r
<< dendl
;
221 std::lock_guard locker
{m_lock
};
222 ceph_assert(m_current_ops
> 0);
225 if (r
< 0 && r
!= -ENOENT
) {
226 lderr(m_cct
) << "object copy failed: " << cpp_strerror(r
) << dendl
;
227 if (m_ret_val
== 0) {
231 m_copied_objects
.push(object_no
);
232 while (!m_updating_progress
&& !m_copied_objects
.empty() &&
233 m_copied_objects
.top() ==
234 (m_object_number
? *m_object_number
+ 1 : 0)) {
235 m_object_number
= m_copied_objects
.top();
236 m_copied_objects
.pop();
237 uint64_t progress_object_no
= *m_object_number
+ 1;
238 m_updating_progress
= true;
240 m_handler
->update_progress(progress_object_no
, m_end_object_no
);
242 ceph_assert(m_updating_progress
);
243 m_updating_progress
= false;
248 r
= send_next_object_copy();
254 complete
= (m_current_ops
== 0) && !m_updating_progress
;
262 template <typename I
>
263 void ImageCopyRequest
<I
>::finish(int r
) {
264 ldout(m_cct
, 20) << "r=" << r
<< dendl
;
266 m_on_finish
->complete(r
);
270 } // namespace deep_copy
271 } // namespace librbd
273 template class librbd::deep_copy::ImageCopyRequest
<librbd::ImageCtx
>;