diff options
author | Jason Dillaman <dillaman@redhat.com> | 2017-02-03 19:37:43 +0100 |
---|---|---|
committer | Jason Dillaman <dillaman@redhat.com> | 2017-03-08 18:02:27 +0100 |
commit | 79627df0713969a4ba755767248d94890b429e49 (patch) | |
tree | 899ad64922e2f6867775847b77ba4cd5196b9885 /src | |
parent | librbd: additional asynchronous mirror state machines (diff) | |
download | ceph-79627df0713969a4ba755767248d94890b429e49.tar.xz ceph-79627df0713969a4ba755767248d94890b429e49.zip |
librbd: add aio_mirror_image_* API methods
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/include/rbd/librbd.h | 12 | ||||
-rw-r--r-- | src/include/rbd/librbd.hpp | 6 | ||||
-rw-r--r-- | src/librbd/api/Mirror.cc | 185 | ||||
-rw-r--r-- | src/librbd/api/Mirror.h | 9 | ||||
-rw-r--r-- | src/librbd/io/AioCompletion.cc | 1 | ||||
-rw-r--r-- | src/librbd/io/AioCompletion.h | 1 | ||||
-rw-r--r-- | src/librbd/io/Types.h | 1 | ||||
-rw-r--r-- | src/librbd/librbd.cc | 205 | ||||
-rw-r--r-- | src/test/librbd/test_mirroring.cc | 160 |
9 files changed, 480 insertions, 100 deletions
diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h index 460c1d2debf..78168b62fce 100644 --- a/src/include/rbd/librbd.h +++ b/src/include/rbd/librbd.h @@ -735,6 +735,18 @@ CEPH_RBD_API int rbd_mirror_image_get_info(rbd_image_t image, CEPH_RBD_API int rbd_mirror_image_get_status(rbd_image_t image, rbd_mirror_image_status_t *mirror_image_status, size_t status_size); +CEPH_RBD_API int rbd_aio_mirror_image_promote(rbd_image_t image, bool force, + rbd_completion_t c); +CEPH_RBD_API int rbd_aio_mirror_image_demote(rbd_image_t image, + rbd_completion_t c); +CEPH_RBD_API int rbd_aio_mirror_image_get_info(rbd_image_t image, + rbd_mirror_image_info_t *mirror_image_info, + size_t info_size, + rbd_completion_t c); +CEPH_RBD_API int rbd_aio_mirror_image_get_status(rbd_image_t image, + rbd_mirror_image_status_t *mirror_image_status, + size_t status_size, + rbd_completion_t c); // RBD consistency groups support functions CEPH_RBD_API int rbd_group_create(rados_ioctx_t p, const char *name); diff --git a/src/include/rbd/librbd.hpp b/src/include/rbd/librbd.hpp index 44f741fd624..3c667d2e871 100644 --- a/src/include/rbd/librbd.hpp +++ b/src/include/rbd/librbd.hpp @@ -408,6 +408,12 @@ public: size_t info_size); int mirror_image_get_status(mirror_image_status_t *mirror_image_status, size_t status_size); + int aio_mirror_image_promote(bool force, RBD::AioCompletion *c); + int aio_mirror_image_demote(RBD::AioCompletion *c); + int aio_mirror_image_get_info(mirror_image_info_t *mirror_image_info, + size_t info_size, RBD::AioCompletion *c); + int aio_mirror_image_get_status(mirror_image_status_t *mirror_image_status, + size_t status_size, RBD::AioCompletion *c); int update_watch(UpdateWatchCtx *ctx, uint64_t *handle); int update_unwatch(uint64_t handle); diff --git a/src/librbd/api/Mirror.cc b/src/librbd/api/Mirror.cc index ca294025128..96b8421c98c 100644 --- a/src/librbd/api/Mirror.cc +++ b/src/librbd/api/Mirror.cc @@ -10,11 +10,15 @@ #include "librbd/ImageCtx.h" #include "librbd/ImageState.h" #include "librbd/Journal.h" +#include "librbd/Utils.h" #include "librbd/api/Image.h" #include "librbd/mirror/DemoteRequest.h" #include "librbd/mirror/DisableRequest.h" #include "librbd/mirror/EnableRequest.h" +#include "librbd/mirror/GetInfoRequest.h" +#include "librbd/mirror/GetStatusRequest.h" #include "librbd/mirror/PromoteRequest.h" +#include "librbd/mirror/Types.h" #include "librbd/MirroringWatcher.h" #include <boost/scope_exit.hpp> @@ -73,6 +77,62 @@ int list_mirror_images(librados::IoCtx& io_ctx, return 0; } +struct C_ImageGetInfo : public Context { + mirror_image_info_t *mirror_image_info; + Context *on_finish; + + cls::rbd::MirrorImage mirror_image; + mirror::PromotionState promotion_state; + + C_ImageGetInfo(mirror_image_info_t *mirror_image_info, Context *on_finish) + : mirror_image_info(mirror_image_info), on_finish(on_finish) { + } + + void finish(int r) override { + if (r < 0) { + on_finish->complete(r); + return; + } + + mirror_image_info->global_id = mirror_image.global_image_id; + mirror_image_info->state = static_cast<rbd_mirror_image_state_t>( + mirror_image.state); + mirror_image_info->primary = ( + promotion_state == mirror::PROMOTION_STATE_PRIMARY); + on_finish->complete(0); + } +}; + +struct C_ImageGetStatus : public C_ImageGetInfo { + std::string image_name; + mirror_image_status_t *mirror_image_status; + + cls::rbd::MirrorImageStatus mirror_image_status_internal; + + C_ImageGetStatus(const std::string &image_name, + mirror_image_status_t *mirror_image_status, + Context *on_finish) + : C_ImageGetInfo(&mirror_image_status->info, on_finish), + image_name(image_name), mirror_image_status(mirror_image_status) { + } + + void finish(int r) override { + if (r < 0) { + on_finish->complete(r); + return; + } + + mirror_image_status->name = image_name; + mirror_image_status->state = static_cast<mirror_image_status_state_t>( + mirror_image_status_internal.state); + mirror_image_status->description = mirror_image_status_internal.description; + mirror_image_status->last_update = + mirror_image_status_internal.last_update.sec(); + mirror_image_status->up = mirror_image_status_internal.up; + C_ImageGetInfo::finish(0); + } +}; + } // anonymous namespace template <typename I> @@ -262,13 +322,9 @@ int Mirror<I>::image_disable(I *ictx, bool force) { template <typename I> int Mirror<I>::image_promote(I *ictx, bool force) { CephContext *cct = ictx->cct; - ldout(cct, 20) << "ictx=" << ictx << ", " - << "force=" << force << dendl; C_SaferCond ctx; - auto req = mirror::PromoteRequest<>::create(*ictx, force, &ctx); - req->send(); - + Mirror<I>::image_promote(ictx, force, &ctx); int r = ctx.wait(); if (r < 0) { lderr(cct) << "failed to promote image" << dendl; @@ -279,14 +335,21 @@ int Mirror<I>::image_promote(I *ictx, bool force) { } template <typename I> -int Mirror<I>::image_demote(I *ictx) { +void Mirror<I>::image_promote(I *ictx, bool force, Context *on_finish) { CephContext *cct = ictx->cct; - ldout(cct, 20) << "ictx=" << ictx << dendl; + ldout(cct, 20) << "ictx=" << ictx << ", " + << "force=" << force << dendl; - C_SaferCond ctx; - auto req = mirror::DemoteRequest<>::create(*ictx, &ctx); + auto req = mirror::PromoteRequest<>::create(*ictx, force, on_finish); req->send(); +} + +template <typename I> +int Mirror<I>::image_demote(I *ictx) { + CephContext *cct = ictx->cct; + C_SaferCond ctx; + Mirror<I>::image_demote(ictx, &ctx); int r = ctx.wait(); if (r < 0) { lderr(cct) << "failed to demote image" << dendl; @@ -297,6 +360,15 @@ int Mirror<I>::image_demote(I *ictx) { } template <typename I> +void Mirror<I>::image_demote(I *ictx, Context *on_finish) { + CephContext *cct = ictx->cct; + ldout(cct, 20) << "ictx=" << ictx << dendl; + + auto req = mirror::DemoteRequest<>::create(*ictx, on_finish); + req->send(); +} + +template <typename I> int Mirror<I>::image_resync(I *ictx) { CephContext *cct = ictx->cct; ldout(cct, 20) << "ictx=" << ictx << dendl; @@ -333,87 +405,62 @@ int Mirror<I>::image_resync(I *ictx) { } template <typename I> -int Mirror<I>::image_get_info(I *ictx, mirror_image_info_t *mirror_image_info, - size_t info_size) { +void Mirror<I>::image_get_info(I *ictx, mirror_image_info_t *mirror_image_info, + size_t info_size, Context *on_finish) { CephContext *cct = ictx->cct; ldout(cct, 20) << "ictx=" << ictx << dendl; if (info_size < sizeof(mirror_image_info_t)) { - return -ERANGE; - } - - int r = ictx->state->refresh_if_required(); - if (r < 0) { - return r; + on_finish->complete(-ERANGE); + return; } - cls::rbd::MirrorImage mirror_image_internal; - r = cls_client::mirror_image_get(&ictx->md_ctx, ictx->id, - &mirror_image_internal); - if (r < 0 && r != -ENOENT) { - lderr(cct) << "failed to retrieve mirroring state: " << cpp_strerror(r) - << dendl; - return r; - } + auto ctx = new C_ImageGetInfo(mirror_image_info, on_finish); + auto req = mirror::GetInfoRequest<I>::create(*ictx, &ctx->mirror_image, + &ctx->promotion_state, + ctx); + req->send(); +} - mirror_image_info->global_id = mirror_image_internal.global_image_id; - if (r == -ENOENT) { - mirror_image_info->state = RBD_MIRROR_IMAGE_DISABLED; - } else { - mirror_image_info->state = - static_cast<rbd_mirror_image_state_t>(mirror_image_internal.state); - } +template <typename I> +int Mirror<I>::image_get_info(I *ictx, mirror_image_info_t *mirror_image_info, + size_t info_size) { + C_SaferCond ctx; + image_get_info(ictx, mirror_image_info, info_size, &ctx); - if (mirror_image_info->state == RBD_MIRROR_IMAGE_ENABLED) { - r = Journal<I>::is_tag_owner(ictx, &mirror_image_info->primary); - if (r < 0) { - lderr(cct) << "failed to check tag ownership: " - << cpp_strerror(r) << dendl; - return r; - } - } else { - mirror_image_info->primary = false; + int r = ctx.wait(); + if (r < 0) { + return r; } - return 0; } template <typename I> -int Mirror<I>::image_get_status(I *ictx, mirror_image_status_t *status, - size_t status_size) { +void Mirror<I>::image_get_status(I *ictx, mirror_image_status_t *status, + size_t status_size, Context *on_finish) { CephContext *cct = ictx->cct; ldout(cct, 20) << "ictx=" << ictx << dendl; if (status_size < sizeof(mirror_image_status_t)) { - return -ERANGE; - } - - int r = ictx->state->refresh_if_required(); - if (r < 0) { - return r; + on_finish->complete(-ERANGE); + return; } - mirror_image_info_t info; - r = image_get_info(ictx, &info, sizeof(info)); - if (r < 0) { - return r; - } + auto ctx = new C_ImageGetStatus(ictx->name, status, on_finish); + auto req = mirror::GetStatusRequest<I>::create( + *ictx, &ctx->mirror_image_status_internal, &ctx->mirror_image, + &ctx->promotion_state, ctx); + req->send(); +} - cls::rbd::MirrorImageStatus - s(cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN, "status not found"); +template <typename I> +int Mirror<I>::image_get_status(I *ictx, mirror_image_status_t *status, + size_t status_size) { + C_SaferCond ctx; + image_get_status(ictx, status, status_size, &ctx); - r = cls_client::mirror_image_status_get(&ictx->md_ctx, info.global_id, &s); - if (r < 0 && r != -ENOENT) { - lderr(cct) << "failed to retrieve image mirror status: " - << cpp_strerror(r) << dendl; + int r = ctx.wait(); + if (r < 0) { return r; } - - *status = mirror_image_status_t{ - ictx->name, - info, - static_cast<mirror_image_status_state_t>(s.state), - s.description, - s.last_update.sec(), - s.up}; return 0; } diff --git a/src/librbd/api/Mirror.h b/src/librbd/api/Mirror.h index 7a8b9f3a287..08f7ec888b9 100644 --- a/src/librbd/api/Mirror.h +++ b/src/librbd/api/Mirror.h @@ -9,6 +9,8 @@ #include <string> #include <vector> +struct Context; + namespace librbd { struct ImageCtx; @@ -43,13 +45,20 @@ struct Mirror { static int image_enable(ImageCtxT *ictx, bool relax_same_pool_parent_check); static int image_disable(ImageCtxT *ictx, bool force); static int image_promote(ImageCtxT *ictx, bool force); + static void image_promote(ImageCtxT *ictx, bool force, Context *on_finish); static int image_demote(ImageCtxT *ictx); + static void image_demote(ImageCtxT *ictx, Context *on_finish); static int image_resync(ImageCtxT *ictx); static int image_get_info(ImageCtxT *ictx, mirror_image_info_t *mirror_image_info, size_t info_size); + static void image_get_info(ImageCtxT *ictx, + mirror_image_info_t *mirror_image_info, + size_t info_size, Context *on_finish); static int image_get_status(ImageCtxT *ictx, mirror_image_status_t *status, size_t status_size); + static void image_get_status(ImageCtxT *ictx, mirror_image_status_t *status, + size_t status_size, Context *on_finish); }; diff --git a/src/librbd/io/AioCompletion.cc b/src/librbd/io/AioCompletion.cc index ecc0445efda..7f83f4deab5 100644 --- a/src/librbd/io/AioCompletion.cc +++ b/src/librbd/io/AioCompletion.cc @@ -59,6 +59,7 @@ void AioCompletion::complete() { utime_t elapsed; elapsed = ceph_clock_now() - start_time; switch (aio_type) { + case AIO_TYPE_GENERIC: case AIO_TYPE_OPEN: case AIO_TYPE_CLOSE: break; diff --git a/src/librbd/io/AioCompletion.h b/src/librbd/io/AioCompletion.h index a484365d309..0433ac945ca 100644 --- a/src/librbd/io/AioCompletion.h +++ b/src/librbd/io/AioCompletion.h @@ -20,6 +20,7 @@ class CephContext; namespace librbd { namespace io { + /** * AioCompletion is the overall completion for a single * rbd I/O request. It may be composed of many AioObjectRequests, diff --git a/src/librbd/io/Types.h b/src/librbd/io/Types.h index 1c3f967c0c7..874e1dd3e28 100644 --- a/src/librbd/io/Types.h +++ b/src/librbd/io/Types.h @@ -13,6 +13,7 @@ namespace io { typedef enum { AIO_TYPE_NONE = 0, + AIO_TYPE_GENERIC, AIO_TYPE_OPEN, AIO_TYPE_CLOSE, AIO_TYPE_READ, diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index dea4ecb9478..92704f65138 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -77,28 +77,48 @@ librbd::io::AioCompletion* get_aio_completion(librbd::RBD::AioCompletion *comp) return reinterpret_cast<librbd::io::AioCompletion *>(comp->pc); } -struct C_OpenComplete : public Context { +struct C_AioCompletion : public Context { + CephContext *cct; + librbd::io::aio_type_t aio_type; + librbd::io::AioCompletion* aio_comp; + + C_AioCompletion(librbd::ImageCtx *ictx, librbd::io::aio_type_t aio_type, + librbd::io::AioCompletion* aio_comp) + : cct(ictx->cct), aio_type(aio_type), aio_comp(aio_comp) { + aio_comp->init_time(ictx, aio_type); + aio_comp->get(); + } + + void finish(int r) override { + ldout(cct, 20) << "C_AioComplete::finish: r=" << r << dendl; + if (r < 0) { + aio_comp->fail(r); + } else { + aio_comp->lock.Lock(); + aio_comp->complete(); + aio_comp->put_unlock(); + } + } +}; + +struct C_OpenComplete : public C_AioCompletion { librbd::ImageCtx *ictx; - librbd::io::AioCompletion* comp; void **ictxp; bool reopen; C_OpenComplete(librbd::ImageCtx *ictx, librbd::io::AioCompletion* comp, void **ictxp) - : ictx(ictx), comp(comp), ictxp(ictxp) { - comp->init_time(ictx, librbd::io::AIO_TYPE_OPEN); - comp->get(); + : C_AioCompletion(ictx, librbd::io::AIO_TYPE_OPEN, comp), + ictx(ictx), ictxp(ictxp) { } void finish(int r) override { ldout(ictx->cct, 20) << "C_OpenComplete::finish: r=" << r << dendl; if (r < 0) { *ictxp = nullptr; - comp->fail(r); } else { *ictxp = ictx; - comp->lock.Lock(); - comp->complete(); - comp->put_unlock(); } + + C_AioCompletion::finish(r); } }; @@ -121,26 +141,6 @@ struct C_OpenAfterCloseComplete : public Context { } }; -struct C_CloseComplete : public Context { - CephContext *cct; - librbd::io::AioCompletion* comp; - C_CloseComplete(librbd::ImageCtx *ictx, librbd::io::AioCompletion* comp) - : cct(ictx->cct), comp(comp) { - comp->init_time(ictx, librbd::io::AIO_TYPE_CLOSE); - comp->get(); - } - void finish(int r) override { - ldout(cct, 20) << "C_CloseComplete::finish: r=" << r << dendl; - if (r < 0) { - comp->fail(r); - } else { - comp->lock.Lock(); - comp->complete(); - comp->put_unlock(); - } - } -}; - struct C_UpdateWatchCB : public librbd::UpdateWatchCtx { rbd_update_callback_t watch_cb; void *arg; @@ -184,6 +184,50 @@ void mirror_image_status_cpp_to_c(const librbd::mirror_image_status_t &cpp_statu c_status->up = cpp_status.up; } +struct C_MirrorImageGetInfo : public Context { + rbd_mirror_image_info_t *mirror_image_info; + Context *on_finish; + + librbd::mirror_image_info_t cpp_mirror_image_info; + + C_MirrorImageGetInfo(rbd_mirror_image_info_t *mirror_image_info, + Context *on_finish) + : mirror_image_info(mirror_image_info), on_finish(on_finish) { + } + + void finish(int r) override { + if (r < 0) { + on_finish->complete(r); + return; + } + + mirror_image_info_cpp_to_c(cpp_mirror_image_info, mirror_image_info); + on_finish->complete(0); + } +}; + +struct C_MirrorImageGetStatus : public Context { + rbd_mirror_image_status_t *mirror_image_status; + Context *on_finish; + + librbd::mirror_image_status_t cpp_mirror_image_status; + + C_MirrorImageGetStatus(rbd_mirror_image_status_t *mirror_image_status, + Context *on_finish) + : mirror_image_status(mirror_image_status), on_finish(on_finish) { + } + + void finish(int r) override { + if (r < 0) { + on_finish->complete(r); + return; + } + + mirror_image_status_cpp_to_c(cpp_mirror_image_status, mirror_image_status); + on_finish->complete(0); + } +}; + } // anonymous namespace namespace librbd { @@ -680,7 +724,8 @@ namespace librbd { ImageCtx *ictx = (ImageCtx *)ctx; tracepoint(librbd, aio_close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), c->pc); - ictx->state->close(new C_CloseComplete(ictx, get_aio_completion(c))); + ictx->state->close(new C_AioCompletion(ictx, librbd::io::AIO_TYPE_CLOSE, + get_aio_completion(c))); ctx = NULL; tracepoint(librbd, aio_close_image_exit, 0); @@ -1582,6 +1627,44 @@ namespace librbd { status_size); } + int Image::aio_mirror_image_promote(bool force, RBD::AioCompletion *c) { + ImageCtx *ictx = (ImageCtx *)ctx; + librbd::api::Mirror<>::image_promote( + ictx, force, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC, + get_aio_completion(c))); + return 0; + } + + int Image::aio_mirror_image_demote(RBD::AioCompletion *c) { + ImageCtx *ictx = (ImageCtx *)ctx; + librbd::api::Mirror<>::image_demote( + ictx, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC, + get_aio_completion(c))); + return 0; + } + + int Image::aio_mirror_image_get_info(mirror_image_info_t *mirror_image_info, + size_t info_size, + RBD::AioCompletion *c) { + ImageCtx *ictx = (ImageCtx *)ctx; + librbd::api::Mirror<>::image_get_info( + ictx, mirror_image_info, info_size, + new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC, + get_aio_completion(c))); + return 0; + } + + int Image::aio_mirror_image_get_status(mirror_image_status_t *status, + size_t status_size, + RBD::AioCompletion *c) { + ImageCtx *ictx = (ImageCtx *)ctx; + librbd::api::Mirror<>::image_get_status( + ictx, status, status_size, + new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC, + get_aio_completion(c))); + return 0; + } + int Image::update_watch(UpdateWatchCtx *wctx, uint64_t *handle) { ImageCtx *ictx = (ImageCtx *)ctx; tracepoint(librbd, update_watch_enter, ictx, wctx); @@ -2198,7 +2281,8 @@ extern "C" int rbd_aio_close(rbd_image_t image, rbd_completion_t c) librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c; tracepoint(librbd, aio_close_image_enter, ictx, ictx->name.c_str(), ictx->id.c_str(), comp->pc); - ictx->state->close(new C_CloseComplete(ictx, get_aio_completion(comp))); + ictx->state->close(new C_AioCompletion(ictx, librbd::io::AIO_TYPE_CLOSE, + get_aio_completion(comp))); tracepoint(librbd, aio_close_image_exit, 0); return 0; } @@ -3340,6 +3424,65 @@ extern "C" int rbd_mirror_image_get_status(rbd_image_t image, return 0; } +extern "C" int rbd_aio_mirror_image_promote(rbd_image_t image, bool force, + rbd_completion_t c) { + librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; + librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c; + librbd::api::Mirror<>::image_promote( + ictx, force, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC, + get_aio_completion(comp))); + return 0; +} + +extern "C" int rbd_aio_mirror_image_demote(rbd_image_t image, + rbd_completion_t c) { + librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; + librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c; + librbd::api::Mirror<>::image_demote( + ictx, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC, + get_aio_completion(comp))); + return 0; +} + +extern "C" int rbd_aio_mirror_image_get_info(rbd_image_t image, + rbd_mirror_image_info_t *info, + size_t info_size, + rbd_completion_t c) { + librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; + librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c; + + if (sizeof(rbd_mirror_image_info_t) > info_size) { + return -ERANGE; + } + + auto ctx = new C_MirrorImageGetInfo( + info, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC, + get_aio_completion(comp))); + librbd::api::Mirror<>::image_get_info( + ictx, &ctx->cpp_mirror_image_info, sizeof(ctx->cpp_mirror_image_info), ctx); + return 0; +} + +extern "C" int rbd_aio_mirror_image_get_status(rbd_image_t image, + rbd_mirror_image_status_t *status, + size_t status_size, + rbd_completion_t c) { + librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; + librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c; + + if (sizeof(rbd_mirror_image_status_t) > status_size) { + return -ERANGE; + } + + auto ctx = new C_MirrorImageGetStatus( + status, new C_AioCompletion(ictx, librbd::io::AIO_TYPE_GENERIC, + get_aio_completion(comp))); + librbd::api::Mirror<>::image_get_status( + ictx, &ctx->cpp_mirror_image_status, sizeof(ctx->cpp_mirror_image_status), + ctx); + return 0; +} + extern "C" int rbd_update_watch(rbd_image_t image, uint64_t *handle, rbd_update_callback_t watch_cb, void *arg) { diff --git a/src/test/librbd/test_mirroring.cc b/src/test/librbd/test_mirroring.cc index 8e70f383b23..ec81ae4705a 100644 --- a/src/test/librbd/test_mirroring.cc +++ b/src/test/librbd/test_mirroring.cc @@ -681,3 +681,163 @@ TEST_F(TestMirroring, RemoveBootstrapped) ASSERT_TRUE(watcher.m_notified); ASSERT_EQ(0, image.close()); } + +TEST_F(TestMirroring, AioPromoteDemote) { + std::list<std::string> image_names; + for (size_t idx = 0; idx < 10; ++idx) { + image_names.push_back(get_temp_image_name()); + } + + ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_IMAGE)); + + // create mirror images + int order = 20; + std::list<librbd::Image> images; + for (auto &image_name : image_names) { + ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 2048, + RBD_FEATURE_EXCLUSIVE_LOCK | + RBD_FEATURE_JOURNALING, + &order)); + + images.emplace_back(); + ASSERT_EQ(0, m_rbd.open(m_ioctx, images.back(), image_name.c_str())); + ASSERT_EQ(0, images.back().mirror_image_enable()); + } + + // demote all images + std::list<librbd::RBD::AioCompletion *> aio_comps; + for (auto &image : images) { + aio_comps.push_back(new librbd::RBD::AioCompletion(nullptr, nullptr)); + ASSERT_EQ(0, image.aio_mirror_image_demote(aio_comps.back())); + } + for (auto aio_comp : aio_comps) { + ASSERT_EQ(0, aio_comp->wait_for_complete()); + ASSERT_EQ(1, aio_comp->is_complete()); + ASSERT_EQ(0, aio_comp->get_return_value()); + aio_comp->release(); + } + aio_comps.clear(); + + // verify demotions + for (auto &image : images) { + librbd::mirror_image_info_t mirror_image; + ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, + sizeof(mirror_image))); + ASSERT_FALSE(mirror_image.primary); + } + + // promote all images + for (auto &image : images) { + aio_comps.push_back(new librbd::RBD::AioCompletion(nullptr, nullptr)); + ASSERT_EQ(0, image.aio_mirror_image_promote(false, aio_comps.back())); + } + for (auto aio_comp : aio_comps) { + ASSERT_EQ(0, aio_comp->wait_for_complete()); + ASSERT_EQ(1, aio_comp->is_complete()); + ASSERT_EQ(0, aio_comp->get_return_value()); + aio_comp->release(); + } + + // verify promotions + for (auto &image : images) { + librbd::mirror_image_info_t mirror_image; + ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, + sizeof(mirror_image))); + ASSERT_TRUE(mirror_image.primary); + } +} + +TEST_F(TestMirroring, AioGetInfo) { + std::list<std::string> image_names; + for (size_t idx = 0; idx < 10; ++idx) { + image_names.push_back(get_temp_image_name()); + } + + ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_POOL)); + + // create mirror images + int order = 20; + std::list<librbd::Image> images; + for (auto &image_name : image_names) { + ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 2048, + RBD_FEATURE_EXCLUSIVE_LOCK | + RBD_FEATURE_JOURNALING, + &order)); + + images.emplace_back(); + ASSERT_EQ(0, m_rbd.open(m_ioctx, images.back(), image_name.c_str())); + } + + std::list<librbd::RBD::AioCompletion *> aio_comps; + std::list<librbd::mirror_image_info_t> infos; + for (auto &image : images) { + aio_comps.push_back(new librbd::RBD::AioCompletion(nullptr, nullptr)); + infos.emplace_back(); + ASSERT_EQ(0, image.aio_mirror_image_get_info(&infos.back(), + sizeof(infos.back()), + aio_comps.back())); + } + for (auto aio_comp : aio_comps) { + ASSERT_EQ(0, aio_comp->wait_for_complete()); + ASSERT_EQ(1, aio_comp->is_complete()); + ASSERT_EQ(0, aio_comp->get_return_value()); + aio_comp->release(); + } + aio_comps.clear(); + + for (auto &info : infos) { + ASSERT_NE("", info.global_id); + ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, info.state); + ASSERT_TRUE(info.primary); + } +} + +TEST_F(TestMirroring, AioGetStatus) { + std::list<std::string> image_names; + for (size_t idx = 0; idx < 10; ++idx) { + image_names.push_back(get_temp_image_name()); + } + + ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_POOL)); + + // create mirror images + int order = 20; + std::list<librbd::Image> images; + for (auto &image_name : image_names) { + ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 2048, + RBD_FEATURE_EXCLUSIVE_LOCK | + RBD_FEATURE_JOURNALING, + &order)); + + images.emplace_back(); + ASSERT_EQ(0, m_rbd.open(m_ioctx, images.back(), image_name.c_str())); + } + + std::list<librbd::RBD::AioCompletion *> aio_comps; + std::list<librbd::mirror_image_status_t> statuses; + for (auto &image : images) { + aio_comps.push_back(new librbd::RBD::AioCompletion(nullptr, nullptr)); + statuses.emplace_back(); + ASSERT_EQ(0, image.aio_mirror_image_get_status(&statuses.back(), + sizeof(statuses.back()), + aio_comps.back())); + } + for (auto aio_comp : aio_comps) { + ASSERT_EQ(0, aio_comp->wait_for_complete()); + ASSERT_EQ(1, aio_comp->is_complete()); + ASSERT_EQ(0, aio_comp->get_return_value()); + aio_comp->release(); + } + aio_comps.clear(); + + for (auto &status : statuses) { + ASSERT_NE("", status.name); + ASSERT_NE("", status.info.global_id); + ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, status.info.state); + ASSERT_TRUE(status.info.primary); + ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, status.state); + ASSERT_EQ("status not found", status.description); + ASSERT_FALSE(status.up); + ASSERT_EQ(0, status.last_update); + } +} |