From d61293d4dacd86e670b300714da69f02aff48ffc Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Sun, 13 Mar 2016 22:08:16 -0400 Subject: [PATCH] rbd-mirror: helper state machine for closing librbd images librbd ImageCtx's cannot be deleted from within the librbd thread. This state machine will perform the deletion from the rbd-mirror work queue thread. Signed-off-by: Jason Dillaman --- .../image_replayer/CloseImageRequest.cc | 84 +++++++++++++++++++ .../image_replayer/CloseImageRequest.h | 66 +++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 src/tools/rbd_mirror/image_replayer/CloseImageRequest.cc create mode 100644 src/tools/rbd_mirror/image_replayer/CloseImageRequest.h diff --git a/src/tools/rbd_mirror/image_replayer/CloseImageRequest.cc b/src/tools/rbd_mirror/image_replayer/CloseImageRequest.cc new file mode 100644 index 0000000000000..37512455ca7f1 --- /dev/null +++ b/src/tools/rbd_mirror/image_replayer/CloseImageRequest.cc @@ -0,0 +1,84 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "CloseImageRequest.h" +#include "common/dout.h" +#include "common/errno.h" +#include "common/WorkQueue.h" +#include "librbd/ImageCtx.h" +#include "librbd/ImageState.h" +#include "librbd/Utils.h" + +#define dout_subsys ceph_subsys_rbd_mirror +#undef dout_prefix +#define dout_prefix *_dout << "rbd::mirror::image_replayer::CloseImageRequest: " \ + << this << " " << __func__ + +namespace rbd { +namespace mirror { +namespace image_replayer { + +using librbd::util::create_context_callback; + +template +CloseImageRequest::CloseImageRequest(I **image_ctx, ContextWQ *work_queue, + Context *on_finish) + : m_image_ctx(image_ctx), m_work_queue(work_queue), m_on_finish(on_finish) { +} + +template +void CloseImageRequest::send() { + close_image(); +} + +template +void CloseImageRequest::close_image() { + dout(20) << dendl; + + Context *ctx = create_context_callback< + CloseImageRequest, &CloseImageRequest::handle_close_image>(this); + (*m_image_ctx)->state->close(ctx); +} + +template +void CloseImageRequest::handle_close_image(int r) { + dout(20) << ": r=" << r << dendl; + + if (r < 0) { + derr << "error encountered while closing image: " << cpp_strerror(r) + << dendl; + } + + switch_thread_context(); +} + +template +void CloseImageRequest::switch_thread_context() { + dout(20) << dendl; + + // swap the librbd thread context for the rbd-mirror thread context + Context *ctx = create_context_callback< + CloseImageRequest, &CloseImageRequest::handle_switch_thread_context>( + this); + m_work_queue->queue(ctx, 0); +} + +template +void CloseImageRequest::handle_switch_thread_context(int r) { + dout(20) << dendl; + + assert(r == 0); + + delete *m_image_ctx; + *m_image_ctx = nullptr; + + m_on_finish->complete(0); + delete this; +} + +} // namespace image_replayer +} // namespace mirror +} // namespace rbd + +template class rbd::mirror::image_replayer::CloseImageRequest; + diff --git a/src/tools/rbd_mirror/image_replayer/CloseImageRequest.h b/src/tools/rbd_mirror/image_replayer/CloseImageRequest.h new file mode 100644 index 0000000000000..8c4329706218e --- /dev/null +++ b/src/tools/rbd_mirror/image_replayer/CloseImageRequest.h @@ -0,0 +1,66 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef RBD_MIRROR_IMAGE_REPLAYER_CLOSE_IMAGE_REQUEST_H +#define RBD_MIRROR_IMAGE_REPLAYER_CLOSE_IMAGE_REQUEST_H + +#include "include/int_types.h" +#include "librbd/ImageCtx.h" +#include + +class Context; +class ContextWQ; +namespace librbd { class ImageCtx; } + +namespace rbd { +namespace mirror { +namespace image_replayer { + +template +class CloseImageRequest { +public: + static CloseImageRequest* create(ImageCtxT **image_ctx, ContextWQ *work_queue, + Context *on_finish) { + return new CloseImageRequest(image_ctx, work_queue, on_finish); + } + + CloseImageRequest(ImageCtxT **image_ctx, ContextWQ *work_queue, + Context *on_finish); + + void send(); + +private: + /** + * @verbatim + * + * + * | + * v + * CLOSE_IMAGE + * | + * v + * SWITCH_CONTEXT + * | + * v + * + * + * @endverbatim + */ + ImageCtxT **m_image_ctx; + ContextWQ *m_work_queue; + Context *m_on_finish; + + void close_image(); + void handle_close_image(int r); + + void switch_thread_context(); + void handle_switch_thread_context(int r); +}; + +} // namespace image_replayer +} // namespace mirror +} // namespace rbd + +extern template class rbd::mirror::image_replayer::CloseImageRequest; + +#endif // RBD_MIRROR_IMAGE_REPLAYER_CLOSE_IMAGE_REQUEST_H -- 2.39.5