diff options
author | Jason Dillaman <dillaman@redhat.com> | 2018-04-17 22:22:06 +0200 |
---|---|---|
committer | Jason Dillaman <dillaman@redhat.com> | 2018-08-15 00:29:45 +0200 |
commit | b498aa0380b9f6f6401fe360b44b7b55f14aa771 (patch) | |
tree | 82ce6052c665485ebeeaf9e3f1f35a97bc983819 /src | |
parent | librbd: normalize clone state machine method names and debug logs (diff) | |
download | ceph-b498aa0380b9f6f6401fe360b44b7b55f14aa771.tar.xz ceph-b498aa0380b9f6f6401fe360b44b7b55f14aa771.zip |
librbd: move shared common clone parent logic to state machine
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/librbd/api/Image.cc | 29 | ||||
-rw-r--r-- | src/librbd/image/CloneRequest.cc | 221 | ||||
-rw-r--r-- | src/librbd/image/CloneRequest.h | 56 | ||||
-rw-r--r-- | src/librbd/internal.cc | 76 | ||||
-rw-r--r-- | src/librbd/internal.h | 7 | ||||
-rw-r--r-- | src/librbd/librbd.cc | 7 | ||||
-rw-r--r-- | src/test/librbd/image/test_mock_CloneRequest.cc | 207 | ||||
-rw-r--r-- | src/test/rbd_mirror/image_replayer/test_mock_CreateImageRequest.cc | 177 | ||||
-rw-r--r-- | src/test/rbd_mirror/test_ImageDeleter.cc | 7 | ||||
-rw-r--r-- | src/tools/rbd_mirror/image_replayer/CreateImageRequest.cc | 113 | ||||
-rw-r--r-- | src/tools/rbd_mirror/image_replayer/CreateImageRequest.h | 27 |
11 files changed, 472 insertions, 455 deletions
diff --git a/src/librbd/api/Image.cc b/src/librbd/api/Image.cc index a295b59d901..877027cdef0 100644 --- a/src/librbd/api/Image.cc +++ b/src/librbd/api/Image.cc @@ -248,38 +248,13 @@ int Image<I>::deep_copy(I *src, librados::IoCtx& dest_md_ctx, // TODO support clone v2 parent namespaces parent_io_ctx.set_namespace(dest_md_ctx.get_namespace()); - ImageCtx *src_parent_image_ctx = - new ImageCtx("", parent_spec.image_id, nullptr, parent_io_ctx, false); - r = src_parent_image_ctx->state->open(true); - if (r < 0) { - if (r != -ENOENT) { - lderr(cct) << "failed to open source parent image: " - << cpp_strerror(r) << dendl; - } - return r; - } - - C_SaferCond cond; - src_parent_image_ctx->state->snap_set(parent_spec.snap_id, &cond); - r = cond.wait(); - if (r < 0) { - if (r != -ENOENT) { - lderr(cct) << "failed to set snapshot: " << cpp_strerror(r) << dendl; - } - return r; - } - C_SaferCond ctx; std::string dest_id = util::generate_image_id(dest_md_ctx); auto *req = image::CloneRequest<I>::create( - src_parent_image_ctx, dest_md_ctx, destname, dest_id, opts, - "", "", src->op_work_queue, &ctx); + parent_io_ctx, parent_spec.image_id, "", parent_spec.snap_id, dest_md_ctx, + destname, dest_id, opts, "", "", src->op_work_queue, &ctx); req->send(); r = ctx.wait(); - int close_r = src_parent_image_ctx->state->close(); - if (r == 0 && close_r < 0) { - r = close_r; - } } if (r < 0) { lderr(cct) << "header creation failed" << dendl; diff --git a/src/librbd/image/CloneRequest.cc b/src/librbd/image/CloneRequest.cc index 71b4951a091..18dbbcd42e4 100644 --- a/src/librbd/image/CloneRequest.cc +++ b/src/librbd/image/CloneRequest.cc @@ -28,16 +28,20 @@ using util::create_context_callback; using util::create_async_context_callback; template <typename I> -CloneRequest<I>::CloneRequest(I *p_imctx, IoCtx &c_ioctx, +CloneRequest<I>::CloneRequest(IoCtx& parent_io_ctx, + const std::string& parent_image_id, + const std::string& parent_snap_name, + uint64_t parent_snap_id, + IoCtx &c_ioctx, const std::string &c_name, const std::string &c_id, ImageOptions c_options, const std::string &non_primary_global_image_id, const std::string &primary_mirror_uuid, ContextWQ *op_work_queue, Context *on_finish) - : m_p_imctx(p_imctx), m_ioctx(c_ioctx), m_name(c_name), m_id(c_id), - m_opts(c_options), - m_pspec(m_p_imctx->md_ctx.get_id(), m_p_imctx->id, m_p_imctx->snap_id), + : m_parent_io_ctx(parent_io_ctx), m_parent_image_id(parent_image_id), + m_parent_snap_name(parent_snap_name), m_parent_snap_id(parent_snap_id), + m_ioctx(c_ioctx), m_name(c_name), m_id(c_id), m_opts(c_options), m_non_primary_global_image_id(non_primary_global_image_id), m_primary_mirror_uuid(primary_mirror_uuid), m_op_work_queue(op_work_queue), m_on_finish(on_finish), @@ -51,10 +55,13 @@ CloneRequest<I>::CloneRequest(I *p_imctx, IoCtx &c_ioctx, m_opts.set(RBD_IMAGE_OPTION_FORMAT, static_cast<uint64_t>(2)); } - ldout(m_cct, 20) << "clone " << &m_p_imctx->md_ctx << " name " << m_p_imctx->name - << " snap " << m_p_imctx->snap_name << " to child " << &m_ioctx - << " name " << m_name << " opts = " << &m_opts << dendl; - return; + ldout(m_cct, 20) << "parent_pool_id=" << parent_io_ctx.get_id() << ", " + << "parent_image_id=" << parent_image_id << ", " + << "parent_snap=" << parent_snap_name << "/" + << parent_snap_id << " clone to " + << "pool_id=" << m_ioctx.get_id() << ", " + << "name=" << m_name << ", " + << "opts=" << m_opts << dendl; } template <typename I> @@ -104,6 +111,80 @@ void CloneRequest<I>::validate_options() { } } + open_parent(); +} + +template <typename I> +void CloneRequest<I>::open_parent() { + ldout(m_cct, 20) << dendl; + + m_parent_image_ctx = I::create("", m_parent_image_id, "", m_parent_io_ctx, true); + + Context *ctx = create_context_callback< + CloneRequest<I>, &CloneRequest<I>::handle_open_parent>(this); + m_parent_image_ctx->state->open(OPEN_FLAG_SKIP_OPEN_PARENT, ctx); +} + +template <typename I> +void CloneRequest<I>::handle_open_parent(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; + + if (r < 0) { + m_parent_image_ctx->destroy(); + m_parent_image_ctx = nullptr; + + lderr(m_cct) << "failed to open parent image: " << cpp_strerror(r) << dendl; + complete(r); + return; + } + + set_parent_snap(); +} + +template <typename I> +void CloneRequest<I>::set_parent_snap() { + assert((m_parent_snap_name.empty()) ^ (m_parent_snap_id == CEPH_NOSNAP)); + + if (m_parent_snap_id == CEPH_NOSNAP) { + // look up user snapshot by name + m_parent_image_ctx->snap_lock.get_read(); + auto it = m_parent_image_ctx->snap_ids.find( + {cls::rbd::UserSnapshotNamespace{}, m_parent_snap_name}); + if (it == m_parent_image_ctx->snap_ids.end()) { + m_parent_image_ctx->snap_lock.put_read(); + + lderr(m_cct) << "failed to located parent snapshot: " << + m_parent_snap_name << dendl; + m_r_saved = -ENOENT; + close_parent(); + return; + } + + m_parent_snap_id = it->second; + m_parent_image_ctx->snap_lock.put_read(); + } + + ldout(m_cct, 20) << "parent_snap_id=" << m_parent_snap_id << dendl; + + Context *ctx = create_context_callback< + CloneRequest<I>, &CloneRequest<I>::handle_set_parent_snap>(this); + m_parent_image_ctx->state->snap_set(m_parent_snap_id, ctx); +} + +template <typename I> +void CloneRequest<I>::handle_set_parent_snap(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; + + if (r < 0) { + lderr(m_cct) << "failed to set parent snapshot: " << cpp_strerror(r) + << dendl; + + m_r_saved = r; + close_parent(); + return; + } + + m_pspec = {m_parent_io_ctx.get_id(), m_parent_image_id, m_parent_snap_id}; validate_parent(); } @@ -111,48 +192,57 @@ template <typename I> void CloneRequest<I>::validate_parent() { ldout(m_cct, 20) << dendl; - if (m_p_imctx->operations_disabled) { + if (m_parent_image_ctx->operations_disabled) { lderr(m_cct) << "image operations disabled due to unsupported op features" << dendl; - complete(-EROFS); + m_r_saved = -EROFS; + close_parent(); return; } - if (m_p_imctx->snap_id == CEPH_NOSNAP) { + if (m_parent_image_ctx->snap_id == CEPH_NOSNAP) { lderr(m_cct) << "image to be cloned must be a snapshot" << dendl; - complete(-EINVAL); + m_r_saved = -EINVAL; + close_parent(); return; } - if (m_p_imctx->old_format) { + if (m_parent_image_ctx->old_format) { lderr(m_cct) << "parent image must be in new format" << dendl; - complete(-EINVAL); + m_r_saved = -EINVAL; + close_parent(); return; } - int r = 0; + m_parent_image_ctx->snap_lock.get_read(); + uint64_t p_features = m_parent_image_ctx->features; + m_size = m_parent_image_ctx->get_image_size(m_parent_image_ctx->snap_id); + bool snap_protected; - m_p_imctx->snap_lock.get_read(); - m_p_features = m_p_imctx->features; - m_size = m_p_imctx->get_image_size(m_p_imctx->snap_id); - r = m_p_imctx->is_snap_protected(m_p_imctx->snap_id, &snap_protected); - m_p_imctx->snap_lock.put_read(); + int r = m_parent_image_ctx->is_snap_protected(m_parent_image_ctx->snap_id, &snap_protected); + m_parent_image_ctx->snap_lock.put_read(); - if ((m_p_features & RBD_FEATURE_LAYERING) != RBD_FEATURE_LAYERING) { + if ((p_features & RBD_FEATURE_LAYERING) != RBD_FEATURE_LAYERING) { lderr(m_cct) << "parent image must support layering" << dendl; - complete(-ENOSYS); + m_r_saved = -ENOSYS; + close_parent(); return; } + if (m_use_p_features) { + m_features = (p_features & ~RBD_FEATURES_IMPLICIT_ENABLE); + } if (r < 0) { lderr(m_cct) << "unable to locate parent's snapshot" << dendl; - complete(r); + m_r_saved = r; + close_parent(); return; } if (m_clone_format == 1 && !snap_protected) { lderr(m_cct) << "parent snapshot must be protected" << dendl; - complete(-EINVAL); + m_r_saved = -EINVAL; + close_parent(); return; } @@ -163,6 +253,13 @@ template <typename I> void CloneRequest<I>::validate_child() { ldout(m_cct, 20) << dendl; + if ((m_features & RBD_FEATURE_LAYERING) != RBD_FEATURE_LAYERING) { + lderr(m_cct) << "cloning image must support layering" << dendl; + m_r_saved = -ENOSYS; + close_parent(); + return; + } + using klass = CloneRequest<I>; librados::AioCompletion *comp = create_rados_callback< klass, &klass::handle_validate_child>(this); @@ -182,7 +279,8 @@ void CloneRequest<I>::handle_validate_child(int r) { if (r != -ENOENT) { lderr(m_cct) << "rbd image " << m_name << " already exists" << dendl; - complete(r); + m_r_saved = r; + close_parent(); return; } @@ -193,26 +291,17 @@ template <typename I> void CloneRequest<I>::create_child() { ldout(m_cct, 20) << dendl; - if (m_use_p_features) { - m_features = (m_p_features & ~RBD_FEATURES_IMPLICIT_ENABLE); - } - - uint64_t order = m_p_imctx->order; + uint64_t order = m_parent_image_ctx->order; if (m_opts.get(RBD_IMAGE_OPTION_ORDER, &order) != 0) { m_opts.set(RBD_IMAGE_OPTION_ORDER, order); } - if ((m_features & RBD_FEATURE_LAYERING) != RBD_FEATURE_LAYERING) { - lderr(m_cct) << "cloning image must support layering" << dendl; - complete(-ENOSYS); - return; - } m_opts.set(RBD_IMAGE_OPTION_FEATURES, m_features); using klass = CloneRequest<I>; Context *ctx = create_context_callback< klass, &klass::handle_create_child>(this); - RWLock::RLocker snap_locker(m_p_imctx->snap_lock); + RWLock::RLocker snap_locker(m_parent_image_ctx->snap_lock); CreateRequest<I> *req = CreateRequest<I>::create( m_ioctx, m_name, m_id, m_size, m_opts, m_non_primary_global_image_id, m_primary_mirror_uuid, true, m_op_work_queue, ctx); @@ -225,7 +314,8 @@ void CloneRequest<I>::handle_create_child(int r) { if (r < 0) { lderr(m_cct) << "error creating child: " << cpp_strerror(r) << dendl; - complete(r); + m_r_saved = r; + close_parent(); return; } open_child(); @@ -254,6 +344,9 @@ void CloneRequest<I>::handle_open_child(int r) { ldout(m_cct, 20) << "r=" << r << dendl; if (r < 0) { + m_imctx->destroy(); + m_imctx = nullptr; + lderr(m_cct) << "Error opening new image: " << cpp_strerror(r) << dendl; m_r_saved = r; remove_child(); @@ -331,12 +424,12 @@ void CloneRequest<I>::v2_child_attach() { ldout(m_cct, 20) << dendl; librados::ObjectWriteOperation op; - cls_client::child_attach(&op, m_p_imctx->snap_id, + cls_client::child_attach(&op, m_parent_image_ctx->snap_id, {m_imctx->md_ctx.get_id(), m_imctx->id}); auto aio_comp = create_rados_callback< CloneRequest<I>, &CloneRequest<I>::handle_v2_child_attach>(this); - int r = m_p_imctx->md_ctx.aio_operate(m_p_imctx->header_oid, aio_comp, &op); + int r = m_parent_image_ctx->md_ctx.aio_operate(m_parent_image_ctx->header_oid, aio_comp, &op); assert(r == 0); aio_comp->release(); } @@ -402,9 +495,9 @@ void CloneRequest<I>::handle_v1_refresh(int r) { bool snap_protected = false; if (r == 0) { - m_p_imctx->snap_lock.get_read(); - r = m_p_imctx->is_snap_protected(m_p_imctx->snap_id, &snap_protected); - m_p_imctx->snap_lock.put_read(); + m_parent_image_ctx->snap_lock.get_read(); + r = m_parent_image_ctx->is_snap_protected(m_parent_image_ctx->snap_id, &snap_protected); + m_parent_image_ctx->snap_lock.put_read(); } if (r < 0 || !snap_protected) { @@ -428,7 +521,7 @@ void CloneRequest<I>::metadata_list() { librados::AioCompletion *comp = create_rados_callback<klass, &klass::handle_metadata_list>(this); m_out_bl.clear(); - m_p_imctx->md_ctx.aio_operate(m_p_imctx->header_oid, + m_parent_image_ctx->md_ctx.aio_operate(m_parent_image_ctx->header_oid, comp, &op, &m_out_bl); comp->release(); } @@ -594,15 +687,17 @@ void CloneRequest<I>::handle_close_child(int r) { if (r < 0) { lderr(m_cct) << "couldn't close image: " << cpp_strerror(r) << dendl; - complete(r); - return; + if (m_r_saved == 0) { + m_r_saved = r; + } } - if (m_r_saved == 0) { - complete(0); - } else { + if (m_r_saved < 0) { remove_child(); + return; } + + close_parent(); } template <typename I> @@ -626,6 +721,36 @@ void CloneRequest<I>::handle_remove_child(int r) { lderr(m_cct) << "Error removing failed clone: " << cpp_strerror(r) << dendl; } + + close_parent(); +} + +template <typename I> +void CloneRequest<I>::close_parent() { + ldout(m_cct, 20) << dendl; + assert(m_parent_image_ctx != nullptr); + + Context *ctx = create_async_context_callback( + *m_parent_image_ctx, create_context_callback< + CloneRequest<I>, &CloneRequest<I>::handle_close_parent>(this)); + m_parent_image_ctx->state->close(ctx); +} + +template <typename I> +void CloneRequest<I>::handle_close_parent(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; + + m_parent_image_ctx->destroy(); + m_parent_image_ctx = nullptr; + + if (r < 0) { + lderr(m_cct) << "failed to close parent image: " + << cpp_strerror(r) << dendl; + if (m_r_saved == 0) { + m_r_saved = r; + } + } + complete(m_r_saved); } diff --git a/src/librbd/image/CloneRequest.h b/src/librbd/image/CloneRequest.h index 45ac351a7f0..d98ebc4f648 100644 --- a/src/librbd/image/CloneRequest.h +++ b/src/librbd/image/CloneRequest.h @@ -18,24 +18,33 @@ namespace image { template <typename ImageCtxT = ImageCtx> class CloneRequest { public: - static CloneRequest *create(ImageCtxT *p_imctx, IoCtx &c_ioctx, - const std::string &c_name, + static CloneRequest *create(IoCtx& parent_io_ctx, + const std::string& parent_image_id, + const std::string& parent_snap_name, + uint64_t parent_snap_id, + IoCtx &c_ioctx, const std::string &c_name, const std::string &c_id, ImageOptions c_options, const std::string &non_primary_global_image_id, const std::string &primary_mirror_uuid, ContextWQ *op_work_queue, Context *on_finish) { - return new CloneRequest(p_imctx, c_ioctx, c_name, c_id, c_options, + return new CloneRequest(parent_io_ctx, parent_image_id, parent_snap_name, + parent_snap_id, c_ioctx, c_name, c_id, c_options, non_primary_global_image_id, primary_mirror_uuid, op_work_queue, on_finish); } - CloneRequest(ImageCtxT *p_imctx, IoCtx &c_ioctx, const std::string &c_name, + CloneRequest(IoCtx& parent_io_ctx, + const std::string& parent_image_id, + const std::string& parent_snap_name, + uint64_t parent_snap_id, + IoCtx &c_ioctx, const std::string &c_name, const std::string &c_id, ImageOptions c_options, const std::string &non_primary_global_image_id, const std::string &primary_mirror_uuid, ContextWQ *op_work_queue, Context *on_finish); void send(); + private: /** * @verbatim @@ -43,16 +52,22 @@ private: * <start> * | * v - * VALIDATE CHILD - * | - * v - * CREATE CHILD <finish> + * OPEN PARENT <finish> * | ^ * v | + * SET PARENT SNAP * * * * * * * > CLOSE PARENT + * | * ^ + * v * | + * VALIDATE CHILD * | + * | * | + * v * | + * CREATE CHILD * * * * * * * * | + * | | + * v | * OPEN CHILD * * * * * * * * * * > REMOVE CHILD * | ^ * v | - * SET PARENT * * * * * * * * * * > CLOSE IMAGE + * SET PARENT * * * * * * * * * * > CLOSE CHILD * | ^ * |\--------\ * * | | * @@ -81,7 +96,10 @@ private: * SET MIRROR ENABLED * * * * * * * * * * | * v - * CLOSE IMAGE + * CLOSE CHILD + * | + * v + * CLOSE PARENT * | * v * <finish> @@ -89,7 +107,12 @@ private: * @endverbatim */ - ImageCtxT *m_p_imctx; + IoCtx &m_parent_io_ctx; + std::string m_parent_image_id; + std::string m_parent_snap_name; + uint64_t m_parent_snap_id; + ImageCtxT *m_parent_image_ctx; + IoCtx &m_ioctx; std::string m_name; std::string m_id; @@ -106,7 +129,6 @@ private: CephContext *m_cct; uint32_t m_clone_format = 2; bool m_use_p_features; - uint64_t m_p_features; uint64_t m_features; map<string, bufferlist> m_pairs; std::string m_last_metadata_key; @@ -115,6 +137,13 @@ private: int m_r_saved = 0; void validate_options(); + + void open_parent(); + void handle_open_parent(int r); + + void set_parent_snap(); + void handle_set_parent_snap(int r); + void validate_parent(); void validate_child(); @@ -159,6 +188,9 @@ private: void remove_child(); void handle_remove_child(int r); + void close_parent(); + void handle_close_parent(int r); + void complete(int r); }; diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 8cca5a0c5a3..97ba292907e 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -941,17 +941,23 @@ bool compare_by_name(const child_info_t& c1, const child_info_t& c2) opts.set(RBD_IMAGE_OPTION_STRIPE_UNIT, stripe_unit); opts.set(RBD_IMAGE_OPTION_STRIPE_COUNT, stripe_count); - int r = clone(p_ioctx, p_name, p_snap_name, c_ioctx, c_name, opts); + int r = clone(p_ioctx, nullptr, p_name, p_snap_name, c_ioctx, nullptr, + c_name, opts, "", ""); opts.get(RBD_IMAGE_OPTION_ORDER, &order); *c_order = order; return r; } - int clone(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name, - IoCtx& c_ioctx, const char *c_name, ImageOptions& c_opts) + int clone(IoCtx& p_ioctx, const char *p_id, const char *p_name, + const char *p_snap_name, IoCtx& c_ioctx, const char *c_id, + const char *c_name, ImageOptions& c_opts, + const std::string &non_primary_global_image_id, + const std::string &primary_mirror_uuid) { + assert((p_id == nullptr) ^ (p_name == nullptr)); + CephContext *cct = (CephContext *)p_ioctx.cct(); - if (p_snap_name == NULL) { + if (p_snap_name == nullptr) { lderr(cct) << "image to be cloned must be a snapshot" << dendl; return -EINVAL; } @@ -962,42 +968,32 @@ bool compare_by_name(const child_info_t& c1, const child_info_t& c2) 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(0); - if (r < 0) { - lderr(cct) << "error opening parent image: " - << cpp_strerror(r) << dendl; - return r; - } - - r = clone(p_imctx, c_ioctx, c_name, "", c_opts, "", ""); - - int close_r = p_imctx->state->close(); - if (r == 0 && close_r < 0) { - r = close_r; - } - - if (r < 0) { - return r; + int r; + std::string parent_id; + if (p_id == nullptr) { + r = cls_client::dir_get_id(&p_ioctx, RBD_DIRECTORY, p_name, + &parent_id); + if (r < 0) { + if (r != -ENOENT) { + lderr(cct) << "failed to retrieve parent image id: " + << cpp_strerror(r) << dendl; + } + return r; + } + } else { + parent_id = p_id; } - return 0; - } - int clone(ImageCtx *p_imctx, IoCtx& c_ioctx, const std::string &c_name, - const std::string &c_id, ImageOptions& c_opts, - const std::string &non_primary_global_image_id, - const std::string &primary_mirror_uuid) - { - std::string id(c_id); - if (id.empty()) { - id = util::generate_image_id(c_ioctx); + std::string clone_id; + if (c_id == nullptr) { + clone_id = util::generate_image_id(c_ioctx); + } else { + clone_id = c_id; } - CephContext *cct = (CephContext *)c_ioctx.cct(); ldout(cct, 10) << __func__ << " " << "c_name=" << c_name << ", " - << "c_id= " << c_id << ", " + << "c_id= " << clone_id << ", " << "c_opts=" << c_opts << dendl; ThreadPool *thread_pool; @@ -1006,11 +1002,17 @@ bool compare_by_name(const child_info_t& c1, const child_info_t& c2) C_SaferCond cond; auto *req = image::CloneRequest<>::create( - p_imctx, c_ioctx, c_name, id, c_opts, - non_primary_global_image_id, primary_mirror_uuid, op_work_queue, &cond); + p_ioctx, parent_id, p_snap_name, CEPH_NOSNAP, c_ioctx, c_name, clone_id, + c_opts, non_primary_global_image_id, primary_mirror_uuid, op_work_queue, + &cond); req->send(); - return cond.wait(); + r = cond.wait(); + if (r < 0) { + return r; + } + + return 0; } int rename(IoCtx& io_ctx, const char *srcname, const char *dstname) diff --git a/src/librbd/internal.h b/src/librbd/internal.h index 3271d902cb0..889eff3b3aa 100644 --- a/src/librbd/internal.h +++ b/src/librbd/internal.h @@ -77,10 +77,9 @@ namespace librbd { IoCtx& c_ioctx, const char *c_name, uint64_t features, int *c_order, uint64_t stripe_unit, int stripe_count); - int clone(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name, - IoCtx& c_ioctx, const char *c_name, ImageOptions& c_opts); - int clone(ImageCtx *p_imctx, IoCtx& c_ioctx, const std::string &c_name, - const std::string &c_id, ImageOptions& c_opts, + int clone(IoCtx& p_ioctx, const char *p_id, const char *p_name, + const char *p_snap_name, IoCtx& c_ioctx, const char *c_id, + const char *c_name, ImageOptions& c_opts, const std::string &non_primary_global_image_id, const std::string &primary_mirror_uuid); int rename(librados::IoCtx& io_ctx, const char *srcname, const char *dstname); diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index 4b21ec5fe3c..eaf705fa609 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -532,8 +532,8 @@ namespace librbd { { TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioctx)); tracepoint(librbd, clone3_enter, p_ioctx.get_pool_name().c_str(), p_ioctx.get_id(), p_name, p_snap_name, c_ioctx.get_pool_name().c_str(), c_ioctx.get_id(), c_name, c_opts.opts); - int r = librbd::clone(p_ioctx, p_name, p_snap_name, c_ioctx, c_name, - c_opts); + int r = librbd::clone(p_ioctx, nullptr, p_name, p_snap_name, c_ioctx, + nullptr, c_name, c_opts, "", ""); tracepoint(librbd, clone3_exit, r); return r; } @@ -2671,7 +2671,8 @@ extern "C" int rbd_clone3(rados_ioctx_t p_ioctx, const char *p_name, TracepointProvider::initialize<tracepoint_traits>(get_cct(p_ioc)); tracepoint(librbd, clone3_enter, p_ioc.get_pool_name().c_str(), p_ioc.get_id(), p_name, p_snap_name, c_ioc.get_pool_name().c_str(), c_ioc.get_id(), c_name, c_opts); librbd::ImageOptions c_opts_(c_opts); - int r = librbd::clone(p_ioc, p_name, p_snap_name, c_ioc, c_name, c_opts_); + int r = librbd::clone(p_ioc, nullptr, p_name, p_snap_name, c_ioc, nullptr, + c_name, c_opts_, "", ""); tracepoint(librbd, clone3_exit, r); return r; } diff --git a/src/test/librbd/image/test_mock_CloneRequest.cc b/src/test/librbd/image/test_mock_CloneRequest.cc index 16fc92ab7ca..f149008ebbb 100644 --- a/src/test/librbd/image/test_mock_CloneRequest.cc +++ b/src/test/librbd/image/test_mock_CloneRequest.cc @@ -224,6 +224,17 @@ public: .WillOnce(WithArg<1>(Invoke([this, r](Context* ctx) { image_ctx->op_work_queue->queue(ctx, r); }))); + if (r < 0) { + EXPECT_CALL(mock_image_ctx, destroy()); + } + } + + void expect_snap_set(librbd::MockTestImageCtx &mock_image_ctx, + uint64_t snap_id, int r) { + EXPECT_CALL(*mock_image_ctx.state, snap_set(snap_id, _)) + .WillOnce(WithArg<1>(Invoke([this, r](Context *on_finish) { + image_ctx->op_work_queue->queue(on_finish, r); + }))); } void expect_set_parent(MockImageCtx &mock_image_ctx, int r) { @@ -352,6 +363,9 @@ TEST_F(TestMockImageCloneRequest, SuccessV1) { expect_op_work_queue(mock_image_ctx); InSequence seq; + expect_open(mock_image_ctx, 0); + expect_snap_set(mock_image_ctx, 123, 0); + expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123); expect_is_snap_protected(mock_image_ctx, true, 0); @@ -380,11 +394,12 @@ TEST_F(TestMockImageCloneRequest, SuccessV1) { } expect_close(mock_image_ctx, 0); + expect_close(mock_image_ctx, 0); C_SaferCond ctx; ImageOptions clone_opts; - auto req = new MockCloneRequest(&mock_image_ctx, m_ioctx, "clone name", - "clone id", clone_opts, "", "", + auto req = new MockCloneRequest(m_ioctx, "parent id", "", 123, m_ioctx, + "clone name", "clone id", clone_opts, "", "", image_ctx->op_work_queue, &ctx); req->send(); ASSERT_EQ(0, ctx.wait()); @@ -397,6 +412,9 @@ TEST_F(TestMockImageCloneRequest, SuccessV2) { expect_op_work_queue(mock_image_ctx); InSequence seq; + expect_open(mock_image_ctx, 0); + expect_snap_set(mock_image_ctx, 123, 0); + expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123); expect_is_snap_protected(mock_image_ctx, true, 0); @@ -423,11 +441,12 @@ TEST_F(TestMockImageCloneRequest, SuccessV2) { } expect_close(mock_image_ctx, 0); + expect_close(mock_image_ctx, 0); C_SaferCond ctx; ImageOptions clone_opts; - auto req = new MockCloneRequest(&mock_image_ctx, m_ioctx, "clone name", - "clone id", clone_opts, "", "", + auto req = new MockCloneRequest(m_ioctx, "parent id", "", 123, m_ioctx, + "clone name", "clone id", clone_opts, "", "", image_ctx->op_work_queue, &ctx); req->send(); ASSERT_EQ(0, ctx.wait()); @@ -442,6 +461,9 @@ TEST_F(TestMockImageCloneRequest, SuccessAuto) { InSequence seq; expect_get_min_compat_client(1, 0); + expect_open(mock_image_ctx, 0); + expect_snap_set(mock_image_ctx, 123, 0); + expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123); expect_is_snap_protected(mock_image_ctx, true, 0); @@ -470,16 +492,55 @@ TEST_F(TestMockImageCloneRequest, SuccessAuto) { } expect_close(mock_image_ctx, 0); + expect_close(mock_image_ctx, 0); C_SaferCond ctx; ImageOptions clone_opts; - auto req = new MockCloneRequest(&mock_image_ctx, m_ioctx, "clone name", - "clone id", clone_opts, "", "", + auto req = new MockCloneRequest(m_ioctx, "parent id", "", 123, m_ioctx, + "clone name", "clone id", clone_opts, "", "", image_ctx->op_work_queue, &ctx); req->send(); ASSERT_EQ(0, ctx.wait()); } +TEST_F(TestMockImageCloneRequest, OpenParentError) { + REQUIRE_FEATURE(RBD_FEATURE_LAYERING); + + MockTestImageCtx mock_image_ctx(*image_ctx); + expect_op_work_queue(mock_image_ctx); + + InSequence seq; + expect_open(mock_image_ctx, -EINVAL); + + C_SaferCond ctx; + ImageOptions clone_opts; + auto req = new MockCloneRequest(m_ioctx, "parent id", "", 123, m_ioctx, + "clone name", "clone id", clone_opts, "", "", + image_ctx->op_work_queue, &ctx); + req->send(); + ASSERT_EQ(-EINVAL, ctx.wait()); +} + +TEST_F(TestMockImageCloneRequest, SetParentSnapError) { + REQUIRE_FEATURE(RBD_FEATURE_LAYERING); + + MockTestImageCtx mock_image_ctx(*image_ctx); + expect_op_work_queue(mock_image_ctx); + + InSequence seq; + expect_open(mock_image_ctx, 0); + expect_snap_set(mock_image_ctx, 123, -EINVAL); + expect_close(mock_image_ctx, 0); + + C_SaferCond ctx; + ImageOptions clone_opts; + auto req = new MockCloneRequest(m_ioctx, "parent id", "", 123, m_ioctx, + "clone name", "clone id", clone_opts, "", "", + image_ctx->op_work_queue, &ctx); + req->send(); + ASSERT_EQ(-EINVAL, ctx.wait()); +} + TEST_F(TestMockImageCloneRequest, CreateError) { REQUIRE_FEATURE(RBD_FEATURE_LAYERING); @@ -487,16 +548,21 @@ TEST_F(TestMockImageCloneRequest, CreateError) { expect_op_work_queue(mock_image_ctx); InSequence seq; + expect_open(mock_image_ctx, 0); + expect_snap_set(mock_image_ctx, 123, 0); + expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123); expect_is_snap_protected(mock_image_ctx, true, 0); MockCreateRequest mock_create_request; expect_create(mock_create_request, -EINVAL); + expect_close(mock_image_ctx, 0); + C_SaferCond ctx; ImageOptions clone_opts; - auto req = new MockCloneRequest(&mock_image_ctx, m_ioctx, "clone name", - "clone id", clone_opts, "", "", + auto req = new MockCloneRequest(m_ioctx, "parent id", "", 123, m_ioctx, + "clone name", "clone id", clone_opts, "", "", image_ctx->op_work_queue, &ctx); req->send(); ASSERT_EQ(-EINVAL, ctx.wait()); @@ -509,6 +575,9 @@ TEST_F(TestMockImageCloneRequest, OpenError) { expect_op_work_queue(mock_image_ctx); InSequence seq; + expect_open(mock_image_ctx, 0); + expect_snap_set(mock_image_ctx, 123, 0); + expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123); expect_is_snap_protected(mock_image_ctx, true, 0); @@ -520,10 +589,12 @@ TEST_F(TestMockImageCloneRequest, OpenError) { MockRemoveRequest mock_remove_request; expect_remove(mock_remove_request, 0); + expect_close(mock_image_ctx, 0); + C_SaferCond ctx; ImageOptions clone_opts; - auto req = new MockCloneRequest(&mock_image_ctx, m_ioctx, "clone name", - "clone id", clone_opts, "", "", + auto req = new MockCloneRequest(m_ioctx, "parent id", "", 123, m_ioctx, + "clone name", "clone id", clone_opts, "", "", image_ctx->op_work_queue, &ctx); req->send(); ASSERT_EQ(-EINVAL, ctx.wait()); @@ -536,6 +607,9 @@ TEST_F(TestMockImageCloneRequest, SetParentError) { expect_op_work_queue(mock_image_ctx); InSequence seq; + expect_open(mock_image_ctx, 0); + expect_snap_set(mock_image_ctx, 123, 0); + expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123); expect_is_snap_protected(mock_image_ctx, true, 0); @@ -549,10 +623,12 @@ TEST_F(TestMockImageCloneRequest, SetParentError) { MockRemoveRequest mock_remove_request; expect_remove(mock_remove_request, 0); + expect_close(mock_image_ctx, 0); + C_SaferCond ctx; ImageOptions clone_opts; - auto req = new MockCloneRequest(&mock_image_ctx, m_ioctx, "clone name", - "clone id", clone_opts, "", "", + auto req = new MockCloneRequest(m_ioctx, "parent id", "", 123, m_ioctx, + "clone name", "clone id", clone_opts, "", "", image_ctx->op_work_queue, &ctx); req->send(); ASSERT_EQ(-EINVAL, ctx.wait()); @@ -566,6 +642,9 @@ TEST_F(TestMockImageCloneRequest, AddChildError) { expect_op_work_queue(mock_image_ctx); InSequence seq; + expect_open(mock_image_ctx, 0); + expect_snap_set(mock_image_ctx, 123, 0); + expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123); expect_is_snap_protected(mock_image_ctx, true, 0); @@ -580,10 +659,12 @@ TEST_F(TestMockImageCloneRequest, AddChildError) { MockRemoveRequest mock_remove_request; expect_remove(mock_remove_request, 0); + expect_close(mock_image_ctx, 0); + C_SaferCond ctx; ImageOptions clone_opts; - auto req = new MockCloneRequest(&mock_image_ctx, m_ioctx, "clone name", - "clone id", clone_opts, "", "", + auto req = new MockCloneRequest(m_ioctx, "parent id", "", 123, m_ioctx, + "clone name", "clone id", clone_opts, "", "", image_ctx->op_work_queue, &ctx); req->send(); ASSERT_EQ(-EINVAL, ctx.wait()); @@ -597,6 +678,9 @@ TEST_F(TestMockImageCloneRequest, RefreshError) { expect_op_work_queue(mock_image_ctx); InSequence seq; + expect_open(mock_image_ctx, 0); + expect_snap_set(mock_image_ctx, 123, 0); + expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123); expect_is_snap_protected(mock_image_ctx, true, 0); @@ -615,10 +699,12 @@ TEST_F(TestMockImageCloneRequest, RefreshError) { MockRemoveRequest mock_remove_request; expect_remove(mock_remove_request, 0); + expect_close(mock_image_ctx, 0); + C_SaferCond ctx; ImageOptions clone_opts; - auto req = new MockCloneRequest(&mock_image_ctx, m_ioctx, "clone name", - "clone id", clone_opts, "", "", + auto req = new MockCloneRequest(m_ioctx, "parent id", "", 123, m_ioctx, + "clone name", "clone id", clone_opts, "", "", image_ctx->op_work_queue, &ctx); req->send(); ASSERT_EQ(-EINVAL, ctx.wait()); @@ -632,6 +718,9 @@ TEST_F(TestMockImageCloneRequest, MetadataListError) { expect_op_work_queue(mock_image_ctx); InSequence seq; + expect_open(mock_image_ctx, 0); + expect_snap_set(mock_image_ctx, 123, 0); + expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123); expect_is_snap_protected(mock_image_ctx, true, 0); @@ -653,10 +742,12 @@ TEST_F(TestMockImageCloneRequest, MetadataListError) { MockRemoveRequest mock_remove_request; expect_remove(mock_remove_request, 0); + expect_close(mock_image_ctx, 0); + C_SaferCond ctx; ImageOptions clone_opts; - auto req = new MockCloneRequest(&mock_image_ctx, m_ioctx, "clone name", - "clone id", clone_opts, "", "", + auto req = new MockCloneRequest(m_ioctx, "parent id", "", 123, m_ioctx, + "clone name", "clone id", clone_opts, "", "", image_ctx->op_work_queue, &ctx); req->send(); ASSERT_EQ(-EINVAL, ctx.wait()); @@ -669,6 +760,9 @@ TEST_F(TestMockImageCloneRequest, MetadataSetError) { expect_op_work_queue(mock_image_ctx); InSequence seq; + expect_open(mock_image_ctx, 0); + expect_snap_set(mock_image_ctx, 123, 0); + expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123); expect_is_snap_protected(mock_image_ctx, true, 0); @@ -689,10 +783,12 @@ TEST_F(TestMockImageCloneRequest, MetadataSetError) { MockRemoveRequest mock_remove_request; expect_remove(mock_remove_request, 0); + expect_close(mock_image_ctx, 0); + C_SaferCond ctx; ImageOptions clone_opts; - auto req = new MockCloneRequest(&mock_image_ctx, m_ioctx, "clone name", - "clone id", clone_opts, "", "", + auto req = new MockCloneRequest(m_ioctx, "parent id", "", 123, m_ioctx, + "clone name", "clone id", clone_opts, "", "", image_ctx->op_work_queue, &ctx); req->send(); ASSERT_EQ(-EINVAL, ctx.wait()); @@ -706,6 +802,9 @@ TEST_F(TestMockImageCloneRequest, GetMirrorModeError) { expect_op_work_queue(mock_image_ctx); InSequence seq; + expect_open(mock_image_ctx, 0); + expect_snap_set(mock_image_ctx, 123, 0); + expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123); expect_is_snap_protected(mock_image_ctx, true, 0); @@ -730,10 +829,12 @@ TEST_F(TestMockImageCloneRequest, GetMirrorModeError) { MockRemoveRequest mock_remove_request; expect_remove(mock_remove_request, 0); + expect_close(mock_image_ctx, 0); + C_SaferCond ctx; ImageOptions clone_opts; - auto req = new MockCloneRequest(&mock_image_ctx, m_ioctx, "clone name", - "clone id", clone_opts, "", "", + auto req = new MockCloneRequest(m_ioctx, "parent id", "", 123, m_ioctx, + "clone name", "clone id", clone_opts, "", "", image_ctx->op_work_queue, &ctx); req->send(); ASSERT_EQ(-EINVAL, ctx.wait()); @@ -746,6 +847,9 @@ TEST_F(TestMockImageCloneRequest, MirrorEnableError) { expect_op_work_queue(mock_image_ctx); InSequence seq; + expect_open(mock_image_ctx, 0); + expect_snap_set(mock_image_ctx, 123, 0); + expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123); expect_is_snap_protected(mock_image_ctx, true, 0); @@ -771,10 +875,12 @@ TEST_F(TestMockImageCloneRequest, MirrorEnableError) { MockRemoveRequest mock_remove_request; expect_remove(mock_remove_request, 0); + expect_close(mock_image_ctx, 0); + C_SaferCond ctx; ImageOptions clone_opts; - auto req = new MockCloneRequest(&mock_image_ctx, m_ioctx, "clone name", - "clone id", clone_opts, "", "", + auto req = new MockCloneRequest(m_ioctx, "parent id", "", 123, m_ioctx, + "clone name", "clone id", clone_opts, "", "", image_ctx->op_work_queue, &ctx); req->send(); ASSERT_EQ(-EINVAL, ctx.wait()); @@ -787,6 +893,9 @@ TEST_F(TestMockImageCloneRequest, CloseError) { expect_op_work_queue(mock_image_ctx); InSequence seq; + expect_open(mock_image_ctx, 0); + expect_snap_set(mock_image_ctx, 123, 0); + expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123); expect_is_snap_protected(mock_image_ctx, true, 0); @@ -804,10 +913,15 @@ TEST_F(TestMockImageCloneRequest, CloseError) { expect_close(mock_image_ctx, -EINVAL); + MockRemoveRequest mock_remove_request; + expect_remove(mock_remove_request, 0); + + expect_close(mock_image_ctx, 0); + C_SaferCond ctx; ImageOptions clone_opts; - auto req = new MockCloneRequest(&mock_image_ctx, m_ioctx, "clone name", - "clone id", clone_opts, "", "", + auto req = new MockCloneRequest(m_ioctx, "parent id", "", 123, m_ioctx, + "clone name", "clone id", clone_opts, "", "", image_ctx->op_work_queue, &ctx); req->send(); ASSERT_EQ(-EINVAL, ctx.wait()); @@ -820,6 +934,9 @@ TEST_F(TestMockImageCloneRequest, RemoveError) { expect_op_work_queue(mock_image_ctx); InSequence seq; + expect_open(mock_image_ctx, 0); + expect_snap_set(mock_image_ctx, 123, 0); + expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123); expect_is_snap_protected(mock_image_ctx, true, 0); @@ -831,10 +948,44 @@ TEST_F(TestMockImageCloneRequest, RemoveError) { MockRemoveRequest mock_remove_request; expect_remove(mock_remove_request, -EPERM); + expect_close(mock_image_ctx, 0); + + C_SaferCond ctx; + ImageOptions clone_opts; + auto req = new MockCloneRequest(m_ioctx, "parent id", "", 123, m_ioctx, + "clone name", "clone id", clone_opts, "", "", + image_ctx->op_work_queue, &ctx); + req->send(); + ASSERT_EQ(-EINVAL, ctx.wait()); +} + +TEST_F(TestMockImageCloneRequest, CloseParentError) { + REQUIRE_FEATURE(RBD_FEATURE_LAYERING); + + MockTestImageCtx mock_image_ctx(*image_ctx); + expect_op_work_queue(mock_image_ctx); + + InSequence seq; + expect_open(mock_image_ctx, 0); + expect_snap_set(mock_image_ctx, 123, 0); + + expect_get_image_size(mock_image_ctx, mock_image_ctx.snaps.front(), 123); + expect_is_snap_protected(mock_image_ctx, true, 0); + + MockCreateRequest mock_create_request; + expect_create(mock_create_request, 0); + + expect_open(mock_image_ctx, -EINVAL); + + MockRemoveRequest mock_remove_request; + expect_remove(mock_remove_request, 0); + + expect_close(mock_image_ctx, -EPERM); + C_SaferCond ctx; ImageOptions clone_opts; - auto req = new MockCloneRequest(&mock_image_ctx, m_ioctx, "clone name", - "clone id", clone_opts, "", "", + auto req = new MockCloneRequest(m_ioctx, "parent id", "", 123, m_ioctx, + "clone name", "clone id", clone_opts, "", "", image_ctx->op_work_queue, &ctx); req->send(); ASSERT_EQ(-EINVAL, ctx.wait()); diff --git a/src/test/rbd_mirror/image_replayer/test_mock_CreateImageRequest.cc b/src/test/rbd_mirror/image_replayer/test_mock_CreateImageRequest.cc index 3d2152ab931..a0715e6c352 100644 --- a/src/test/rbd_mirror/image_replayer/test_mock_CreateImageRequest.cc +++ b/src/test/rbd_mirror/image_replayer/test_mock_CreateImageRequest.cc @@ -72,15 +72,18 @@ struct CloneRequest<librbd::MockTestImageCtx> { static CloneRequest *s_instance; Context *on_finish = nullptr; - static CloneRequest *create(librbd::MockTestImageCtx *p_imctx, + static CloneRequest *create(IoCtx &p_ioctx, const std::string &p_id, + const std::string &p_snap_name, + uint64_t p_snap_id, IoCtx &c_ioctx, const std::string &c_name, const std::string &c_id, ImageOptions c_options, const std::string &non_primary_global_image_id, const std::string &primary_mirror_uuid, - MockContextWQ *op_work_queue, Context *on_finish) { + MockContextWQ *op_work_queue, + Context *on_finish) { assert(s_instance != nullptr); s_instance->on_finish = on_finish; - s_instance->construct(p_imctx); + s_instance->construct(); return s_instance; } @@ -93,7 +96,7 @@ struct CloneRequest<librbd::MockTestImageCtx> { } MOCK_METHOD0(send, void()); - MOCK_METHOD1(construct, void(librbd::MockTestImageCtx *p_imctx)); + MOCK_METHOD0(construct, void()); }; CloneRequest<librbd::MockTestImageCtx>* @@ -281,22 +284,9 @@ public: })); } - void expect_snap_set(librbd::MockTestImageCtx &mock_image_ctx, - const std::string &snap_name, int r) { - EXPECT_CALL(*mock_image_ctx.state, snap_set(_, _)) - .WillOnce(Invoke([this, &mock_image_ctx, snap_name, r](uint64_t snap_id, Context *on_finish) { - RWLock::RLocker snap_locker(mock_image_ctx.snap_lock); - auto id = mock_image_ctx.image_ctx->get_snap_id( - cls::rbd::UserSnapshotNamespace{}, snap_name); - ASSERT_EQ(snap_id, id); - m_threads->work_queue->queue(on_finish, r); - })); - } - void expect_clone_image(MockCloneRequest &mock_clone_request, - librbd::MockTestImageCtx &mock_parent_imctx, int r) { - EXPECT_CALL(mock_clone_request, construct(&mock_parent_imctx)); + EXPECT_CALL(mock_clone_request, construct()); EXPECT_CALL(mock_clone_request, send()) .WillOnce(Invoke([this, &mock_clone_request, r]() { m_threads->work_queue->queue(mock_clone_request.on_finish, r); @@ -372,7 +362,6 @@ TEST_F(TestMockImageReplayerCreateImageRequest, Clone) { &remote_clone_image_ctx)); librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx); - librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx); librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx); MockCloneRequest mock_clone_request; MockOpenImageRequest mock_open_image_request; @@ -386,11 +375,7 @@ TEST_F(TestMockImageReplayerCreateImageRequest, Clone) { expect_open_image(mock_open_image_request, m_remote_io_ctx, m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0); - expect_open_image(mock_open_image_request, m_local_io_ctx, - "local parent id", mock_local_parent_image_ctx, 0); - expect_snap_set(mock_local_parent_image_ctx, "snap", 0); - expect_clone_image(mock_clone_request, mock_local_parent_image_ctx, 0); - expect_close_image(mock_close_image_request, mock_local_parent_image_ctx, 0); + expect_clone_image(mock_clone_request, 0); expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0); C_SaferCond ctx; @@ -484,91 +469,6 @@ TEST_F(TestMockImageReplayerCreateImageRequest, CloneOpenRemoteParentError) { ASSERT_EQ(-ENOENT, ctx.wait()); } -TEST_F(TestMockImageReplayerCreateImageRequest, CloneOpenLocalParentError) { - librbd::RBD rbd; - librbd::ImageCtx *local_image_ctx; - ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size)); - ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx)); - - std::string clone_image_name = get_temp_image_name(); - ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name)); - - librbd::ImageCtx *remote_clone_image_ctx; - ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name, - &remote_clone_image_ctx)); - - librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx); - librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx); - librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx); - MockCloneRequest mock_clone_request; - MockOpenImageRequest mock_open_image_request; - MockCloseImageRequest mock_close_image_request; - - InSequence seq; - expect_ioctx_create(m_remote_io_ctx); - expect_ioctx_create(m_local_io_ctx); - expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0); - expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0); - - expect_open_image(mock_open_image_request, m_remote_io_ctx, - m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0); - expect_open_image(mock_open_image_request, m_local_io_ctx, - "local parent id", mock_local_parent_image_ctx, -ENOENT); - expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0); - - C_SaferCond ctx; - MockCreateImageRequest *request = create_request("global uuid", "remote uuid", - "image name", "101241a7c4c9", - mock_remote_clone_image_ctx, - &ctx); - request->send(); - ASSERT_EQ(-ENOENT, ctx.wait()); -} - -TEST_F(TestMockImageReplayerCreateImageRequest, CloneSnapSetError) { - librbd::RBD rbd; - librbd::ImageCtx *local_image_ctx; - ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size)); - ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx)); - snap_create(local_image_ctx, "snap"); - - std::string clone_image_name = get_temp_image_name(); - ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name)); - - librbd::ImageCtx *remote_clone_image_ctx; - ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name, - &remote_clone_image_ctx)); - - librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx); - librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx); - librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx); - MockCloneRequest mock_clone_request; - MockOpenImageRequest mock_open_image_request; - MockCloseImageRequest mock_close_image_request; - - InSequence seq; - expect_ioctx_create(m_remote_io_ctx); - expect_ioctx_create(m_local_io_ctx); - expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0); - expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0); - - expect_open_image(mock_open_image_request, m_remote_io_ctx, - m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0); - expect_open_image(mock_open_image_request, m_local_io_ctx, - "local parent id", mock_local_parent_image_ctx, 0); - expect_snap_set(mock_local_parent_image_ctx, "snap", -ENOENT); - expect_close_image(mock_close_image_request, mock_local_parent_image_ctx, 0); - expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0); - - C_SaferCond ctx; - MockCreateImageRequest *request = create_request("global uuid", "remote uuid", - "image name", "101241a7c4c9", - mock_remote_clone_image_ctx, - &ctx); - request->send(); - ASSERT_EQ(-ENOENT, ctx.wait()); -} - TEST_F(TestMockImageReplayerCreateImageRequest, CloneError) { librbd::RBD rbd; librbd::ImageCtx *local_image_ctx; @@ -584,7 +484,6 @@ TEST_F(TestMockImageReplayerCreateImageRequest, CloneError) { &remote_clone_image_ctx)); librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx); - librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx); librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx); MockCloneRequest mock_clone_request; MockOpenImageRequest mock_open_image_request; @@ -598,11 +497,7 @@ TEST_F(TestMockImageReplayerCreateImageRequest, CloneError) { expect_open_image(mock_open_image_request, m_remote_io_ctx, m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0); - expect_open_image(mock_open_image_request, m_local_io_ctx, - "local parent id", mock_local_parent_image_ctx, 0); - expect_snap_set(mock_local_parent_image_ctx, "snap", 0); - expect_clone_image(mock_clone_request, mock_local_parent_image_ctx, -EINVAL); - expect_close_image(mock_close_image_request, mock_local_parent_image_ctx, 0); + expect_clone_image(mock_clone_request, -EINVAL); expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0); C_SaferCond ctx; @@ -614,51 +509,6 @@ TEST_F(TestMockImageReplayerCreateImageRequest, CloneError) { ASSERT_EQ(-EINVAL, ctx.wait()); } -TEST_F(TestMockImageReplayerCreateImageRequest, CloneLocalParentCloseError) { - librbd::RBD rbd; - librbd::ImageCtx *local_image_ctx; - ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size)); - ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx)); - snap_create(local_image_ctx, "snap"); - - std::string clone_image_name = get_temp_image_name(); - ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name)); - - librbd::ImageCtx *remote_clone_image_ctx; - ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name, - &remote_clone_image_ctx)); - - librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx); - librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx); - librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx); - MockCloneRequest mock_clone_request; - MockOpenImageRequest mock_open_image_request; - MockCloseImageRequest mock_close_image_request; - - InSequence seq; - expect_ioctx_create(m_remote_io_ctx); - expect_ioctx_create(m_local_io_ctx); - expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0); - expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0); - - expect_open_image(mock_open_image_request, m_remote_io_ctx, - m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0); - expect_open_image(mock_open_image_request, m_local_io_ctx, - "local parent id", mock_local_parent_image_ctx, 0); - expect_snap_set(mock_local_parent_image_ctx, "snap", 0); - expect_clone_image(mock_clone_request, mock_local_parent_image_ctx, 0); - expect_close_image(mock_close_image_request, mock_local_parent_image_ctx, -EINVAL); - expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0); - - C_SaferCond ctx; - MockCreateImageRequest *request = create_request("global uuid", "remote uuid", - "image name", "101241a7c4c9", - mock_remote_clone_image_ctx, - &ctx); - request->send(); - ASSERT_EQ(0, ctx.wait()); -} - TEST_F(TestMockImageReplayerCreateImageRequest, CloneRemoteParentCloseError) { librbd::RBD rbd; librbd::ImageCtx *local_image_ctx; @@ -674,7 +524,6 @@ TEST_F(TestMockImageReplayerCreateImageRequest, CloneRemoteParentCloseError) { &remote_clone_image_ctx)); librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx); - librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx); librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx); MockCloneRequest mock_clone_request; MockOpenImageRequest mock_open_image_request; @@ -688,11 +537,7 @@ TEST_F(TestMockImageReplayerCreateImageRequest, CloneRemoteParentCloseError) { expect_open_image(mock_open_image_request, m_remote_io_ctx, m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0); - expect_open_image(mock_open_image_request, m_local_io_ctx, - "local parent id", mock_local_parent_image_ctx, 0); - expect_snap_set(mock_local_parent_image_ctx, "snap", 0); - expect_clone_image(mock_clone_request, mock_local_parent_image_ctx, 0); - expect_close_image(mock_close_image_request, mock_local_parent_image_ctx, 0); + expect_clone_image(mock_clone_request, 0); expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, -EINVAL); C_SaferCond ctx; diff --git a/src/test/rbd_mirror/test_ImageDeleter.cc b/src/test/rbd_mirror/test_ImageDeleter.cc index 69f7ba9ef13..ee62ced0f57 100644 --- a/src/test/rbd_mirror/test_ImageDeleter.cc +++ b/src/test/rbd_mirror/test_ImageDeleter.cc @@ -193,9 +193,10 @@ public: std::string clone_id = librbd::util::generate_image_id(m_local_io_ctx); librbd::ImageOptions clone_opts; clone_opts.set(RBD_IMAGE_OPTION_FEATURES, ictx->features); - EXPECT_EQ(0, librbd::clone(ictx, m_local_io_ctx, "clone1", clone_id, - clone_opts, GLOBAL_CLONE_IMAGE_ID, - m_remote_mirror_uuid)); + EXPECT_EQ(0, librbd::clone(m_local_io_ctx, m_local_image_id.c_str(), + nullptr, "snap1", m_local_io_ctx, + clone_id.c_str(), "clone1", clone_opts, + GLOBAL_CLONE_IMAGE_ID, m_remote_mirror_uuid)); cls::rbd::MirrorImage mirror_image( GLOBAL_CLONE_IMAGE_ID, MirrorImageState::MIRROR_IMAGE_STATE_ENABLED); diff --git a/src/tools/rbd_mirror/image_replayer/CreateImageRequest.cc b/src/tools/rbd_mirror/image_replayer/CreateImageRequest.cc index 11831c19336..453471a0a9e 100644 --- a/src/tools/rbd_mirror/image_replayer/CreateImageRequest.cc +++ b/src/tools/rbd_mirror/image_replayer/CreateImageRequest.cc @@ -202,38 +202,13 @@ void CreateImageRequest<I>::handle_open_remote_parent_image(int r) { return; } - open_local_parent_image(); + clone_image(); } template <typename I> -void CreateImageRequest<I>::open_local_parent_image() { +void CreateImageRequest<I>::clone_image() { dout(20) << dendl; - Context *ctx = create_context_callback< - CreateImageRequest<I>, - &CreateImageRequest<I>::handle_open_local_parent_image>(this); - OpenImageRequest<I> *request = OpenImageRequest<I>::create( - m_local_parent_io_ctx, &m_local_parent_image_ctx, - m_local_parent_spec.image_id, true, ctx); - request->send(); -} - -template <typename I> -void CreateImageRequest<I>::handle_open_local_parent_image(int r) { - dout(20) << ": r=" << r << dendl; - if (r < 0) { - derr << ": failed to open local parent image " << m_parent_pool_name << "/" - << m_local_parent_spec.image_id << dendl; - m_ret_val = r; - close_remote_parent_image(); - return; - } - - set_local_parent_snap(); -} - -template <typename I> -void CreateImageRequest<I>::set_local_parent_snap() { std::string snap_name; cls::rbd::SnapshotNamespace snap_namespace; { @@ -246,66 +221,18 @@ void CreateImageRequest<I>::set_local_parent_snap() { } } - if (snap_name.empty()) { - dout(15) << ": failed to locate remote parent snapshot" << dendl; - m_ret_val = -ENOENT; - close_local_parent_image(); - return; - } - - m_local_parent_spec.snap_id = CEPH_NOSNAP; - { - RWLock::RLocker local_snap_locker(m_local_parent_image_ctx->snap_lock); - auto it = m_local_parent_image_ctx->snap_ids.find( - {snap_namespace, snap_name}); - if (it != m_local_parent_image_ctx->snap_ids.end()) { - m_local_parent_spec.snap_id = it->second; - } - } - - if (m_local_parent_spec.snap_id == CEPH_NOSNAP) { - dout(15) << ": failed to locate local parent snapshot" << dendl; - m_ret_val = -ENOENT; - close_local_parent_image(); - return; - } - - dout(15) << ": local_snap_id=" << m_local_parent_spec.snap_id << dendl; - - Context *ctx = create_context_callback< - CreateImageRequest<I>, - &CreateImageRequest<I>::handle_set_local_parent_snap>(this); - m_local_parent_image_ctx->state->snap_set(m_local_parent_spec.snap_id, ctx); -} - -template <typename I> -void CreateImageRequest<I>::handle_set_local_parent_snap(int r) { - dout(20) << ": r=" << r << dendl; - if (r < 0) { - derr << ": failed to set parent snapshot " << m_local_parent_spec.snap_id - << ": " << cpp_strerror(r) << dendl; - m_ret_val = r; - close_local_parent_image(); - return; - } - - clone_image(); -} - -template <typename I> -void CreateImageRequest<I>::clone_image() { - dout(20) << dendl; - librbd::ImageOptions opts; populate_image_options(&opts); using klass = CreateImageRequest<I>; - Context *ctx = create_context_callback<klass, &klass::handle_clone_image>(this); + Context *ctx = create_context_callback< + klass, &klass::handle_clone_image>(this); librbd::image::CloneRequest<I> *req = librbd::image::CloneRequest<I>::create( - m_local_parent_image_ctx, m_local_io_ctx, m_local_image_name, - m_local_image_id, opts, m_global_image_id, m_remote_mirror_uuid, - m_remote_image_ctx->op_work_queue, ctx); + m_local_parent_io_ctx, m_local_parent_spec.image_id, snap_name, CEPH_NOSNAP, + m_local_io_ctx, m_local_image_name, m_local_image_id, opts, + m_global_image_id, m_remote_mirror_uuid, m_remote_image_ctx->op_work_queue, + ctx); req->send(); } @@ -314,33 +241,11 @@ void CreateImageRequest<I>::handle_clone_image(int r) { dout(20) << ": r=" << r << dendl; if (r < 0) { derr << ": failed to clone image " << m_parent_pool_name << "/" - << m_local_parent_image_ctx->name << " to " + << m_remote_parent_spec.image_id << " to " << m_local_image_name << dendl; m_ret_val = r; } - close_local_parent_image(); -} - -template <typename I> -void CreateImageRequest<I>::close_local_parent_image() { - dout(20) << dendl; - Context *ctx = create_context_callback< - CreateImageRequest<I>, - &CreateImageRequest<I>::handle_close_local_parent_image>(this); - CloseImageRequest<I> *request = CloseImageRequest<I>::create( - &m_local_parent_image_ctx, ctx); - request->send(); -} - -template <typename I> -void CreateImageRequest<I>::handle_close_local_parent_image(int r) { - dout(20) << ": r=" << r << dendl; - if (r < 0) { - derr << ": error encountered closing local parent image: " - << cpp_strerror(r) << dendl; - } - close_remote_parent_image(); } diff --git a/src/tools/rbd_mirror/image_replayer/CreateImageRequest.h b/src/tools/rbd_mirror/image_replayer/CreateImageRequest.h index 0e6b8e10560..104a132f22b 100644 --- a/src/tools/rbd_mirror/image_replayer/CreateImageRequest.h +++ b/src/tools/rbd_mirror/image_replayer/CreateImageRequest.h @@ -64,19 +64,10 @@ private: * OPEN_REMOTE_PARENT * * * * * * * | * * * * * | | * * * v | * - * OPEN_LOCAL_PARENT * * * * * * * | * - * | * | * - * v * | * - * SET_LOCAL_PARENT_SNAP * | * - * | * * | * - * v * * | * - * CLONE_IMAGE * * | * - * | * * | * - * v v * | * - * CLOSE_LOCAL_PARENT * | * - * | * | * - * v * | * - * CLOSE_REMOTE_PARENT < * * * * * | * + * CLONE_IMAGE | * + * | | * + * v | * + * CLOSE_REMOTE_PARENT | * * | v * * \------------------------> <finish> < * * * @endverbatim @@ -96,7 +87,6 @@ private: librbd::ParentSpec m_remote_parent_spec; librados::IoCtx m_local_parent_io_ctx; - ImageCtxT *m_local_parent_image_ctx = nullptr; librbd::ParentSpec m_local_parent_spec; bufferlist m_out_bl; @@ -116,18 +106,9 @@ private: void open_remote_parent_image(); void handle_open_remote_parent_image(int r); - void open_local_parent_image(); - void handle_open_local_parent_image(int r); - - void set_local_parent_snap(); - void handle_set_local_parent_snap(int r); - void clone_image(); void handle_clone_image(int r); - void close_local_parent_image(); - void handle_close_local_parent_image(int r); - void close_remote_parent_image(); void handle_close_remote_parent_image(int r); |