From 55dcce90bf460f54bbfb6bdba68b2f1f24d973da Mon Sep 17 00:00:00 2001 From: Mykola Golub Date: Fri, 11 Oct 2019 19:32:31 +0100 Subject: [PATCH] librbd: state machine for snapshot based mirror promote/demote Signed-off-by: Mykola Golub --- src/librbd/CMakeLists.txt | 2 + src/librbd/mirror/snapshot/DemoteRequest.cc | 100 +++++++++++++++++++ src/librbd/mirror/snapshot/DemoteRequest.h | 73 ++++++++++++++ src/librbd/mirror/snapshot/PromoteRequest.cc | 100 +++++++++++++++++++ src/librbd/mirror/snapshot/PromoteRequest.h | 73 ++++++++++++++ 5 files changed, 348 insertions(+) create mode 100644 src/librbd/mirror/snapshot/DemoteRequest.cc create mode 100644 src/librbd/mirror/snapshot/DemoteRequest.h create mode 100644 src/librbd/mirror/snapshot/PromoteRequest.cc create mode 100644 src/librbd/mirror/snapshot/PromoteRequest.h diff --git a/src/librbd/CMakeLists.txt b/src/librbd/CMakeLists.txt index 9bf456f8781..8de8dbe0b57 100644 --- a/src/librbd/CMakeLists.txt +++ b/src/librbd/CMakeLists.txt @@ -106,6 +106,8 @@ set(librbd_internal_srcs mirror/PromoteRequest.cc mirror/snapshot/CreateNonPrimaryRequest.cc mirror/snapshot/CreatePrimaryRequest.cc + mirror/snapshot/DemoteRequest.cc + mirror/snapshot/PromoteRequest.cc mirror/snapshot/UnlinkPeerRequest.cc object_map/CreateRequest.cc object_map/InvalidateRequest.cc diff --git a/src/librbd/mirror/snapshot/DemoteRequest.cc b/src/librbd/mirror/snapshot/DemoteRequest.cc new file mode 100644 index 00000000000..18481b20a49 --- /dev/null +++ b/src/librbd/mirror/snapshot/DemoteRequest.cc @@ -0,0 +1,100 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "librbd/mirror/snapshot/DemoteRequest.h" +#include "common/dout.h" +#include "common/errno.h" +#include "cls/rbd/cls_rbd_client.h" +#include "librbd/ImageCtx.h" +#include "librbd/ImageState.h" +#include "librbd/Operations.h" +#include "librbd/Utils.h" +#include "librbd/mirror/snapshot/CreatePrimaryRequest.h" + +#define dout_subsys ceph_subsys_rbd +#undef dout_prefix +#define dout_prefix *_dout << "librbd::mirror::snapshot::DemoteRequest: " \ + << this << " " << __func__ << ": " + +namespace librbd { +namespace mirror { +namespace snapshot { + +using librbd::util::create_context_callback; + +template +void DemoteRequest::send() { + refresh_image(); +} + +template +void DemoteRequest::refresh_image() { + if (!m_image_ctx->state->is_refresh_required()) { + create_snapshot(); + return; + } + + CephContext *cct = m_image_ctx->cct; + ldout(cct, 20) << dendl; + + auto ctx = create_context_callback< + DemoteRequest, &DemoteRequest::handle_refresh_image>(this); + m_image_ctx->state->refresh(ctx); +} + +template +void DemoteRequest::handle_refresh_image(int r) { + CephContext *cct = m_image_ctx->cct; + ldout(cct, 20) << "r=" << r << dendl; + + if (r < 0) { + lderr(cct) << "failed to refresh image: " << cpp_strerror(r) << dendl; + finish(r); + return; + } + + create_snapshot(); +} + +template +void DemoteRequest::create_snapshot() { + CephContext *cct = m_image_ctx->cct; + ldout(cct, 20) << dendl; + + auto ctx = create_context_callback< + DemoteRequest, &DemoteRequest::handle_create_snapshot>(this); + + auto req = CreatePrimaryRequest::create(m_image_ctx, true, false, nullptr, + ctx); + req->send(); +} + +template +void DemoteRequest::handle_create_snapshot(int r) { + CephContext *cct = m_image_ctx->cct; + ldout(cct, 20) << "r=" << r << dendl; + + if (r < 0) { + lderr(cct) << "failed to create mirror snapshot: " << cpp_strerror(r) + << dendl; + finish(r); + return; + } + + finish(0); +} + +template +void DemoteRequest::finish(int r) { + CephContext *cct = m_image_ctx->cct; + ldout(cct, 20) << "r=" << r << dendl; + + m_on_finish->complete(r); + delete this; +} + +} // namespace snapshot +} // namespace mirror +} // namespace librbd + +template class librbd::mirror::snapshot::DemoteRequest; diff --git a/src/librbd/mirror/snapshot/DemoteRequest.h b/src/librbd/mirror/snapshot/DemoteRequest.h new file mode 100644 index 00000000000..054a9dce12d --- /dev/null +++ b/src/librbd/mirror/snapshot/DemoteRequest.h @@ -0,0 +1,73 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_LIBRBD_MIRROR_SNAPSHOT_DEMOTE_REQUEST_H +#define CEPH_LIBRBD_MIRROR_SNAPSHOT_DEMOTE_REQUEST_H + +#include "include/buffer.h" + +#include +#include + +struct Context; + +namespace librbd { + +struct ImageCtx; + +namespace mirror { +namespace snapshot { + +template +class DemoteRequest { +public: + static DemoteRequest *create(ImageCtxT *image_ctx, bool force, + Context *on_finish) { + return new DemoteRequest(image_ctx, force, on_finish); + } + + DemoteRequest(ImageCtxT *image_ctx, bool force, Context *on_finish) + : m_image_ctx(image_ctx), m_force(force), m_on_finish(on_finish) { + } + + void send(); + +private: + /** + * @verbatim + * + * + * | + * v + * REFRESH_IMAGE + * | + * v + * CREATE_SNAPSHOT + * | + * v + * + * + * @endverbatim + */ + + ImageCtxT *m_image_ctx; + bool m_force; + Context *m_on_finish; + + void refresh_image(); + void handle_refresh_image(int r); + + void create_snapshot(); + void handle_create_snapshot(int r); + + void finish(int r); + +}; + +} // namespace snapshot +} // namespace mirror +} // namespace librbd + +extern template class librbd::mirror::snapshot::DemoteRequest; + +#endif // CEPH_LIBRBD_MIRROR_SNAPSHOT_DEMOTE_REQUEST_H diff --git a/src/librbd/mirror/snapshot/PromoteRequest.cc b/src/librbd/mirror/snapshot/PromoteRequest.cc new file mode 100644 index 00000000000..c9e59e03065 --- /dev/null +++ b/src/librbd/mirror/snapshot/PromoteRequest.cc @@ -0,0 +1,100 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "librbd/mirror/snapshot/PromoteRequest.h" +#include "common/dout.h" +#include "common/errno.h" +#include "cls/rbd/cls_rbd_client.h" +#include "librbd/ImageCtx.h" +#include "librbd/ImageState.h" +#include "librbd/Operations.h" +#include "librbd/Utils.h" +#include "librbd/mirror/snapshot/CreatePrimaryRequest.h" + +#define dout_subsys ceph_subsys_rbd +#undef dout_prefix +#define dout_prefix *_dout << "librbd::mirror::snapshot::PromoteRequest: " \ + << this << " " << __func__ << ": " + +namespace librbd { +namespace mirror { +namespace snapshot { + +using librbd::util::create_context_callback; + +template +void PromoteRequest::send() { + refresh_image(); +} + +template +void PromoteRequest::refresh_image() { + if (!m_image_ctx->state->is_refresh_required()) { + create_snapshot(); + return; + } + + CephContext *cct = m_image_ctx->cct; + ldout(cct, 20) << dendl; + + auto ctx = create_context_callback< + PromoteRequest, &PromoteRequest::handle_refresh_image>(this); + m_image_ctx->state->refresh(ctx); +} + +template +void PromoteRequest::handle_refresh_image(int r) { + CephContext *cct = m_image_ctx->cct; + ldout(cct, 20) << "r=" << r << dendl; + + if (r < 0) { + lderr(cct) << "failed to refresh image: " << cpp_strerror(r) << dendl; + finish(r); + return; + } + + create_snapshot(); +} + +template +void PromoteRequest::create_snapshot() { + CephContext *cct = m_image_ctx->cct; + ldout(cct, 20) << dendl; + + auto ctx = create_context_callback< + PromoteRequest, &PromoteRequest::handle_create_snapshot>(this); + + auto req = CreatePrimaryRequest::create(m_image_ctx, false, true, nullptr, + ctx); + req->send(); +} + +template +void PromoteRequest::handle_create_snapshot(int r) { + CephContext *cct = m_image_ctx->cct; + ldout(cct, 20) << "r=" << r << dendl; + + if (r < 0) { + lderr(cct) << "failed to create mirror snapshot: " << cpp_strerror(r) + << dendl; + finish(r); + return; + } + + finish(0); +} + +template +void PromoteRequest::finish(int r) { + CephContext *cct = m_image_ctx->cct; + ldout(cct, 20) << "r=" << r << dendl; + + m_on_finish->complete(r); + delete this; +} + +} // namespace snapshot +} // namespace mirror +} // namespace librbd + +template class librbd::mirror::snapshot::PromoteRequest; diff --git a/src/librbd/mirror/snapshot/PromoteRequest.h b/src/librbd/mirror/snapshot/PromoteRequest.h new file mode 100644 index 00000000000..ef6e93301d7 --- /dev/null +++ b/src/librbd/mirror/snapshot/PromoteRequest.h @@ -0,0 +1,73 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_LIBRBD_MIRROR_SNAPSHOT_PROMOTE_REQUEST_H +#define CEPH_LIBRBD_MIRROR_SNAPSHOT_PROMOTE_REQUEST_H + +#include "include/buffer.h" + +#include +#include + +struct Context; + +namespace librbd { + +struct ImageCtx; + +namespace mirror { +namespace snapshot { + +template +class PromoteRequest { +public: + static PromoteRequest *create(ImageCtxT *image_ctx, bool force, + Context *on_finish) { + return new PromoteRequest(image_ctx, force, on_finish); + } + + PromoteRequest(ImageCtxT *image_ctx, bool force, Context *on_finish) + : m_image_ctx(image_ctx), m_force(force), m_on_finish(on_finish) { + } + + void send(); + +private: + /** + * @verbatim + * + * + * | + * v + * REFRESH_IMAGE + * | + * v + * CREATE_SNAPSHOT + * | + * v + * + * + * @endverbatim + */ + + ImageCtxT *m_image_ctx; + bool m_force; + Context *m_on_finish; + + void refresh_image(); + void handle_refresh_image(int r); + + void create_snapshot(); + void handle_create_snapshot(int r); + + void finish(int r); + +}; + +} // namespace snapshot +} // namespace mirror +} // namespace librbd + +extern template class librbd::mirror::snapshot::PromoteRequest; + +#endif // CEPH_LIBRBD_MIRROR_SNAPSHOT_PROMOTE_REQUEST_H -- 2.39.5