]>
Commit | Line | Data |
---|---|---|
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 | ||
18 | namespace librbd { | |
19 | namespace deep_copy { | |
20 | ||
21 | using librbd::util::create_context_callback; | |
22 | using librbd::util::unique_lock_name; | |
23 | ||
24 | template <typename I> | |
25 | ImageCopyRequest<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 | ||
41 | template <typename I> | |
42 | void 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 | ||
54 | template <typename I> | |
55 | void ImageCopyRequest<I>::cancel() { | |
56 | Mutex::Locker locker(m_lock); | |
57 | ||
58 | ldout(m_cct, 20) << dendl; | |
59 | m_canceled = true; | |
60 | } | |
61 | ||
62 | template <typename I> | |
63 | void 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 | ||
101 | template <typename I> | |
102 | void 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 | ||
129 | template <typename I> | |
130 | void 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 | ||
170 | template <typename I> | |
171 | void 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 | ||
181 | template class librbd::deep_copy::ImageCopyRequest<librbd::ImageCtx>; |