From 931c9f0fd9332136466a8d81c9708b86f597f4be Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Mon, 20 Apr 2020 18:16:40 -0400 Subject: [PATCH] librbd: mirror enable state machine might need to open image If attempting to create a snapshot-based mirroring primary snapshot, the image needs to first be opened. If we weren't supplied an image, open the image, create the snapshot, and close the image again. Signed-off-by: Jason Dillaman --- src/librbd/mirror/EnableRequest.cc | 76 ++++++++++++++++++++++++++++-- src/librbd/mirror/EnableRequest.h | 15 ++++++ 2 files changed, 88 insertions(+), 3 deletions(-) diff --git a/src/librbd/mirror/EnableRequest.cc b/src/librbd/mirror/EnableRequest.cc index c2cbbbd322c7f..cb61631f48600 100644 --- a/src/librbd/mirror/EnableRequest.cc +++ b/src/librbd/mirror/EnableRequest.cc @@ -106,7 +106,7 @@ void EnableRequest::handle_get_mirror_image(int r) { template void EnableRequest::get_tag_owner() { if (m_mirror_image.mode == cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT) { - create_primary_snapshot(); + open_image(); return; } else if (!m_non_primary_global_image_id.empty()) { image_state_update(); @@ -143,13 +143,43 @@ void EnableRequest::handle_get_tag_owner(int r) { } template -void EnableRequest::create_primary_snapshot() { +void EnableRequest::open_image() { if (!m_non_primary_global_image_id.empty()) { // special case for rbd-mirror creating a non-primary image enable_non_primary_feature(); return; + } else if (m_image_ctx != nullptr) { + create_primary_snapshot(); + return; + } + + ldout(m_cct, 10) << dendl; + + m_close_image = true; + m_image_ctx = I::create("", m_image_id, CEPH_NOSNAP, m_io_ctx, false); + + auto ctx = create_context_callback< + EnableRequest, &EnableRequest::handle_open_image>(this); + m_image_ctx->state->open(OPEN_FLAG_SKIP_OPEN_PARENT, ctx); +} + +template +void EnableRequest::handle_open_image(int r) { + ldout(m_cct, 10) << "r=" << r << dendl; + + if (r < 0) { + lderr(m_cct) << "failed to open image: " << cpp_strerror(r) << dendl; + m_image_ctx->destroy(); + m_image_ctx = nullptr; + finish(r); + return; } + create_primary_snapshot(); +} + +template +void EnableRequest::create_primary_snapshot() { ldout(m_cct, 10) << dendl; ceph_assert(m_image_ctx != nullptr); @@ -169,13 +199,53 @@ void EnableRequest::handle_create_primary_snapshot(int r) { if (r < 0) { lderr(m_cct) << "failed to create initial primary snapshot: " << cpp_strerror(r) << dendl; - finish(r); + m_ret_val = r; + } + + close_image(); +} + +template +void EnableRequest::close_image() { + if (!m_close_image) { + if (m_ret_val < 0) { + finish(m_ret_val); + } else { + image_state_update(); + } + return; + } + + ldout(m_cct, 10) << dendl; + + auto ctx = create_context_callback< + EnableRequest, &EnableRequest::handle_close_image>(this); + m_image_ctx->state->close(ctx); +} + +template +void EnableRequest::handle_close_image(int r) { + ldout(m_cct, 10) << "r=" << r << dendl; + + m_image_ctx->destroy(); + m_image_ctx = nullptr; + + if (r < 0) { + lderr(m_cct) << "failed to close image: " << cpp_strerror(r) << dendl; + if (m_ret_val == 0) { + m_ret_val = r; + } + } + + if (m_ret_val < 0) { + finish(m_ret_val); return; } image_state_update(); } + template void EnableRequest::enable_non_primary_feature() { if (m_mirror_image.mode != cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT) { diff --git a/src/librbd/mirror/EnableRequest.h b/src/librbd/mirror/EnableRequest.h index c9945d7b56c7d..12ab0f035af7b 100644 --- a/src/librbd/mirror/EnableRequest.h +++ b/src/librbd/mirror/EnableRequest.h @@ -53,8 +53,14 @@ private: * GET_TAG_OWNER * * * * * * * * * | * * v (skip if not needed) * + * OPEN_IMAGE * + * | * + * v (skip if not needed) * * CREATE_PRIMARY_SNAPSHOT * * * * | * + * v (skip of not opened) * + * CLOSE_IMAGE * + * | * * v (skip if not needed) * * ENABLE_NON_PRIMARY_FEATURE * * | * @@ -84,6 +90,9 @@ private: bufferlist m_out_bl; cls::rbd::MirrorImage m_mirror_image; + int m_ret_val = 0; + bool m_close_image = false; + bool m_is_primary = false; uint64_t m_snap_id = CEPH_NOSNAP; @@ -93,9 +102,15 @@ private: void get_tag_owner(); void handle_get_tag_owner(int r); + void open_image(); + void handle_open_image(int r); + void create_primary_snapshot(); void handle_create_primary_snapshot(int r); + void close_image(); + void handle_close_image(int r); + void enable_non_primary_feature(); void handle_enable_non_primary_feature(int r); -- 2.39.5