1616
1717#define dout_subsys ceph_subsys_rbd
1818#undef dout_prefix
19- #define dout_prefix *_dout << " librbd::migration::NativeFormat: " << this \
20- << " " << __func__ << " : "
19+ #define dout_prefix *_dout << " librbd::migration::NativeFormat: " << __func__ \
20+ << " : "
2121
2222namespace librbd {
2323namespace migration {
@@ -51,45 +51,47 @@ std::string NativeFormat<I>::build_source_spec(
5151}
5252
5353template <typename I>
54- NativeFormat<I>::NativeFormat(
55- I* image_ctx, const json_spirit::mObject & json_object, bool import_only)
56- : m_image_ctx(image_ctx), m_json_object(json_object),
57- m_import_only (import_only) {
54+ bool NativeFormat<I>::is_source_spec(
55+ const json_spirit::mObject & source_spec_object) {
56+ auto it = source_spec_object.find (TYPE_KEY);
57+ return it != source_spec_object.end () &&
58+ it->second .type () == json_spirit::str_type &&
59+ it->second .get_str () == " native" ;
5860}
5961
6062template <typename I>
61- void NativeFormat<I>::open(Context* on_finish) {
62- auto cct = m_image_ctx->cct ;
63- ldout (cct, 10 ) << dendl;
64-
63+ int NativeFormat<I>::create_image_ctx(
64+ librados::IoCtx& dst_io_ctx,
65+ const json_spirit::mObject & source_spec_object,
66+ bool import_only, uint64_t src_snap_id, I** src_image_ctx) {
67+ auto cct = reinterpret_cast <CephContext*>(dst_io_ctx.cct ());
6568 int64_t pool_id = -1 ;
6669 std::string pool_namespace;
6770 std::string image_name;
6871 std::string image_id;
72+ std::string snap_name;
73+ uint64_t snap_id = CEPH_NOSNAP;
6974
70- if (auto it = m_json_object .find (POOL_NAME_KEY);
71- it != m_json_object .end ()) {
75+ if (auto it = source_spec_object .find (POOL_NAME_KEY);
76+ it != source_spec_object .end ()) {
7277 if (it->second .type () == json_spirit::str_type) {
73- librados::Rados rados (m_image_ctx-> md_ctx );
78+ librados::Rados rados (dst_io_ctx );
7479 pool_id = rados.pool_lookup (it->second .get_str ().c_str ());
7580 if (pool_id < 0 ) {
7681 lderr (cct) << " failed to lookup pool" << dendl;
77- on_finish->complete (static_cast <int >(pool_id));
78- return ;
82+ return static_cast <int >(pool_id);
7983 }
8084 } else {
8185 lderr (cct) << " invalid pool name" << dendl;
82- on_finish->complete (-EINVAL);
83- return ;
86+ return -EINVAL;
8487 }
8588 }
8689
87- if (auto it = m_json_object .find (POOL_ID_KEY);
88- it != m_json_object .end ()) {
90+ if (auto it = source_spec_object .find (POOL_ID_KEY);
91+ it != source_spec_object .end ()) {
8992 if (pool_id != -1 ) {
9093 lderr (cct) << " cannot specify both pool name and pool id" << dendl;
91- on_finish->complete (-EINVAL);
92- return ;
94+ return -EINVAL;
9395 }
9496 if (it->second .type () == json_spirit::int_type) {
9597 pool_id = it->second .get_int64 ();
@@ -101,232 +103,107 @@ void NativeFormat<I>::open(Context* on_finish) {
101103 }
102104 if (pool_id == -1 ) {
103105 lderr (cct) << " invalid pool id" << dendl;
104- on_finish->complete (-EINVAL);
105- return ;
106+ return -EINVAL;
106107 }
107108 }
108109
109110 if (pool_id == -1 ) {
110111 lderr (cct) << " missing pool name or pool id" << dendl;
111- on_finish->complete (-EINVAL);
112- return ;
112+ return -EINVAL;
113113 }
114114
115- if (auto it = m_json_object .find (POOL_NAMESPACE_KEY);
116- it != m_json_object .end ()) {
115+ if (auto it = source_spec_object .find (POOL_NAMESPACE_KEY);
116+ it != source_spec_object .end ()) {
117117 if (it->second .type () == json_spirit::str_type) {
118118 pool_namespace = it->second .get_str ();
119119 } else {
120120 lderr (cct) << " invalid pool namespace" << dendl;
121- on_finish->complete (-EINVAL);
122- return ;
121+ return -EINVAL;
123122 }
124123 }
125124
126- if (auto it = m_json_object .find (IMAGE_NAME_KEY);
127- it != m_json_object .end ()) {
125+ if (auto it = source_spec_object .find (IMAGE_NAME_KEY);
126+ it != source_spec_object .end ()) {
128127 if (it->second .type () == json_spirit::str_type) {
129128 image_name = it->second .get_str ();
130129 } else {
131130 lderr (cct) << " invalid image name" << dendl;
132- on_finish->complete (-EINVAL);
133- return ;
131+ return -EINVAL;
134132 }
135133 } else {
136134 lderr (cct) << " missing image name" << dendl;
137- on_finish->complete (-EINVAL);
138- return ;
135+ return -EINVAL;
139136 }
140137
141- if (auto it = m_json_object .find (IMAGE_ID_KEY);
142- it != m_json_object .end ()) {
138+ if (auto it = source_spec_object .find (IMAGE_ID_KEY);
139+ it != source_spec_object .end ()) {
143140 if (it->second .type () == json_spirit::str_type) {
144141 image_id = it->second .get_str ();
145142 } else {
146143 lderr (cct) << " invalid image id" << dendl;
147- on_finish->complete (-EINVAL);
148- return ;
144+ return -EINVAL;
149145 }
150146 }
151147
152- if (auto it = m_json_object .find (SNAP_NAME_KEY);
153- it != m_json_object .end ()) {
148+ if (auto it = source_spec_object .find (SNAP_NAME_KEY);
149+ it != source_spec_object .end ()) {
154150 if (it->second .type () == json_spirit::str_type) {
155- m_snap_name = it->second .get_str ();
151+ snap_name = it->second .get_str ();
156152 } else {
157153 lderr (cct) << " invalid snap name" << dendl;
158- on_finish->complete (-EINVAL);
159- return ;
154+ return -EINVAL;
160155 }
161156 }
162157
163- if (auto it = m_json_object .find (SNAP_ID_KEY);
164- it != m_json_object .end ()) {
165- if (!m_snap_name .empty ()) {
158+ if (auto it = source_spec_object .find (SNAP_ID_KEY);
159+ it != source_spec_object .end ()) {
160+ if (!snap_name .empty ()) {
166161 lderr (cct) << " cannot specify both snap name and snap id" << dendl;
167- on_finish->complete (-EINVAL);
168- return ;
162+ return -EINVAL;
169163 }
170164 if (it->second .type () == json_spirit::int_type) {
171- m_snap_id = it->second .get_uint64 ();
165+ snap_id = it->second .get_uint64 ();
172166 } else if (it->second .type () == json_spirit::str_type) {
173167 try {
174- m_snap_id = boost::lexical_cast<uint64_t >(it->second .get_str ());
168+ snap_id = boost::lexical_cast<uint64_t >(it->second .get_str ());
175169 } catch (boost::bad_lexical_cast&) {
176170 }
177171 }
178- if (m_snap_id == CEPH_NOSNAP) {
172+ if (snap_id == CEPH_NOSNAP) {
179173 lderr (cct) << " invalid snap id" << dendl;
180- on_finish->complete (-EINVAL);
181- return ;
174+ return -EINVAL;
182175 }
183176 }
184177
185178 // snapshot is required for import to keep source read-only
186- if (m_import_only && m_snap_name .empty () && m_snap_id == CEPH_NOSNAP) {
179+ if (import_only && snap_name .empty () && snap_id == CEPH_NOSNAP) {
187180 lderr (cct) << " snapshot required for import" << dendl;
188- on_finish->complete (-EINVAL);
189- return ;
190- }
191-
192- // TODO add support for external clusters
193- librados::IoCtx io_ctx;
194- int r = util::create_ioctx (m_image_ctx->md_ctx , " source image" ,
195- pool_id, pool_namespace, &io_ctx);
196- if (r < 0 ) {
197- on_finish->complete (r);
198- return ;
199- }
200-
201- m_image_ctx->md_ctx .dup (io_ctx);
202- m_image_ctx->data_ctx .dup (io_ctx);
203- m_image_ctx->name = image_name;
204-
205- uint64_t flags = 0 ;
206- if (image_id.empty () && !m_import_only) {
207- flags |= OPEN_FLAG_OLD_FORMAT;
208- } else {
209- m_image_ctx->id = image_id;
181+ return -EINVAL;
210182 }
211183
212- if (m_image_ctx->child != nullptr ) {
213- // set rados flags for reading the parent image
214- if (m_image_ctx->child ->config .template get_val <bool >(" rbd_balance_parent_reads" )) {
215- m_image_ctx->set_read_flag (librados::OPERATION_BALANCE_READS);
216- } else if (m_image_ctx->child ->config .template get_val <bool >(" rbd_localize_parent_reads" )) {
217- m_image_ctx->set_read_flag (librados::OPERATION_LOCALIZE_READS);
218- }
184+ // import snapshot is used only for destination image HEAD
185+ // otherwise, src_snap_id corresponds to destination image "opened at"
186+ // snap_id
187+ if (src_snap_id != CEPH_NOSNAP) {
188+ snap_id = src_snap_id;
219189 }
220190
221- // open the source RBD image
222- on_finish = new LambdaContext ([this , on_finish](int r) {
223- handle_open (r, on_finish); });
224- m_image_ctx->state ->open (flags, on_finish);
225- }
226-
227- template <typename I>
228- void NativeFormat<I>::handle_open(int r, Context* on_finish) {
229- auto cct = m_image_ctx->cct ;
230- ldout (cct, 10 ) << " r=" << r << dendl;
231-
191+ // TODO add support for external clusters
192+ librados::IoCtx src_io_ctx;
193+ int r = util::create_ioctx (dst_io_ctx, " source image" , pool_id,
194+ pool_namespace, &src_io_ctx);
232195 if (r < 0 ) {
233- lderr (cct) << " failed to open image: " << cpp_strerror (r) << dendl;
234- on_finish->complete (r);
235- return ;
236- }
237-
238- if (m_snap_id == CEPH_NOSNAP && m_snap_name.empty ()) {
239- on_finish->complete (0 );
240- return ;
241- }
242-
243- if (!m_snap_name.empty ()) {
244- std::shared_lock image_locker{m_image_ctx->image_lock };
245- m_snap_id = m_image_ctx->get_snap_id (cls::rbd::UserSnapshotNamespace{},
246- m_snap_name);
247- }
248-
249- if (m_snap_id == CEPH_NOSNAP) {
250- lderr (cct) << " failed to locate snapshot " << m_snap_name << dendl;
251- on_finish = new LambdaContext ([on_finish](int ) {
252- on_finish->complete (-ENOENT); });
253- m_image_ctx->state ->close (on_finish);
254- return ;
196+ return r;
255197 }
256198
257- on_finish = new LambdaContext ([this , on_finish](int r) {
258- handle_snap_set (r, on_finish); });
259- m_image_ctx->state ->snap_set (m_snap_id, on_finish);
260- }
261-
262- template <typename I>
263- void NativeFormat<I>::handle_snap_set(int r, Context* on_finish) {
264- auto cct = m_image_ctx->cct ;
265- ldout (cct, 10 ) << " r=" << r << dendl;
266-
267- if (r < 0 ) {
268- lderr (cct) << " failed to set snapshot " << m_snap_id << " : "
269- << cpp_strerror (r) << dendl;
270- on_finish = new LambdaContext ([r, on_finish](int ) {
271- on_finish->complete (r); });
272- m_image_ctx->state ->close (on_finish);
273- return ;
199+ if (!snap_name.empty () && snap_id == CEPH_NOSNAP) {
200+ *src_image_ctx = I::create (image_name, image_id, snap_name.c_str (),
201+ src_io_ctx, true );
202+ } else {
203+ *src_image_ctx = I::create (image_name, image_id, snap_id, src_io_ctx,
204+ true );
274205 }
275-
276- on_finish->complete (0 );
277- }
278-
279- template <typename I>
280- void NativeFormat<I>::close(Context* on_finish) {
281- auto cct = m_image_ctx->cct ;
282- ldout (cct, 10 ) << dendl;
283-
284- // the native librbd::image::CloseRequest handles all cleanup
285- on_finish->complete (0 );
286- }
287-
288- template <typename I>
289- void NativeFormat<I>::get_snapshots(SnapInfos* snap_infos, Context* on_finish) {
290- auto cct = m_image_ctx->cct ;
291- ldout (cct, 10 ) << dendl;
292-
293- m_image_ctx->image_lock .lock_shared ();
294- *snap_infos = m_image_ctx->snap_info ;
295- m_image_ctx->image_lock .unlock_shared ();
296-
297- on_finish->complete (0 );
298- }
299-
300- template <typename I>
301- void NativeFormat<I>::get_image_size(uint64_t snap_id, uint64_t * size,
302- Context* on_finish) {
303- auto cct = m_image_ctx->cct ;
304- ldout (cct, 10 ) << dendl;
305-
306- m_image_ctx->image_lock .lock_shared ();
307- *size = m_image_ctx->get_image_size (snap_id);
308- m_image_ctx->image_lock .unlock_shared ();
309-
310-
311- on_finish->complete (0 );
312- }
313-
314- template <typename I>
315- void NativeFormat<I>::list_snaps(io::Extents&& image_extents,
316- io::SnapIds&& snap_ids, int list_snaps_flags,
317- io::SnapshotDelta* snapshot_delta,
318- const ZTracer::Trace &parent_trace,
319- Context* on_finish) {
320- auto cct = m_image_ctx->cct ;
321- ldout (cct, 20 ) << " image_extents=" << image_extents << dendl;
322-
323- auto aio_comp = io::AioCompletion::create_and_start (
324- on_finish, util::get_image_ctx (m_image_ctx), io::AIO_TYPE_GENERIC);
325- auto req = io::ImageDispatchSpec::create_list_snaps (
326- *m_image_ctx, io::IMAGE_DISPATCH_LAYER_MIGRATION, aio_comp,
327- std::move (image_extents), io::ImageArea::DATA, std::move (snap_ids),
328- list_snaps_flags, snapshot_delta, {});
329- req->send ();
206+ return 0 ;
330207}
331208
332209} // namespace migration
0 commit comments