From 3086d2a085ef2ba0a6b9b5d1a82d19212594f3a5 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Fri, 16 Jun 2017 13:28:01 -0400 Subject: [PATCH] librbd: removed synchronous watcher check from remove image state machine Signed-off-by: Jason Dillaman --- src/librbd/image/RemoveRequest.cc | 116 +++++++++++++++++++----------- src/librbd/image/RemoveRequest.h | 12 +++- 2 files changed, 86 insertions(+), 42 deletions(-) diff --git a/src/librbd/image/RemoveRequest.cc b/src/librbd/image/RemoveRequest.cc index 48da5221e88..5782702d78f 100644 --- a/src/librbd/image/RemoveRequest.cc +++ b/src/librbd/image/RemoveRequest.cc @@ -165,11 +165,11 @@ void RemoveRequest::check_image_snaps() { return; } - check_image_watchers(); + list_image_watchers(); } template -void RemoveRequest::check_image_watchers() { +void RemoveRequest::list_image_watchers() { ldout(m_cct, 20) << dendl; librados::ObjectReadOperation op; @@ -177,7 +177,7 @@ void RemoveRequest::check_image_watchers() { using klass = RemoveRequest; librados::AioCompletion *rados_completion = - create_rados_callback(this); + create_rados_callback(this); int r = m_image_ctx->md_ctx.aio_operate(m_header_oid, rados_completion, &op, &m_out_bl); @@ -186,62 +186,98 @@ void RemoveRequest::check_image_watchers() { } template -void RemoveRequest::filter_out_mirror_watchers() { - if (m_watchers.empty()) { - return; - } +void RemoveRequest::handle_list_image_watchers(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; - if ((m_image_ctx->features & RBD_FEATURE_JOURNALING) == 0) { - return; + if (r == 0 && m_ret_val < 0) { + r = m_ret_val; } - - cls::rbd::MirrorImage mirror_image; - int r = cls_client::mirror_image_get(&m_image_ctx->md_ctx, m_image_ctx->id, - &mirror_image); if (r < 0) { - if (r != -ENOENT) { - lderr(m_cct) << "failed to retrieve mirroring state: " - << cpp_strerror(r) << dendl; - } + lderr(m_cct) << "error listing image watchers: " << cpp_strerror(r) + << dendl; + send_close_image(r); return; } - if (mirror_image.state != cls::rbd::MIRROR_IMAGE_STATE_ENABLED) { + get_mirror_image(); +} + +template +void RemoveRequest::get_mirror_image() { + ldout(m_cct, 20) << dendl; + if ((m_watchers.empty()) || + ((m_image_ctx->features & RBD_FEATURE_JOURNALING) == 0)) { + check_image_watchers(); return; } - std::list mirror_watchers; - r = m_image_ctx->md_ctx.list_watchers(RBD_MIRRORING, &mirror_watchers); - if (r < 0) { - if (r != -ENOENT) { - lderr(m_cct) << "error listing mirroring watchers: " - << cpp_strerror(r) << dendl; - } + librados::ObjectReadOperation op; + cls_client::mirror_image_get_start(&op, m_image_id); + + using klass = RemoveRequest; + librados::AioCompletion *comp = + create_rados_callback(this); + m_out_bl.clear(); + int r = m_image_ctx->md_ctx.aio_operate(RBD_MIRRORING, comp, &op, &m_out_bl); + assert(r == 0); + comp->release(); +} + +template +void RemoveRequest::handle_get_mirror_image(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; + + if (r == -ENOENT || r == -EOPNOTSUPP) { + check_image_watchers(); return; + } else if (r < 0) { + ldout(m_cct, 5) << "error retrieving mirror image: " << cpp_strerror(r) + << dendl; } - for (auto &watcher : mirror_watchers) { - m_watchers.remove_if([watcher] (obj_watch_t &w) { - return (strncmp(w.addr, watcher.addr, sizeof(w.addr)) == 0); - }); - } + + list_mirror_watchers(); } template -void RemoveRequest::handle_check_image_watchers(int r) { +void RemoveRequest::list_mirror_watchers() { + ldout(m_cct, 20) << dendl; + + librados::ObjectReadOperation op; + op.list_watchers(&m_mirror_watchers, &m_ret_val); + + using klass = RemoveRequest; + librados::AioCompletion *rados_completion = + create_rados_callback(this); + m_out_bl.clear(); + int r = m_image_ctx->md_ctx.aio_operate(RBD_MIRRORING, rados_completion, + &op, &m_out_bl); + assert(r == 0); + rados_completion->release(); +} + +template +void RemoveRequest::handle_list_mirror_watchers(int r) { ldout(m_cct, 20) << "r=" << r << dendl; - if (r < 0) { - lderr(m_cct) << "error listing image watchers: " << cpp_strerror(r) - << dendl; - send_close_image(r); - return; + if (r == 0 && m_ret_val < 0) { + r = m_ret_val; + } + if (r < 0 && r != -ENOENT) { + ldout(m_cct, 5) << "error listing mirror watchers: " << cpp_strerror(r) + << dendl; + } + + for (auto &watcher : m_mirror_watchers) { + m_watchers.remove_if([watcher] (obj_watch_t &w) { + return (strncmp(w.addr, watcher.addr, sizeof(w.addr)) == 0); + }); } - // If an image is being bootstrapped by rbd-mirror, it implies - // that the rbd-mirror daemon currently has the image open. - // Permit removal if this is the case. - filter_out_mirror_watchers(); + check_image_watchers(); +} +template +void RemoveRequest::check_image_watchers() { if (m_watchers.size() > 1) { lderr(m_cct) << "image has watchers - not removing" << dendl; send_close_image(-EBUSY); diff --git a/src/librbd/image/RemoveRequest.h b/src/librbd/image/RemoveRequest.h index 24d94d86b9c..05adeaa18fd 100644 --- a/src/librbd/image/RemoveRequest.h +++ b/src/librbd/image/RemoveRequest.h @@ -123,6 +123,7 @@ private: int m_ret_val = 0; bufferlist m_out_bl; std::list m_watchers; + std::list m_mirror_watchers; void open_image(); void handle_open_image(int r); @@ -145,9 +146,16 @@ private: void validate_image_removal(); void check_image_snaps(); - void filter_out_mirror_watchers(); + void list_image_watchers(); + void handle_list_image_watchers(int r); + + void get_mirror_image(); + void handle_get_mirror_image(int r); + + void list_mirror_watchers(); + void handle_list_mirror_watchers(int r); + void check_image_watchers(); - void handle_check_image_watchers(int r); void check_group(); void handle_check_group(int r); -- 2.39.5