summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJason Dillaman <dillaman@redhat.com>2018-04-17 22:22:06 +0200
committerJason Dillaman <dillaman@redhat.com>2018-08-15 00:29:45 +0200
commitb498aa0380b9f6f6401fe360b44b7b55f14aa771 (patch)
tree82ce6052c665485ebeeaf9e3f1f35a97bc983819 /src
parentlibrbd: normalize clone state machine method names and debug logs (diff)
downloadceph-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.cc29
-rw-r--r--src/librbd/image/CloneRequest.cc221
-rw-r--r--src/librbd/image/CloneRequest.h56
-rw-r--r--src/librbd/internal.cc76
-rw-r--r--src/librbd/internal.h7
-rw-r--r--src/librbd/librbd.cc7
-rw-r--r--src/test/librbd/image/test_mock_CloneRequest.cc207
-rw-r--r--src/test/rbd_mirror/image_replayer/test_mock_CreateImageRequest.cc177
-rw-r--r--src/test/rbd_mirror/test_ImageDeleter.cc7
-rw-r--r--src/tools/rbd_mirror/image_replayer/CreateImageRequest.cc113
-rw-r--r--src/tools/rbd_mirror/image_replayer/CreateImageRequest.h27
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);