From 1b826e132c596df530a6c4fb379de21ea4731421 Mon Sep 17 00:00:00 2001 From: Victor Denisov Date: Fri, 24 Jun 2016 16:19:46 -0700 Subject: [PATCH] librbd: Implement consistency group images operations Signed-off-by: Victor Denisov --- src/include/rbd/librbd.h | 40 +++ src/include/rbd/librbd.hpp | 21 ++ src/librbd/ImageCtx.h | 1 + src/librbd/image/RefreshRequest.cc | 5 +- src/librbd/image/RefreshRequest.h | 1 + src/librbd/internal.cc | 267 +++++++++++++++++- src/librbd/internal.h | 7 + src/librbd/librbd.cc | 179 ++++++++++++ .../librbd/image/test_mock_RefreshRequest.cc | 3 + src/test/librbd/mock/MockImageCtx.h | 3 +- src/test/librbd/test_ConsistencyGroups.cc | 28 ++ src/test/librbd/test_librbd.cc | 1 + src/tracing/librbd.tp | 88 ++++++ 13 files changed, 640 insertions(+), 4 deletions(-) diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h index c505a4b1be6..700e6d6b303 100644 --- a/src/include/rbd/librbd.h +++ b/src/include/rbd/librbd.h @@ -138,6 +138,26 @@ typedef struct { bool up; } rbd_mirror_image_status_t; +typedef enum { + GROUP_IMAGE_STATE_ATTACHED, + GROUP_IMAGE_STATE_INCOMPLETE +} rbd_group_image_state_t; + +typedef struct { + char *name; + int64_t pool; +} rbd_group_image_spec_t; + +typedef struct { + rbd_group_image_spec_t spec; + rbd_group_image_state_t state; +} rbd_group_image_status_t; + +typedef struct { + char *name; + int64_t pool; +} rbd_group_spec_t; + CEPH_RBD_API void rbd_version(int *major, int *minor, int *extra); /* image options */ @@ -697,6 +717,26 @@ CEPH_RBD_API int rbd_update_watch(rbd_image_t image, uint64_t *handle, CEPH_RBD_API int rbd_update_unwatch(rbd_image_t image, uint64_t handle); +CEPH_RBD_API int rbd_group_image_add( + rados_ioctx_t group_p, const char *group_name, + rados_ioctx_t image_p, const char *image_name); +CEPH_RBD_API int rbd_group_image_remove( + rados_ioctx_t group_p, const char *group_name, + rados_ioctx_t image_p, const char *image_name); +CEPH_RBD_API int rbd_group_image_list( + rados_ioctx_t group_p, const char *group_name, + rbd_group_image_status_t *images, + size_t *image_size); +CEPH_RBD_API int rbd_image_get_group(rados_ioctx_t image_p, + const char *image_name, + rbd_group_spec_t *group_spec); +CEPH_RBD_API void rbd_group_spec_cleanup(rbd_group_spec_t *group_spec); +CEPH_RBD_API void rbd_group_image_status_cleanup( + rbd_group_image_status_t *image + ); +CEPH_RBD_API void rbd_group_image_status_list_cleanup( + rbd_group_image_status_t *images, + size_t len); #ifdef __cplusplus } #endif diff --git a/src/include/rbd/librbd.hpp b/src/include/rbd/librbd.hpp index 57ccb98747d..4e9b7a6fbdd 100644 --- a/src/include/rbd/librbd.hpp +++ b/src/include/rbd/librbd.hpp @@ -71,6 +71,19 @@ namespace librbd { bool up; } mirror_image_status_t; + typedef rbd_group_image_state_t group_image_state_t; + + typedef struct { + std::string name; + int64_t pool; + group_image_state_t state; + } group_image_status_t; + + typedef struct { + std::string name; + int64_t pool; + } group_spec_t; + typedef rbd_image_info_t image_info_t; class CEPH_RBD_API ProgressContext @@ -153,6 +166,13 @@ public: int group_remove(IoCtx& io_ctx, const char *group_name); int group_list(IoCtx& io_ctx, std::vector& names); + int group_image_add(IoCtx& io_ctx, const char *group_name, + IoCtx& image_io_ctx, const char *image_name); + int group_image_remove(IoCtx& io_ctx, const char *group_name, + IoCtx& image_io_ctx, const char *image_name); + int group_image_list(IoCtx& io_ctx, const char *group_name, + std::vector& images); + private: /* We don't allow assignment or copying */ RBD(const RBD& rhs); @@ -207,6 +227,7 @@ public: std::string *parent_snapname); int old_format(uint8_t *old); int size(uint64_t *size); + int get_group(group_spec_t *group_spec); int features(uint64_t *features); int update_features(uint64_t features, bool enabled); int overlap(uint64_t *overlap); diff --git a/src/librbd/ImageCtx.h b/src/librbd/ImageCtx.h index 51d7a94af89..d7e6280bfe6 100644 --- a/src/librbd/ImageCtx.h +++ b/src/librbd/ImageCtx.h @@ -119,6 +119,7 @@ namespace librbd { std::string id; // only used for new-format images parent_info parent_md; ImageCtx *parent; + cls::rbd::GroupSpec group_spec; uint64_t stripe_unit, stripe_count; uint64_t flags; diff --git a/src/librbd/image/RefreshRequest.cc b/src/librbd/image/RefreshRequest.cc index fdab92b6027..dc23ca63b0b 100644 --- a/src/librbd/image/RefreshRequest.cc +++ b/src/librbd/image/RefreshRequest.cc @@ -249,7 +249,8 @@ Context *RefreshRequest::handle_v2_get_mutable_metadata(int *result) { &m_lockers, &m_exclusive_locked, &m_lock_tag, &m_snapc, - &m_parent_md); + &m_parent_md, + &m_group_spec); } if (*result < 0) { lderr(cct) << "failed to retrieve mutable metadata: " @@ -865,6 +866,8 @@ void RefreshRequest::apply() { m_image_ctx.parent_md = m_parent_md; } + m_image_ctx.group_spec = m_group_spec; + for (size_t i = 0; i < m_snapc.snaps.size(); ++i) { std::vector::const_iterator it = std::find( m_image_ctx.snaps.begin(), m_image_ctx.snaps.end(), diff --git a/src/librbd/image/RefreshRequest.h b/src/librbd/image/RefreshRequest.h index 79b5d9e816d..33e6d0bcca0 100644 --- a/src/librbd/image/RefreshRequest.h +++ b/src/librbd/image/RefreshRequest.h @@ -116,6 +116,7 @@ private: uint64_t m_flags; std::string m_object_prefix; parent_info m_parent_md; + cls::rbd::GroupSpec m_group_spec; ::SnapContext m_snapc; std::vector m_snap_names; diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index e1ad623787d..c97643fe200 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -16,6 +16,7 @@ #include "include/stringify.h" #include "cls/rbd/cls_rbd.h" +#include "cls/rbd/cls_rbd_types.h" #include "cls/rbd/cls_rbd_client.h" #include "cls/journal/cls_journal_types.h" #include "cls/journal/cls_journal_client.h" @@ -2222,6 +2223,15 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force, return -EBUSY; } + cls::rbd::GroupSpec s; + r = cls_client::image_get_group(&io_ctx, header_oid, s); + if (s.is_valid()) { + lderr(cct) << "image is in a consistency group - not removing" << dendl; + ictx->owner_lock.put_read(); + ictx->state->close(); + return -EMLINK; + } + trim_image(ictx, 0, prog_ctx); ictx->parent_lock.get_read(); @@ -3938,9 +3948,27 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force, CephContext *cct((CephContext *)io_ctx.cct()); ldout(cct, 20) << "group_remove " << &io_ctx << " " << group_name << dendl; + std::vector images; + int r = group_image_list(io_ctx, group_name, images); + if (r < 0 && r != -ENOENT) { + lderr(cct) << "error listing group images" << dendl; + return r; + } + + for (auto i : images) { + librados::Rados rados(io_ctx); + IoCtx image_ioctx; + rados.ioctx_create2(i.pool, image_ioctx); + r = group_image_remove(io_ctx, group_name, image_ioctx, i.name.c_str()); + if (r < 0 && r != -ENOENT) { + lderr(cct) << "error removing image from a group" << dendl; + return r; + } + } + std::string group_id; - int r = cls_client::dir_get_id(&io_ctx, RBD_GROUP_DIRECTORY, - std::string(group_name), &group_id); + r = cls_client::dir_get_id(&io_ctx, RBD_GROUP_DIRECTORY, + std::string(group_name), &group_id); if (r < 0 && r != -ENOENT) { lderr(cct) << "error getting id of group" << dendl; return r; @@ -3991,4 +4019,239 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force, return 0; } + + int group_image_add(librados::IoCtx& group_ioctx, const char *group_name, + librados::IoCtx& image_ioctx, const char *image_name) + { + CephContext *cct = (CephContext *)group_ioctx.cct(); + ldout(cct, 20) << "group_image_add " << &group_ioctx + << " group name " << group_name << " image " + << &image_ioctx << " name " << image_name << dendl; + + string group_id; + + int r = cls_client::dir_get_id(&group_ioctx, RBD_GROUP_DIRECTORY, group_name, &group_id); + if (r < 0) { + lderr(cct) << "error reading consistency group id object: " + << cpp_strerror(r) + << dendl; + return r; + } + string group_header_oid = util::group_header_name(group_id); + + + ldout(cct, 20) << "adding image to group name " << group_name + << " group id " << group_header_oid << dendl; + + string image_id; + + r = cls_client::dir_get_id(&image_ioctx, RBD_DIRECTORY, image_name, &image_id); + if (r < 0) { + lderr(cct) << "error reading image id object: " + << cpp_strerror(-r) << dendl; + return r; + } + + string image_header_oid = util::header_name(image_id); + + ldout(cct, 20) << "adding image " << image_name + << " image id " << image_header_oid << dendl; + + cls::rbd::GroupImageStatus incomplete_st(image_id, image_ioctx.get_id(), + cls::rbd::GROUP_IMAGE_LINK_STATE_INCOMPLETE); + cls::rbd::GroupImageStatus attached_st(image_id, image_ioctx.get_id(), + cls::rbd::GROUP_IMAGE_LINK_STATE_ATTACHED); + + r = cls_client::group_image_set(&group_ioctx, group_header_oid, + incomplete_st); + + cls::rbd::GroupSpec group_spec(group_id, group_ioctx.get_id()); + + if (r < 0) { + lderr(cct) << "error adding image reference to consistency group: " + << cpp_strerror(-r) << dendl; + return r; + } + + r = cls_client::image_add_group(&image_ioctx, image_header_oid, + group_spec); + if (r < 0) { + lderr(cct) << "error adding group reference to image: " + << cpp_strerror(-r) << dendl; + cls::rbd::GroupImageSpec spec(image_id, image_ioctx.get_id()); + cls_client::group_image_remove(&group_ioctx, group_header_oid, spec); + // Ignore errors in the clean up procedure. + return r; + } + + r = cls_client::group_image_set(&group_ioctx, group_header_oid, + attached_st); + + return r; + } + + int group_image_remove(librados::IoCtx& group_ioctx, const char *group_name, + librados::IoCtx& image_ioctx, const char *image_name) + { + CephContext *cct = (CephContext *)group_ioctx.cct(); + ldout(cct, 20) << "group_remove_image " << &group_ioctx + << " group name " << group_name << " image " + << &image_ioctx << " name " << image_name << dendl; + + string group_id; + + int r = cls_client::dir_get_id(&group_ioctx, RBD_GROUP_DIRECTORY, group_name, &group_id); + if (r < 0) { + lderr(cct) << "error reading consistency group id object: " + << cpp_strerror(r) + << dendl; + return r; + } + string group_header_oid = util::group_header_name(group_id); + + ldout(cct, 20) << "adding image to group name " << group_name + << " group id " << group_header_oid << dendl; + + string image_id; + r = cls_client::dir_get_id(&image_ioctx, RBD_DIRECTORY, image_name, &image_id); + if (r < 0) { + lderr(cct) << "error reading image id object: " + << cpp_strerror(-r) << dendl; + return r; + } + + string image_header_oid = util::header_name(image_id); + + ldout(cct, 20) << "removing image " << image_name + << " image id " << image_header_oid << dendl; + + cls::rbd::GroupSpec group_spec(group_id, group_ioctx.get_id()); + + cls::rbd::GroupImageStatus incomplete_st(image_id, image_ioctx.get_id(), + cls::rbd::GROUP_IMAGE_LINK_STATE_INCOMPLETE); + + cls::rbd::GroupImageSpec spec(image_id, image_ioctx.get_id()); + + r = cls_client::group_image_set(&group_ioctx, group_header_oid, + incomplete_st); + + if (r < 0) { + lderr(cct) << "couldn't put image into removing state: " + << cpp_strerror(-r) << dendl; + return r; + } + + r = cls_client::image_remove_group(&image_ioctx, image_header_oid, + group_spec); + if ((r < 0) && (r != -ENOENT)) { + lderr(cct) << "couldn't remove group reference from image" + << cpp_strerror(-r) << dendl; + return r; + } + + r = cls_client::group_image_remove(&group_ioctx, group_header_oid, spec); + if (r < 0) { + lderr(cct) << "couldn't remove image from group" + << cpp_strerror(-r) << dendl; + return r; + } + + return 0; + } + + int group_image_list(librados::IoCtx& group_ioctx, + const char *group_name, + std::vector& images) + { + CephContext *cct = (CephContext *)group_ioctx.cct(); + ldout(cct, 20) << "group_image_list " << &group_ioctx + << " group name " << group_name << dendl; + + string group_id; + + int r = cls_client::dir_get_id(&group_ioctx, RBD_GROUP_DIRECTORY, + group_name, &group_id); + if (r < 0) { + lderr(cct) << "error reading consistency group id object: " + << cpp_strerror(r) + << dendl; + return r; + } + string group_header_oid = util::group_header_name(group_id); + + ldout(cct, 20) << "listing images in group name " + << group_name << " group id " << group_header_oid << dendl; + + std::vector image_ids; + + const int max_read = 1024; + do { + std::vector image_ids_page; + cls::rbd::GroupImageSpec start_last; + + r = cls_client::group_image_list(&group_ioctx, group_header_oid, + start_last, max_read, image_ids_page); + + if (r < 0) { + lderr(cct) << "error reading image list from consistency group: " + << cpp_strerror(-r) << dendl; + return r; + } + image_ids.insert(image_ids.end(), + image_ids_page.begin(), image_ids_page.end()); + + if (image_ids_page.size() > 0) + start_last = image_ids_page.rbegin()->spec; + + r = image_ids_page.size(); + } while (r == max_read); + + for (auto i : image_ids) { + librados::Rados rados(group_ioctx); + IoCtx ioctx; + rados.ioctx_create2(i.spec.pool_id, ioctx); + std::string image_name; + r = cls_client::dir_get_name(&ioctx, RBD_DIRECTORY, + i.spec.image_id, &image_name); + if (r < 0) { + return r; + } + + images.push_back( + group_image_status_t { + image_name, + i.spec.pool_id, + static_cast(i.state)}); + } + + return 0; + } + + int image_get_group(ImageCtx *ictx, group_spec_t *group_spec) + { + int r = ictx->state->refresh_if_required(); + if (r < 0) + return r; + + if (-1 != ictx->group_spec.pool_id) { + librados::Rados rados(ictx->md_ctx); + IoCtx ioctx; + rados.ioctx_create2(ictx->group_spec.pool_id, ioctx); + + std::string group_name; + r = cls_client::dir_get_name(&ioctx, RBD_GROUP_DIRECTORY, + ictx->group_spec.group_id, &group_name); + if (r < 0) + return r; + group_spec->pool = ictx->group_spec.pool_id; + group_spec->name = group_name; + } else { + group_spec->pool = -1; + group_spec->name = ""; + } + + return 0; + } + + } diff --git a/src/librbd/internal.h b/src/librbd/internal.h index e73d1d01785..472f12c4628 100644 --- a/src/librbd/internal.h +++ b/src/librbd/internal.h @@ -226,6 +226,13 @@ namespace librbd { int group_create(librados::IoCtx& io_ctx, const char *imgname); int group_remove(librados::IoCtx& io_ctx, const char *group_name); int group_list(librados::IoCtx& io_ctx, std::vector& names); + int group_image_add(librados::IoCtx& group_ioctx, const char *group_name, + librados::IoCtx& image_ioctx, const char *image_name); + int group_image_remove(librados::IoCtx& group_ioctx, const char *group_name, + librados::IoCtx& image_ioctx, const char *image_name); + int group_image_list(librados::IoCtx& group_ioctx, const char *group_name, + std::vector& images); + int image_get_group(ImageCtx *ictx, group_spec_t *group_spec); } #endif diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index 094beaa4d9b..9d91a8a56e0 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -141,6 +141,19 @@ struct C_UpdateWatchCB : public librbd::UpdateWatchCtx { } }; +void group_image_status_cpp_to_c(const librbd::group_image_status_t &cpp_status, + rbd_group_image_status_t *c_status) { + c_status->spec.name = strdup(cpp_status.name.c_str()); + c_status->spec.pool = cpp_status.pool; + c_status->state = cpp_status.state; +} + +void group_spec_cpp_to_c(const librbd::group_spec_t &cpp_spec, + rbd_group_spec_t *c_spec) { + c_spec->name = strdup(cpp_spec.name.c_str()); + c_spec->pool = cpp_spec.pool; +} + void mirror_image_info_cpp_to_c(const librbd::mirror_image_info_t &cpp_info, rbd_mirror_image_info_t *c_info) { c_info->global_id = strdup(cpp_info.global_id.c_str()); @@ -483,6 +496,42 @@ namespace librbd { return r; } + int RBD::group_image_add(IoCtx& group_ioctx, const char *group_name, + IoCtx& image_ioctx, const char *image_name) + { + TracepointProvider::initialize(get_cct(group_ioctx)); + tracepoint(librbd, group_image_add_enter, group_ioctx.get_pool_name().c_str(), + group_ioctx.get_id(), group_name, image_ioctx.get_pool_name().c_str(), + image_ioctx.get_id(), image_name); + int r = librbd::group_image_add(group_ioctx, group_name, image_ioctx, image_name); + tracepoint(librbd, group_image_add_exit, r); + return r; + } + + int RBD::group_image_remove(IoCtx& group_ioctx, const char *group_name, + IoCtx& image_ioctx, const char *image_name) + { + TracepointProvider::initialize(get_cct(group_ioctx)); + tracepoint(librbd, group_image_remove_enter, group_ioctx.get_pool_name().c_str(), + group_ioctx.get_id(), group_name, image_ioctx.get_pool_name().c_str(), + image_ioctx.get_id(), image_name); + int r = librbd::group_image_remove(group_ioctx, group_name, image_ioctx, image_name); + tracepoint(librbd, group_image_remove_exit, r); + return r; + } + + int RBD::group_image_list(IoCtx& group_ioctx, const char *group_name, + std::vector& images) + { + TracepointProvider::initialize(get_cct(group_ioctx)); + tracepoint(librbd, group_image_list_enter, group_ioctx.get_pool_name().c_str(), + group_ioctx.get_id(), group_name); + int r = librbd::group_image_list(group_ioctx, group_name, images); + tracepoint(librbd, group_image_list_exit, r); + return r; + } + + RBD::AioCompletion::AioCompletion(void *cb_arg, callback_t complete_cb) { pc = reinterpret_cast(librbd::AioCompletion::create( @@ -678,6 +727,15 @@ namespace librbd { return r; } + int Image::get_group(group_spec_t *group_spec) + { + ImageCtx *ictx = (ImageCtx *)ctx; + tracepoint(librbd, image_get_group_enter, ictx->name.c_str()); + int r = librbd::image_get_group(ictx, group_spec); + tracepoint(librbd, image_get_group_exit, r); + return r; + } + int Image::features(uint64_t *features) { ImageCtx *ictx = (ImageCtx *)ctx; @@ -3026,3 +3084,124 @@ extern "C" int rbd_group_list(rados_ioctx_t p, char *names, size_t *size) tracepoint(librbd, group_list_exit, (int)expected_size); return (int)expected_size; } + +extern "C" int rbd_group_image_add( + rados_ioctx_t group_p, const char *group_name, + rados_ioctx_t image_p, const char *image_name) +{ + librados::IoCtx group_ioctx; + librados::IoCtx image_ioctx; + + librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx); + librados::IoCtx::from_rados_ioctx_t(image_p, image_ioctx); + + TracepointProvider::initialize(get_cct(group_ioctx)); + tracepoint(librbd, group_image_add_enter, group_ioctx.get_pool_name().c_str(), + group_ioctx.get_id(), group_name, image_ioctx.get_pool_name().c_str(), + image_ioctx.get_id(), image_name); + + int r = librbd::group_image_add(group_ioctx, group_name, image_ioctx, image_name); + + tracepoint(librbd, group_image_add_exit, r); + return r; +} + +extern "C" int rbd_group_image_remove( + rados_ioctx_t group_p, const char *group_name, + rados_ioctx_t image_p, const char *image_name) +{ + librados::IoCtx group_ioctx; + librados::IoCtx image_ioctx; + + librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx); + librados::IoCtx::from_rados_ioctx_t(image_p, image_ioctx); + + TracepointProvider::initialize(get_cct(group_ioctx)); + tracepoint(librbd, group_image_remove_enter, group_ioctx.get_pool_name().c_str(), + group_ioctx.get_id(), group_name, image_ioctx.get_pool_name().c_str(), + image_ioctx.get_id(), image_name); + + int r = librbd::group_image_remove(group_ioctx, group_name, image_ioctx, image_name); + + tracepoint(librbd, group_image_remove_exit, r); + return r; +} + +extern "C" int rbd_group_image_list(rados_ioctx_t group_p, + const char *group_name, + rbd_group_image_status_t *images, + size_t *image_size) +{ + librados::IoCtx group_ioctx; + librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx); + + TracepointProvider::initialize(get_cct(group_ioctx)); + tracepoint(librbd, group_image_list_enter, group_ioctx.get_pool_name().c_str(), + group_ioctx.get_id(), group_name); + + std::vector cpp_images; + int r = librbd::group_image_list(group_ioctx, group_name, cpp_images); + + if (r == -ENOENT) { + tracepoint(librbd, group_image_list_exit, 0); + return 0; + } + + if (r < 0) { + tracepoint(librbd, group_image_list_exit, r); + return r; + } + + if (*image_size < cpp_images.size()) { + tracepoint(librbd, group_image_list_exit, -ERANGE); + return -ERANGE; + } + + for (size_t i = 0; i < cpp_images.size(); ++i) { + group_image_status_cpp_to_c(cpp_images[i], &images[i]); + } + + tracepoint(librbd, group_image_list_exit, r); + return r; +} + +extern "C" int rbd_image_get_group(rados_ioctx_t image_p, + const char *image_name, + rbd_group_spec_t *c_group_spec) +{ + librados::IoCtx io_ctx; + librados::IoCtx::from_rados_ioctx_t(image_p, io_ctx); + + librbd::ImageCtx *ictx = new librbd::ImageCtx(image_name, "", "", io_ctx, false); + int r = ictx->state->open(); + if (r < 0) { + delete ictx; + tracepoint(librbd, open_image_exit, r); + return r; + } + + tracepoint(librbd, image_get_group_enter, ictx->name.c_str()); + librbd::group_spec_t group_spec; + r = librbd::image_get_group(ictx, &group_spec); + group_spec_cpp_to_c(group_spec, c_group_spec); + tracepoint(librbd, image_get_group_exit, r); + ictx->state->close(); + return r; +} + +extern "C" void rbd_group_spec_cleanup(rbd_group_spec_t *group_spec) { + free(group_spec->name); +} + +extern "C" void rbd_group_image_status_cleanup( + rbd_group_image_status_t *image) { + free(image->spec.name); +} + +extern "C" void rbd_group_image_status_list_cleanup( + rbd_group_image_status_t *images, + size_t len) { + for (size_t i = 0; i < len; ++i) { + rbd_group_image_status_cleanup(&images[i]); + } +} diff --git a/src/test/librbd/image/test_mock_RefreshRequest.cc b/src/test/librbd/image/test_mock_RefreshRequest.cc index b24033d3bbe..091a7fc4191 100644 --- a/src/test/librbd/image/test_mock_RefreshRequest.cc +++ b/src/test/librbd/image/test_mock_RefreshRequest.cc @@ -150,6 +150,9 @@ public: EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_parent"), _, _, _)) .WillOnce(DoDefault()); + EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), + exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("image_get_group"), _, _, _)) + .WillOnce(DoDefault()); EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), exec(mock_image_ctx.header_oid, _, StrEq("lock"), StrEq("get_info"), _, _, _)) .WillOnce(DoDefault()); diff --git a/src/test/librbd/mock/MockImageCtx.h b/src/test/librbd/mock/MockImageCtx.h index 2818eb566da..428d1b9d597 100644 --- a/src/test/librbd/mock/MockImageCtx.h +++ b/src/test/librbd/mock/MockImageCtx.h @@ -35,7 +35,6 @@ struct MockImageCtx { assert(s_instance != nullptr); return s_instance; } - MockImageCtx(librbd::ImageCtx &image_ctx) : image_ctx(&image_ctx), cct(image_ctx.cct), @@ -73,6 +72,7 @@ struct MockImageCtx { name(image_ctx.name), parent_md(image_ctx.parent_md), format_string(image_ctx.format_string), + group_spec(image_ctx.group_spec), layout(image_ctx.layout), aio_work_queue(new MockAioImageRequestWQ()), op_work_queue(new MockContextWQ()), @@ -222,6 +222,7 @@ struct MockImageCtx { std::string name; parent_info parent_md; char *format_string; + cls::rbd::GroupSpec group_spec; file_layout_t layout; diff --git a/src/test/librbd/test_ConsistencyGroups.cc b/src/test/librbd/test_ConsistencyGroups.cc index a6a1c24193c..71c01a1d8d9 100644 --- a/src/test/librbd/test_ConsistencyGroups.cc +++ b/src/test/librbd/test_ConsistencyGroups.cc @@ -61,3 +61,31 @@ TEST_F(TestLibCG, group_create) ASSERT_EQ(0, rbd.group_list(ioctx, groups)); ASSERT_EQ(0U, groups.size()); } + +TEST_F(TestLibCG, add_image) +{ + librados::IoCtx ioctx; + ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx)); + + const char *group_name = "mycg"; + const char *image_name = "myimage"; + librbd::RBD rbd; + ASSERT_EQ(0, rbd.group_create(ioctx, group_name)); + int order = 14; + ASSERT_EQ(0, rbd.create2(ioctx, image_name, 65535, + RBD_FEATURE_LAYERING, &order)); // Specified features make image of new format. + + ASSERT_EQ(0, rbd.group_image_add(ioctx, group_name, ioctx, image_name)); + + vector images; + ASSERT_EQ(0, rbd.group_image_list(ioctx, group_name, images)); + ASSERT_EQ(1U, images.size()); + ASSERT_EQ("myimage", images[0].name); + ASSERT_EQ(ioctx.get_id(), images[0].pool); + + ASSERT_EQ(0, rbd.group_image_remove(ioctx, group_name, ioctx, image_name)); + + images.clear(); + ASSERT_EQ(0, rbd.group_image_list(ioctx, group_name, images)); + ASSERT_EQ(0U, images.size()); +} diff --git a/src/test/librbd/test_librbd.cc b/src/test/librbd/test_librbd.cc index 8391c7ad3d4..72b131409e2 100644 --- a/src/test/librbd/test_librbd.cc +++ b/src/test/librbd/test_librbd.cc @@ -604,6 +604,7 @@ int test_ls(rados_ioctx_t io_ctx, size_t num_expected, ...) if (it != image_names.end()) { printf("found %s\n", expected); image_names.erase(it); + printf("erased %s\n", expected); } else { ADD_FAILURE() << "Unable to find image " << expected; va_end(ap); diff --git a/src/tracing/librbd.tp b/src/tracing/librbd.tp index 45330a3d2ee..0726f86cff5 100644 --- a/src/tracing/librbd.tp +++ b/src/tracing/librbd.tp @@ -1965,3 +1965,91 @@ TRACEPOINT_EVENT(librbd, update_unwatch_exit, ctf_integer(int, retval, retval) ) ) + +TRACEPOINT_EVENT(librbd, group_image_add_enter, + TP_ARGS( + const char*, pool_name, + int64_t, id, + const char*, group_name, + const char*, image_pool_name, + int64_t, image_id, + const char*, image_name), + TP_FIELDS( + ctf_string(pool_name, pool_name) + ctf_integer(int64_t, id, id) + ctf_string(group_name, group_name) + ctf_string(image_pool_name, image_pool_name) + ctf_integer(int64_t, image_id, image_id) + ctf_string(image_name, image_name) + ) +) + +TRACEPOINT_EVENT(librbd, group_image_add_exit, + TP_ARGS( + int, retval), + TP_FIELDS( + ctf_integer(int, retval, retval) + ) +) + +TRACEPOINT_EVENT(librbd, group_image_remove_enter, + TP_ARGS( + const char*, pool_name, + int64_t, id, + const char*, group_name, + const char*, image_pool_name, + int64_t, image_id, + const char*, image_name), + TP_FIELDS( + ctf_string(pool_name, pool_name) + ctf_integer(int64_t, id, id) + ctf_string(group_name, group_name) + ctf_string(image_pool_name, image_pool_name) + ctf_integer(int64_t, image_id, image_id) + ctf_string(image_name, image_name) + ) +) + +TRACEPOINT_EVENT(librbd, group_image_remove_exit, + TP_ARGS( + int, retval), + TP_FIELDS( + ctf_integer(int, retval, retval) + ) +) + +TRACEPOINT_EVENT(librbd, group_image_list_enter, + TP_ARGS( + const char*, pool_name, + int64_t, id, + const char*, group_name), + TP_FIELDS( + ctf_string(pool_name, pool_name) + ctf_integer(int64_t, id, id) + ctf_string(group_name, group_name) + ) +) + +TRACEPOINT_EVENT(librbd, group_image_list_exit, + TP_ARGS( + int, retval), + TP_FIELDS( + ctf_integer(int, retval, retval) + ) +) + +TRACEPOINT_EVENT(librbd, image_get_group_enter, + TP_ARGS( + const char*, image_name), + TP_FIELDS( + ctf_string(image_name, image_name) + ) +) + +TRACEPOINT_EVENT(librbd, image_get_group_exit, + TP_ARGS( + int, retval), + TP_FIELDS( + ctf_integer(int, retval, retval) + ) +) -- 2.39.5