From: Mykola Golub Date: Thu, 26 Apr 2018 08:30:03 +0000 (+0300) Subject: librbd: deep copy optionally support flattening cloned image X-Git-Tag: v14.0.0~113^2~1 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=0d43d2faceca158cc9cf2177802b80dda2b554c9;p=ceph-ci.git librbd: deep copy optionally support flattening cloned image Fixes: http://tracker.ceph.com/issues/22787 Signed-off-by: Mykola Golub --- diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h index 51d83f9066d..ee86d8aad23 100644 --- a/src/include/rbd/librbd.h +++ b/src/include/rbd/librbd.h @@ -206,7 +206,8 @@ enum { RBD_IMAGE_OPTION_JOURNAL_POOL = 7, RBD_IMAGE_OPTION_FEATURES_SET = 8, RBD_IMAGE_OPTION_FEATURES_CLEAR = 9, - RBD_IMAGE_OPTION_DATA_POOL = 10 + RBD_IMAGE_OPTION_DATA_POOL = 10, + RBD_IMAGE_OPTION_FLATTEN = 11, }; typedef enum { diff --git a/src/librbd/DeepCopyRequest.cc b/src/librbd/DeepCopyRequest.cc index b5983e9efde..29f5f60198c 100644 --- a/src/librbd/DeepCopyRequest.cc +++ b/src/librbd/DeepCopyRequest.cc @@ -29,16 +29,17 @@ using librbd::util::unique_lock_name; template DeepCopyRequest::DeepCopyRequest(I *src_image_ctx, I *dst_image_ctx, librados::snap_t snap_id_start, - librados::snap_t snap_id_end, + librados::snap_t snap_id_end, bool flatten, const ObjectNumber &object_number, ContextWQ *work_queue, SnapSeqs *snap_seqs, ProgressContext *prog_ctx, Context *on_finish) : RefCountedObject(dst_image_ctx->cct, 1), 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_object_number(object_number), - m_work_queue(work_queue), m_snap_seqs(snap_seqs), m_prog_ctx(prog_ctx), - m_on_finish(on_finish), m_cct(dst_image_ctx->cct), + m_snap_id_end(snap_id_end), m_flatten(flatten), + m_object_number(object_number), m_work_queue(work_queue), + m_snap_seqs(snap_seqs), m_prog_ctx(prog_ctx), m_on_finish(on_finish), + m_cct(dst_image_ctx->cct), m_lock(unique_lock_name("DeepCopyRequest::m_lock", this)) { } @@ -90,8 +91,8 @@ void DeepCopyRequest::send_copy_snapshots() { Context *ctx = create_context_callback< DeepCopyRequest, &DeepCopyRequest::handle_copy_snapshots>(this); m_snapshot_copy_request = SnapshotCopyRequest::create( - m_src_image_ctx, m_dst_image_ctx, m_snap_id_end, m_work_queue, m_snap_seqs, - ctx); + m_src_image_ctx, m_dst_image_ctx, m_snap_id_end, m_flatten, m_work_queue, + m_snap_seqs, ctx); m_snapshot_copy_request->get(); m_lock.Unlock(); @@ -140,7 +141,7 @@ void DeepCopyRequest::send_copy_image() { DeepCopyRequest, &DeepCopyRequest::handle_copy_image>(this); m_image_copy_request = ImageCopyRequest::create( m_src_image_ctx, m_dst_image_ctx, m_snap_id_start, m_snap_id_end, - m_object_number, *m_snap_seqs, m_prog_ctx, ctx); + m_flatten, m_object_number, *m_snap_seqs, m_prog_ctx, ctx); m_image_copy_request->get(); m_lock.Unlock(); diff --git a/src/librbd/DeepCopyRequest.h b/src/librbd/DeepCopyRequest.h index 553f575f7f8..dba07e6a862 100644 --- a/src/librbd/DeepCopyRequest.h +++ b/src/librbd/DeepCopyRequest.h @@ -33,20 +33,20 @@ public: static DeepCopyRequest* create(ImageCtxT *src_image_ctx, ImageCtxT *dst_image_ctx, librados::snap_t snap_id_start, - librados::snap_t snap_id_end, + librados::snap_t snap_id_end, bool flatten, const deep_copy::ObjectNumber &object_number, ContextWQ *work_queue, SnapSeqs *snap_seqs, ProgressContext *prog_ctx, Context *on_finish) { return new DeepCopyRequest(src_image_ctx, dst_image_ctx, snap_id_start, - snap_id_end, object_number, work_queue, + snap_id_end, flatten, object_number, work_queue, snap_seqs, prog_ctx, on_finish); } DeepCopyRequest(ImageCtxT *src_image_ctx, ImageCtxT *dst_image_ctx, librados::snap_t snap_id_start, librados::snap_t snap_id_end, - const deep_copy::ObjectNumber &object_number, + bool flatten, const deep_copy::ObjectNumber &object_number, ContextWQ *work_queue, SnapSeqs *snap_seqs, ProgressContext *prog_ctx, Context *on_finish); ~DeepCopyRequest(); @@ -88,6 +88,7 @@ private: ImageCtxT *m_dst_image_ctx; librados::snap_t m_snap_id_start; librados::snap_t m_snap_id_end; + bool m_flatten; deep_copy::ObjectNumber m_object_number; ContextWQ *m_work_queue; SnapSeqs *m_snap_seqs; diff --git a/src/librbd/api/Image.cc b/src/librbd/api/Image.cc index 0d3c8a46ff4..5c61746deeb 100644 --- a/src/librbd/api/Image.cc +++ b/src/librbd/api/Image.cc @@ -205,8 +205,15 @@ int Image::deep_copy(I *src, librados::IoCtx& dest_md_ctx, return -ENOSYS; } + uint64_t flatten = 0; + if (opts.get(RBD_IMAGE_OPTION_FLATTEN, &flatten) == 0) { + opts.unset(RBD_IMAGE_OPTION_FLATTEN); + } + ParentSpec parent_spec; - { + if (flatten > 0) { + parent_spec.pool_id = -1; + } else { RWLock::RLocker snap_locker(src->snap_lock); RWLock::RLocker parent_locker(src->parent_lock); @@ -297,7 +304,7 @@ int Image::deep_copy(I *src, librados::IoCtx& dest_md_ctx, return r; } - r = deep_copy(src, dest, prog_ctx); + r = deep_copy(src, dest, flatten > 0, prog_ctx); int close_r = dest->state->close(); if (r == 0 && close_r < 0) { @@ -307,7 +314,8 @@ int Image::deep_copy(I *src, librados::IoCtx& dest_md_ctx, } template -int Image::deep_copy(I *src, I *dest, ProgressContext &prog_ctx) { +int Image::deep_copy(I *src, I *dest, bool flatten, + ProgressContext &prog_ctx) { CephContext *cct = src->cct; librados::snap_t snap_id_start = 0; librados::snap_t snap_id_end; @@ -323,8 +331,8 @@ int Image::deep_copy(I *src, I *dest, ProgressContext &prog_ctx) { C_SaferCond cond; SnapSeqs snap_seqs; auto req = DeepCopyRequest<>::create(src, dest, snap_id_start, snap_id_end, - boost::none, op_work_queue, &snap_seqs, - &prog_ctx, &cond); + flatten, boost::none, op_work_queue, + &snap_seqs, &prog_ctx, &cond); req->send(); int r = cond.wait(); if (r < 0) { diff --git a/src/librbd/api/Image.h b/src/librbd/api/Image.h index cefab1aaea5..062d98c23c8 100644 --- a/src/librbd/api/Image.h +++ b/src/librbd/api/Image.h @@ -38,7 +38,7 @@ struct Image { static int deep_copy(ImageCtxT *ictx, librados::IoCtx& dest_md_ctx, const char *destname, ImageOptions& opts, ProgressContext &prog_ctx); - static int deep_copy(ImageCtxT *src, ImageCtxT *dest, + static int deep_copy(ImageCtxT *src, ImageCtxT *dest, bool flatten, ProgressContext &prog_ctx); static int snap_set(ImageCtxT *ictx, diff --git a/src/librbd/deep_copy/ImageCopyRequest.cc b/src/librbd/deep_copy/ImageCopyRequest.cc index d101aa8d17d..e3f742413fc 100644 --- a/src/librbd/deep_copy/ImageCopyRequest.cc +++ b/src/librbd/deep_copy/ImageCopyRequest.cc @@ -26,15 +26,16 @@ template ImageCopyRequest::ImageCopyRequest(I *src_image_ctx, I *dst_image_ctx, librados::snap_t snap_id_start, librados::snap_t snap_id_end, + bool flatten, const ObjectNumber &object_number, const SnapSeqs &snap_seqs, ProgressContext *prog_ctx, Context *on_finish) : RefCountedObject(dst_image_ctx->cct, 1), 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_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_snap_id_end(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(unique_lock_name("ImageCopyRequest::m_lock", this)) { } @@ -207,7 +208,7 @@ void ImageCopyRequest::send_next_object_copy() { }); ObjectCopyRequest *req = ObjectCopyRequest::create( m_src_image_ctx, m_src_parent_image_ctx, m_dst_image_ctx, m_snap_map, ono, - ctx); + m_flatten, ctx); req->send(); } diff --git a/src/librbd/deep_copy/ImageCopyRequest.h b/src/librbd/deep_copy/ImageCopyRequest.h index 8c395a34c9f..c8fc08169f3 100644 --- a/src/librbd/deep_copy/ImageCopyRequest.h +++ b/src/librbd/deep_copy/ImageCopyRequest.h @@ -31,20 +31,21 @@ public: static ImageCopyRequest* create(ImageCtxT *src_image_ctx, ImageCtxT *dst_image_ctx, librados::snap_t snap_id_start, - librados::snap_t snap_id_end, + librados::snap_t 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, object_number, snap_seqs, prog_ctx, - on_finish); + 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, - const ObjectNumber &object_number, const SnapSeqs &snap_seqs, - ProgressContext *prog_ctx, Context *on_finish); + bool flatten, const ObjectNumber &object_number, + const SnapSeqs &snap_seqs, ProgressContext *prog_ctx, + Context *on_finish); void send(); void cancel(); @@ -79,6 +80,7 @@ private: ImageCtxT *m_dst_image_ctx; librados::snap_t m_snap_id_start; librados::snap_t m_snap_id_end; + bool m_flatten; ObjectNumber m_object_number; SnapSeqs m_snap_seqs; ProgressContext *m_prog_ctx; diff --git a/src/librbd/deep_copy/ObjectCopyRequest.cc b/src/librbd/deep_copy/ObjectCopyRequest.cc index 98aa24b8f47..7fb911d23df 100644 --- a/src/librbd/deep_copy/ObjectCopyRequest.cc +++ b/src/librbd/deep_copy/ObjectCopyRequest.cc @@ -45,12 +45,12 @@ ObjectCopyRequest::ObjectCopyRequest(I *src_image_ctx, I *dst_image_ctx, const SnapMap &snap_map, uint64_t dst_object_number, - Context *on_finish) + bool flatten, Context *on_finish) : m_src_image_ctx(src_image_ctx), m_src_parent_image_ctx(src_parent_image_ctx), m_dst_image_ctx(dst_image_ctx), m_cct(dst_image_ctx->cct), m_snap_map(snap_map), m_dst_object_number(dst_object_number), - m_on_finish(on_finish) { + m_flatten(flatten), m_on_finish(on_finish) { assert(!m_snap_map.empty()); m_src_io_ctx.dup(m_src_image_ctx->data_ctx); @@ -704,7 +704,7 @@ void ObjectCopyRequest::compute_read_from_parent_ops( return; } - if (noent_count == m_src_object_extents.size()) { + if (noent_count == m_src_object_extents.size() && !m_flatten) { ldout(m_cct, 20) << "reading all extents skipped when no flatten" << dendl; return; diff --git a/src/librbd/deep_copy/ObjectCopyRequest.h b/src/librbd/deep_copy/ObjectCopyRequest.h index e10daea86c7..0d6598b08c5 100644 --- a/src/librbd/deep_copy/ObjectCopyRequest.h +++ b/src/librbd/deep_copy/ObjectCopyRequest.h @@ -28,16 +28,16 @@ public: ImageCtxT *src_parent_image_ctx, ImageCtxT *dst_image_ctx, const SnapMap &snap_map, - uint64_t object_number, + uint64_t object_number, bool flatten, Context *on_finish) { return new ObjectCopyRequest(src_image_ctx, src_parent_image_ctx, dst_image_ctx, snap_map, object_number, - on_finish); + flatten, on_finish); } ObjectCopyRequest(ImageCtxT *src_image_ctx, ImageCtxT *src_parent_image_ctx, ImageCtxT *dst_image_ctx, const SnapMap &snap_map, - uint64_t object_number, Context *on_finish); + uint64_t object_number, bool flatten, Context *on_finish); void send(); @@ -138,6 +138,7 @@ private: CephContext *m_cct; const SnapMap &m_snap_map; uint64_t m_dst_object_number; + bool m_flatten; Context *m_on_finish; decltype(m_src_image_ctx->data_ctx) m_src_io_ctx; diff --git a/src/librbd/deep_copy/SnapshotCopyRequest.cc b/src/librbd/deep_copy/SnapshotCopyRequest.cc index 72c764132ed..49c3a1b6bd8 100644 --- a/src/librbd/deep_copy/SnapshotCopyRequest.cc +++ b/src/librbd/deep_copy/SnapshotCopyRequest.cc @@ -44,12 +44,12 @@ template SnapshotCopyRequest::SnapshotCopyRequest(I *src_image_ctx, I *dst_image_ctx, librados::snap_t snap_id_end, - ContextWQ *work_queue, + bool flatten, ContextWQ *work_queue, SnapSeqs *snap_seqs, Context *on_finish) : RefCountedObject(dst_image_ctx->cct, 1), m_src_image_ctx(src_image_ctx), m_dst_image_ctx(dst_image_ctx), m_snap_id_end(snap_id_end), - m_work_queue(work_queue), m_snap_seqs_result(snap_seqs), + m_flatten(flatten), m_work_queue(work_queue), m_snap_seqs_result(snap_seqs), m_snap_seqs(*snap_seqs), m_on_finish(on_finish), m_cct(dst_image_ctx->cct), m_lock(unique_lock_name("SnapshotCopyRequest::m_lock", this)) { // snap ids ordered from oldest to newest @@ -353,7 +353,7 @@ void SnapshotCopyRequest::send_snap_create() { m_snap_namespace = snap_info_it->second.snap_namespace; librbd::ParentSpec parent_spec; uint64_t parent_overlap = 0; - if (snap_info_it->second.parent.spec.pool_id != -1) { + if (!m_flatten && snap_info_it->second.parent.spec.pool_id != -1) { parent_spec = m_dst_parent_spec; parent_overlap = snap_info_it->second.parent.overlap; } @@ -519,12 +519,14 @@ void SnapshotCopyRequest::send_set_head() { uint64_t size; ParentSpec parent_spec; - uint64_t parent_overlap; + uint64_t parent_overlap = 0; { RWLock::RLocker src_locker(m_src_image_ctx->snap_lock); size = m_src_image_ctx->size; - parent_spec = m_src_image_ctx->parent_md.spec; - parent_overlap = m_src_image_ctx->parent_md.overlap; + if (!m_flatten) { + parent_spec = m_src_image_ctx->parent_md.spec; + parent_overlap = m_src_image_ctx->parent_md.overlap; + } } auto ctx = create_context_callback< diff --git a/src/librbd/deep_copy/SnapshotCopyRequest.h b/src/librbd/deep_copy/SnapshotCopyRequest.h index 47ab83e4982..f5769a65be7 100644 --- a/src/librbd/deep_copy/SnapshotCopyRequest.h +++ b/src/librbd/deep_copy/SnapshotCopyRequest.h @@ -25,17 +25,17 @@ class SnapshotCopyRequest : public RefCountedObject { public: static SnapshotCopyRequest* create(ImageCtxT *src_image_ctx, ImageCtxT *dst_image_ctx, - librados::snap_t snap_id_end, - ContextWQ *work_queue, - SnapSeqs *snap_seqs, + librados::snap_t snap_id_end, bool flatten, + ContextWQ *work_queue, SnapSeqs *snap_seqs, Context *on_finish) { return new SnapshotCopyRequest(src_image_ctx, dst_image_ctx, snap_id_end, - work_queue, snap_seqs, on_finish); + flatten, work_queue, snap_seqs, on_finish); } SnapshotCopyRequest(ImageCtxT *src_image_ctx, ImageCtxT *dst_image_ctx, - librados::snap_t snap_id_end, ContextWQ *work_queue, - SnapSeqs *snap_seqs, Context *on_finish); + librados::snap_t snap_id_end, bool flatten, + ContextWQ *work_queue, SnapSeqs *snap_seqs, + Context *on_finish); void send(); void cancel(); @@ -80,6 +80,7 @@ private: ImageCtxT *m_src_image_ctx; ImageCtxT *m_dst_image_ctx; librados::snap_t m_snap_id_end; + bool m_flatten; ContextWQ *m_work_queue; SnapSeqs *m_snap_seqs_result; SnapSeqs m_snap_seqs; diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 7a9f7267b46..2ef36f58223 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -311,6 +311,7 @@ bool compare_by_name(const child_info_t& c1, const child_info_t& c2) {RBD_IMAGE_OPTION_FEATURES_SET, UINT64}, {RBD_IMAGE_OPTION_FEATURES_CLEAR, UINT64}, {RBD_IMAGE_OPTION_DATA_POOL, STR}, + {RBD_IMAGE_OPTION_FLATTEN, UINT64}, }; std::string image_option_name(int optname) { @@ -337,6 +338,8 @@ bool compare_by_name(const child_info_t& c1, const child_info_t& c2) return "features_clear"; case RBD_IMAGE_OPTION_DATA_POOL: return "data_pool"; + case RBD_IMAGE_OPTION_FLATTEN: + return "flatten"; default: return "unknown (" + stringify(optname) + ")"; } @@ -842,6 +845,12 @@ bool compare_by_name(const child_info_t& c1, const child_info_t& c2) } CephContext *cct = (CephContext *)io_ctx.cct(); + uint64_t flatten; + if (opts.get(RBD_IMAGE_OPTION_FLATTEN, &flatten) == 0) { + lderr(cct) << "create does not support 'flatten' image option" << dendl; + return -EINVAL; + } + ldout(cct, 10) << __func__ << " name=" << image_name << ", " << "id= " << id << ", " << "size=" << size << ", opts=" << opts << dendl; @@ -930,6 +939,12 @@ bool compare_by_name(const child_info_t& c1, const child_info_t& c2) return -EINVAL; } + uint64_t flatten; + if (c_opts.get(RBD_IMAGE_OPTION_FLATTEN, &flatten) == 0) { + lderr(cct) << "clone does not support 'flatten' image option" << dendl; + return -EINVAL; + } + // make sure parent snapshot exists ImageCtx *p_imctx = new ImageCtx(p_name, "", p_snap_name, p_ioctx, true); int r = p_imctx->state->open(false); @@ -1728,6 +1743,12 @@ bool compare_by_name(const child_info_t& c1, const child_info_t& c2) ImageOptions& opts, ProgressContext &prog_ctx, size_t sparse_size) { CephContext *cct = (CephContext *)dest_md_ctx.cct(); + uint64_t flatten; + if (opts.get(RBD_IMAGE_OPTION_FLATTEN, &flatten) == 0) { + lderr(cct) << "copy does not support 'flatten' image option" << dendl; + return -EINVAL; + } + ldout(cct, 20) << "copy " << src->name << (src->snap_name.length() ? "@" + src->snap_name : "") << " -> " << destname << " opts = " << opts << dendl; diff --git a/src/test/librbd/deep_copy/test_mock_ImageCopyRequest.cc b/src/test/librbd/deep_copy/test_mock_ImageCopyRequest.cc index bd4f897249c..602a12f0475 100644 --- a/src/test/librbd/deep_copy/test_mock_ImageCopyRequest.cc +++ b/src/test/librbd/deep_copy/test_mock_ImageCopyRequest.cc @@ -52,7 +52,7 @@ struct ObjectCopyRequest { librbd::MockTestImageCtx *src_image_ctx, librbd::MockTestImageCtx *src_parent_image_ctx, librbd::MockTestImageCtx *dst_image_ctx, const SnapMap &snap_map, - uint64_t object_number, Context *on_finish) { + uint64_t object_number, bool flatten, Context *on_finish) { assert(s_instance != nullptr); Mutex::Locker locker(s_instance->lock); s_instance->snap_map = &snap_map; @@ -298,7 +298,7 @@ TEST_F(TestMockDeepCopyImageCopyRequest, SimpleImage) { C_SaferCond ctx; auto request = new MockImageCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - 0, snap_id_end, boost::none, + 0, snap_id_end, false, boost::none, m_snap_seqs, &no_op, &ctx); request->send(); @@ -358,7 +358,7 @@ TEST_F(TestMockDeepCopyImageCopyRequest, OutOfOrder) { C_SaferCond ctx; auto request = new MockImageCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - 0, snap_id_end, boost::none, + 0, snap_id_end, false, boost::none, m_snap_seqs, &prog_ctx, &ctx); request->send(); @@ -404,7 +404,7 @@ TEST_F(TestMockDeepCopyImageCopyRequest, SnapshotSubset) { C_SaferCond ctx; auto request = new MockImageCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - snap_id_start, snap_id_end, + snap_id_start, snap_id_end, false, boost::none, m_snap_seqs, &no_op, &ctx); request->send(); @@ -435,7 +435,7 @@ TEST_F(TestMockDeepCopyImageCopyRequest, RestartPartialSync) { C_SaferCond ctx; auto request = new MockImageCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - 0, snap_id_end, + 0, snap_id_end, false, librbd::deep_copy::ObjectNumber{0U}, m_snap_seqs, &no_op, &ctx); request->send(); @@ -470,7 +470,7 @@ TEST_F(TestMockDeepCopyImageCopyRequest, Cancel) { C_SaferCond ctx; auto request = new MockImageCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - 0, snap_id_end, boost::none, + 0, snap_id_end, false, boost::none, m_snap_seqs, &no_op, &ctx); request->send(); @@ -516,7 +516,7 @@ TEST_F(TestMockDeepCopyImageCopyRequest, Cancel_Inflight_Sync) { C_SaferCond ctx; auto request = new MockImageCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - 0, snap_id_end, boost::none, + 0, snap_id_end, false, boost::none, m_snap_seqs, &prog_ctx, &ctx); request->send(); @@ -546,7 +546,7 @@ TEST_F(TestMockDeepCopyImageCopyRequest, MissingSnap) { C_SaferCond ctx; auto request = new MockImageCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - 0, 123, boost::none, + 0, 123, false, boost::none, m_snap_seqs, &no_op, &ctx); request->send(); ASSERT_EQ(-EINVAL, ctx.wait()); @@ -563,7 +563,7 @@ TEST_F(TestMockDeepCopyImageCopyRequest, MissingFromSnap) { C_SaferCond ctx; auto request = new MockImageCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - 123, snap_id_end, boost::none, + 123, snap_id_end, false, boost::none, m_snap_seqs, &no_op, &ctx); request->send(); ASSERT_EQ(-EINVAL, ctx.wait()); @@ -582,7 +582,7 @@ TEST_F(TestMockDeepCopyImageCopyRequest, EmptySnapMap) { C_SaferCond ctx; auto request = new MockImageCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - snap_id_start, snap_id_end, + snap_id_start, snap_id_end, false, boost::none, {{0, 0}}, &no_op, &ctx); request->send(); ASSERT_EQ(-EINVAL, ctx.wait()); @@ -601,7 +601,7 @@ TEST_F(TestMockDeepCopyImageCopyRequest, EmptySnapSeqs) { C_SaferCond ctx; auto request = new MockImageCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - snap_id_start, snap_id_end, + snap_id_start, snap_id_end, false, boost::none, {}, &no_op, &ctx); request->send(); ASSERT_EQ(-EINVAL, ctx.wait()); diff --git a/src/test/librbd/deep_copy/test_mock_ObjectCopyRequest.cc b/src/test/librbd/deep_copy/test_mock_ObjectCopyRequest.cc index b3eb055c35b..cfefb694ec9 100644 --- a/src/test/librbd/deep_copy/test_mock_ObjectCopyRequest.cc +++ b/src/test/librbd/deep_copy/test_mock_ObjectCopyRequest.cc @@ -199,7 +199,7 @@ public: librbd::MockTestImageCtx &mock_dst_image_ctx, Context *on_finish) { expect_get_object_name(mock_dst_image_ctx); return new MockObjectCopyRequest(&mock_src_image_ctx, nullptr, - &mock_dst_image_ctx, m_snap_map, 0, + &mock_dst_image_ctx, m_snap_map, 0, false, on_finish); } diff --git a/src/test/librbd/deep_copy/test_mock_SnapshotCopyRequest.cc b/src/test/librbd/deep_copy/test_mock_SnapshotCopyRequest.cc index 8dcaf266d6f..600074c248a 100644 --- a/src/test/librbd/deep_copy/test_mock_SnapshotCopyRequest.cc +++ b/src/test/librbd/deep_copy/test_mock_SnapshotCopyRequest.cc @@ -223,8 +223,8 @@ public: librbd::MockTestImageCtx &mock_dst_image_ctx, Context *on_finish, librados::snap_t snap_id_end = CEPH_NOSNAP) { return new MockSnapshotCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - snap_id_end, m_work_queue, &m_snap_seqs, - on_finish); + snap_id_end, false, m_work_queue, + &m_snap_seqs, on_finish); } int create_snap(librbd::ImageCtx *image_ctx, const std::string &snap_name, diff --git a/src/test/librbd/test_DeepCopy.cc b/src/test/librbd/test_DeepCopy.cc index 451f2221279..fcd1a2876a4 100644 --- a/src/test/librbd/test_DeepCopy.cc +++ b/src/test/librbd/test_DeepCopy.cc @@ -406,6 +406,16 @@ TEST_F(TestDeepCopy, Clone) test_clone(); } +TEST_F(TestDeepCopy, CloneFlatten) +{ + REQUIRE_FEATURE(RBD_FEATURE_LAYERING); + + uint64_t flatten = 1; + ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_FLATTEN, flatten)); + + test_clone(); +} + TEST_F(TestDeepCopy, Stress) { test_stress(); @@ -437,6 +447,18 @@ TEST_F(TestDeepCopy, Clone_LargerDstObjSize) test_clone(); } +TEST_F(TestDeepCopy, CloneFlatten_LargerDstObjSize) +{ + REQUIRE_FEATURE(RBD_FEATURE_LAYERING); + + uint64_t order = m_src_ictx->order + 1 + rand() % 2; + ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_ORDER, order)); + uint64_t flatten = 1; + ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_FLATTEN, flatten)); + + test_clone(); +} + TEST_F(TestDeepCopy, Stress_LargerDstObjSize) { uint64_t order = m_src_ictx->order + 1 + rand() % 2; @@ -477,6 +499,20 @@ TEST_F(TestDeepCopy, Clone_SmallerDstObjSize) test_clone(); } +TEST_F(TestDeepCopy, CloneFlatten_SmallerDstObjSize) +{ + REQUIRE_FEATURE(RBD_FEATURE_LAYERING); + + uint64_t order = m_src_ictx->order - 1 - rand() % 2; + ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_ORDER, order)); + uint64_t stripe_unit = m_src_ictx->stripe_unit >> 2; + ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_STRIPE_UNIT, stripe_unit)); + uint64_t flatten = 1; + ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_FLATTEN, flatten)); + + test_clone(); +} + TEST_F(TestDeepCopy, Stress_SmallerDstObjSize) { uint64_t order = m_src_ictx->order - 1 - rand() % 2; @@ -529,6 +565,22 @@ TEST_F(TestDeepCopy, Clone_StrippingLargerDstObjSize) test_clone(); } +TEST_F(TestDeepCopy, CloneFlatten_StrippingLargerDstObjSize) +{ + REQUIRE_FEATURE(RBD_FEATURE_LAYERING | RBD_FEATURE_STRIPINGV2); + + uint64_t order = m_src_ictx->order + 1; + uint64_t stripe_unit = 1 << (order - 2); + uint64_t stripe_count = 4; + ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_ORDER, order)); + ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_STRIPE_UNIT, stripe_unit)); + ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_STRIPE_COUNT, stripe_count)); + uint64_t flatten = 1; + ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_FLATTEN, flatten)); + + test_clone(); +} + TEST_F(TestDeepCopy, Stress_StrippingLargerDstObjSize) { REQUIRE_FEATURE(RBD_FEATURE_STRIPINGV2); @@ -585,6 +637,22 @@ TEST_F(TestDeepCopy, Clone_StrippingSmallerDstObjSize) test_clone(); } +TEST_F(TestDeepCopy, CloneFlatten_StrippingSmallerDstObjSize) +{ + REQUIRE_FEATURE(RBD_FEATURE_LAYERING | RBD_FEATURE_STRIPINGV2); + + uint64_t order = m_src_ictx->order - 1 - rand() % 2; + uint64_t stripe_unit = 1 << (order - rand() % 4); + uint64_t stripe_count = 2 + rand() % 14; + ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_ORDER, order)); + ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_STRIPE_UNIT, stripe_unit)); + ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_STRIPE_COUNT, stripe_count)); + uint64_t flatten = 1; + ASSERT_EQ(0, m_opts.set(RBD_IMAGE_OPTION_FLATTEN, flatten)); + + test_clone(); +} + TEST_F(TestDeepCopy, Stress_StrippingSmallerDstObjSize) { REQUIRE_FEATURE(RBD_FEATURE_STRIPINGV2); diff --git a/src/test/librbd/test_mock_DeepCopyRequest.cc b/src/test/librbd/test_mock_DeepCopyRequest.cc index 64ea61d9245..682d0f61c15 100644 --- a/src/test/librbd/test_mock_DeepCopyRequest.cc +++ b/src/test/librbd/test_mock_DeepCopyRequest.cc @@ -41,8 +41,9 @@ public: static ImageCopyRequest* create( librbd::MockTestImageCtx *src_image_ctx, librbd::MockTestImageCtx *dst_image_ctx, librados::snap_t snap_id_start, - librados::snap_t snap_id_end, const ObjectNumber &object_number, - const SnapSeqs &snap_seqs, ProgressContext *prog_ctx, + librados::snap_t snap_id_end, bool flatten, + const ObjectNumber &object_number, const SnapSeqs &snap_seqs, + ProgressContext *prog_ctx, Context *on_finish) { assert(s_instance != nullptr); s_instance->on_finish = on_finish; @@ -92,7 +93,7 @@ public: static SnapshotCopyRequest* create(librbd::MockTestImageCtx *src_image_ctx, librbd::MockTestImageCtx *dst_image_ctx, - librados::snap_t snap_id_end, + librados::snap_t snap_id_end, bool flatten, ContextWQ *work_queue, SnapSeqs *snap_seqs, Context *on_finish) { assert(s_instance != nullptr); @@ -260,8 +261,8 @@ TEST_F(TestMockDeepCopyRequest, SimpleCopy) { librbd::SnapSeqs snap_seqs; librbd::NoOpProgressContext no_op; auto request = librbd::DeepCopyRequest::create( - &mock_src_image_ctx, &mock_dst_image_ctx, 0, CEPH_NOSNAP, boost::none, - m_work_queue, &snap_seqs, &no_op, &ctx); + &mock_src_image_ctx, &mock_dst_image_ctx, 0, CEPH_NOSNAP, false, + boost::none, m_work_queue, &snap_seqs, &no_op, &ctx); request->send(); ASSERT_EQ(0, ctx.wait()); } @@ -278,8 +279,8 @@ TEST_F(TestMockDeepCopyRequest, ErrorOnCopySnapshots) { librbd::SnapSeqs snap_seqs; librbd::NoOpProgressContext no_op; auto request = librbd::DeepCopyRequest::create( - &mock_src_image_ctx, &mock_dst_image_ctx, 0, CEPH_NOSNAP, boost::none, - m_work_queue, &snap_seqs, &no_op, &ctx); + &mock_src_image_ctx, &mock_dst_image_ctx, 0, CEPH_NOSNAP, false, + boost::none, m_work_queue, &snap_seqs, &no_op, &ctx); request->send(); ASSERT_EQ(-EINVAL, ctx.wait()); } @@ -298,8 +299,8 @@ TEST_F(TestMockDeepCopyRequest, ErrorOnCopyImage) { librbd::SnapSeqs snap_seqs; librbd::NoOpProgressContext no_op; auto request = librbd::DeepCopyRequest::create( - &mock_src_image_ctx, &mock_dst_image_ctx, 0, CEPH_NOSNAP, boost::none, - m_work_queue, &snap_seqs, &no_op, &ctx); + &mock_src_image_ctx, &mock_dst_image_ctx, 0, CEPH_NOSNAP, false, + boost::none, m_work_queue, &snap_seqs, &no_op, &ctx); request->send(); ASSERT_EQ(-EINVAL, ctx.wait()); } @@ -333,8 +334,8 @@ TEST_F(TestMockDeepCopyRequest, ErrorOnCopyMetadata) { librbd::SnapSeqs snap_seqs; librbd::NoOpProgressContext no_op; auto request = librbd::DeepCopyRequest::create( - &mock_src_image_ctx, &mock_dst_image_ctx, 0, CEPH_NOSNAP, boost::none, - m_work_queue, &snap_seqs, &no_op, &ctx); + &mock_src_image_ctx, &mock_dst_image_ctx, 0, CEPH_NOSNAP, false, + boost::none, m_work_queue, &snap_seqs, &no_op, &ctx); request->send(); ASSERT_EQ(-EINVAL, ctx.wait()); } @@ -375,7 +376,7 @@ TEST_F(TestMockDeepCopyRequest, Snap) { librbd::NoOpProgressContext no_op; auto request = librbd::DeepCopyRequest::create( &mock_src_image_ctx, &mock_dst_image_ctx, 0, m_src_image_ctx->snap_id, - boost::none, m_work_queue, &snap_seqs, &no_op, &ctx); + false, boost::none, m_work_queue, &snap_seqs, &no_op, &ctx); request->send(); ASSERT_EQ(0, ctx.wait()); } diff --git a/src/test/rbd_mirror/test_mock_ImageSync.cc b/src/test/rbd_mirror/test_mock_ImageSync.cc index c858f412315..12c646c4e39 100644 --- a/src/test/rbd_mirror/test_mock_ImageSync.cc +++ b/src/test/rbd_mirror/test_mock_ImageSync.cc @@ -45,7 +45,7 @@ public: librbd::MockTestImageCtx *src_image_ctx, librbd::MockTestImageCtx *dst_image_ctx, librados::snap_t snap_id_start, librados::snap_t snap_id_end, - const librbd::deep_copy::ObjectNumber &object_number, + bool flatten, const librbd::deep_copy::ObjectNumber &object_number, ContextWQ *work_queue, SnapSeqs *snap_seqs, ProgressContext *prog_ctx, Context *on_finish) { assert(s_instance != nullptr); diff --git a/src/tools/rbd_mirror/ImageSync.cc b/src/tools/rbd_mirror/ImageSync.cc index f7ececbafc4..68588c2ac8f 100644 --- a/src/tools/rbd_mirror/ImageSync.cc +++ b/src/tools/rbd_mirror/ImageSync.cc @@ -245,7 +245,7 @@ void ImageSync::send_copy_image() { m_image_copy_prog_ctx = new ImageCopyProgressContext(this); m_image_copy_request = librbd::DeepCopyRequest::create( m_remote_image_ctx, m_local_image_ctx, snap_id_start, snap_id_end, - object_number, m_work_queue, &m_client_meta->snap_seqs, + false, object_number, m_work_queue, &m_client_meta->snap_seqs, m_image_copy_prog_ctx, ctx); m_image_copy_request->get(); m_lock.Unlock();