template <typename I>
ImageCopyRequest<I>::ImageCopyRequest(I *src_image_ctx, I *dst_image_ctx,
- librados::snap_t snap_id_start,
- librados::snap_t snap_id_end,
+ librados::snap_t src_snap_id_start,
+ librados::snap_t src_snap_id_end,
bool flatten,
const ObjectNumber &object_number,
const SnapSeqs &snap_seqs,
ProgressContext *prog_ctx,
Context *on_finish)
: RefCountedObject(dst_image_ctx->cct), m_src_image_ctx(src_image_ctx),
- m_dst_image_ctx(dst_image_ctx), m_snap_id_start(snap_id_start),
- m_snap_id_end(snap_id_end), m_flatten(flatten),
+ m_dst_image_ctx(dst_image_ctx), m_src_snap_id_start(src_snap_id_start),
+ m_src_snap_id_end(src_snap_id_end), m_flatten(flatten),
m_object_number(object_number), m_snap_seqs(snap_seqs),
m_prog_ctx(prog_ctx), m_on_finish(on_finish), m_cct(dst_image_ctx->cct),
m_lock(ceph::make_mutex(unique_lock_name("ImageCopyRequest::m_lock", this))) {
template <typename I>
void ImageCopyRequest<I>::send() {
- util::compute_snap_map(m_snap_id_start, m_snap_id_end, m_snap_seqs,
+ m_dst_image_ctx->image_lock.lock_shared();
+ util::compute_snap_map(m_dst_image_ctx->cct, m_src_snap_id_start,
+ m_src_snap_id_end, m_dst_image_ctx->snaps, m_snap_seqs,
&m_snap_map);
+ m_dst_image_ctx->image_lock.unlock_shared();
+
if (m_snap_map.empty()) {
lderr(m_cct) << "failed to map snapshots within boundary" << dendl;
finish(-EINVAL);
public:
static ImageCopyRequest* create(ImageCtxT *src_image_ctx,
ImageCtxT *dst_image_ctx,
- librados::snap_t snap_id_start,
- librados::snap_t snap_id_end, bool flatten,
+ librados::snap_t src_snap_id_start,
+ librados::snap_t src_snap_id_end,
+ bool flatten,
const ObjectNumber &object_number,
const SnapSeqs &snap_seqs,
ProgressContext *prog_ctx,
Context *on_finish) {
- return new ImageCopyRequest(src_image_ctx, dst_image_ctx, snap_id_start,
- snap_id_end, flatten, object_number, snap_seqs,
- prog_ctx, on_finish);
+ return new ImageCopyRequest(src_image_ctx, dst_image_ctx, src_snap_id_start,
+ src_snap_id_end, flatten, object_number,
+ snap_seqs, prog_ctx, on_finish);
}
ImageCopyRequest(ImageCtxT *src_image_ctx, ImageCtxT *dst_image_ctx,
- librados::snap_t snap_id_start, librados::snap_t snap_id_end,
+ librados::snap_t src_snap_id_start,
+ librados::snap_t src_snap_id_end,
bool flatten, const ObjectNumber &object_number,
const SnapSeqs &snap_seqs, ProgressContext *prog_ctx,
Context *on_finish);
ImageCtxT *m_src_image_ctx;
ImageCtxT *m_dst_image_ctx;
- librados::snap_t m_snap_id_start;
- librados::snap_t m_snap_id_end;
+ librados::snap_t m_src_snap_id_start;
+ librados::snap_t m_src_snap_id_end;
bool m_flatten;
ObjectNumber m_object_number;
SnapSeqs m_snap_seqs;
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
+#include "common/debug.h"
#include "Utils.h"
+#include <set>
namespace librbd {
namespace deep_copy {
namespace util {
-void compute_snap_map(librados::snap_t snap_id_start,
- librados::snap_t snap_id_end,
+#define dout_subsys ceph_subsys_rbd
+#undef dout_prefix
+#define dout_prefix *_dout << "librbd::deep_copy::util::" << __func__ << ": "
+
+void compute_snap_map(CephContext* cct,
+ librados::snap_t src_snap_id_start,
+ librados::snap_t src_snap_id_end,
+ const SnapIds& dst_snap_ids,
const SnapSeqs &snap_seqs,
SnapMap *snap_map) {
+ std::set<librados::snap_t> ordered_dst_snap_ids{
+ dst_snap_ids.begin(), dst_snap_ids.end()};
+ auto dst_snap_id_it = ordered_dst_snap_ids.begin();
+
SnapIds snap_ids;
for (auto &it : snap_seqs) {
+ // ensure all dst snap ids are included in the mapping table since
+ // deep copy will skip non-user snapshots
+ while (dst_snap_id_it != ordered_dst_snap_ids.end()) {
+ if (*dst_snap_id_it < it.second) {
+ snap_ids.insert(snap_ids.begin(), *dst_snap_id_it);
+ } else if (*dst_snap_id_it > it.second) {
+ break;
+ }
+ ++dst_snap_id_it;
+ }
+
+ // we should only have the HEAD revision in the the last snap seq
+ ceph_assert(snap_ids.empty() || snap_ids[0] != CEPH_NOSNAP);
snap_ids.insert(snap_ids.begin(), it.second);
- if (it.first < snap_id_start) {
+
+ if (it.first < src_snap_id_start) {
continue;
- } else if (it.first > snap_id_end) {
+ } else if (it.first > src_snap_id_end) {
break;
}
(*snap_map)[it.first] = snap_ids;
}
+
+ ldout(cct, 10) << "src_snap_id_start=" << src_snap_id_start << ", "
+ << "src_snap_id_end=" << src_snap_id_end << ", "
+ << "dst_snap_ids=" << dst_snap_ids << ", "
+ << "snap_seqs=" << snap_seqs << ", "
+ << "snap_map=" << *snap_map << dendl;
}
-} // util
+} // namespace util
} // namespace deep_copy
} // namespace librbd
#include <boost/optional.hpp>
+struct CephContext;
+
namespace librbd {
namespace deep_copy {
namespace util {
-void compute_snap_map(librados::snap_t snap_id_start,
- librados::snap_t snap_id_end,
+void compute_snap_map(CephContext* cct,
+ librados::snap_t src_snap_id_start,
+ librados::snap_t src_snap_id_end,
+ const SnapIds& dst_snap_ids,
const SnapSeqs &snap_seqs,
SnapMap *snap_map);
m_migration_spec.image_name, m_migration_spec.image_id, {},
overlap, m_migration_spec.flatten};
- deep_copy::util::compute_snap_map(0, CEPH_NOSNAP, snap_seqs,
- &migration_info->snap_map);
+ deep_copy::util::compute_snap_map(m_image_ctx.cct, 0, CEPH_NOSNAP, {},
+ snap_seqs, &migration_info->snap_map);
return true;
}