From 1e4320a98d6e51bf9be820bb43ddb34b77791fa0 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Mon, 20 Apr 2020 17:04:02 -0400 Subject: [PATCH] librbd: permit mirroring to be enabled upon image creation The librbd create API's ImageOptions parameter now supports passing the mirror image mode. Signed-off-by: Jason Dillaman (cherry picked from commit 37f6fa8fe95729af845100e28df8b8e0668c2270) --- src/include/rbd/librbd.h | 1 + src/librbd/image/CreateRequest.cc | 15 ++++++++++----- src/librbd/image/CreateRequest.h | 1 - src/librbd/internal.cc | 11 +++++++++-- src/librbd/mirror/EnableRequest.cc | 3 ++- src/test/librbd/test_librbd.cc | 28 ++++++++++++++++++++++++++++ 6 files changed, 50 insertions(+), 9 deletions(-) diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h index 25068dbf4e59c..d85cd36504b66 100644 --- a/src/include/rbd/librbd.h +++ b/src/include/rbd/librbd.h @@ -292,6 +292,7 @@ enum { RBD_IMAGE_OPTION_DATA_POOL = 10, RBD_IMAGE_OPTION_FLATTEN = 11, RBD_IMAGE_OPTION_CLONE_FORMAT = 12, + RBD_IMAGE_OPTION_MIRROR_IMAGE_MODE = 13, }; typedef enum { diff --git a/src/librbd/image/CreateRequest.cc b/src/librbd/image/CreateRequest.cc index dbc03e7a221aa..ffa3dbc68a8bb 100644 --- a/src/librbd/image/CreateRequest.cc +++ b/src/librbd/image/CreateRequest.cc @@ -133,7 +133,10 @@ CreateRequest::CreateRequest(const ConfigProxy& config, IoCtx &ioctx, m_id_obj = util::id_obj_name(m_image_name); m_header_obj = util::header_name(m_image_id); m_objmap_name = ObjectMap<>::object_map_name(m_image_id, CEPH_NOSNAP); - m_force_non_primary = !non_primary_global_image_id.empty(); + if (!non_primary_global_image_id.empty() && + (m_create_flags & CREATE_FLAG_MIRROR_ENABLE_MASK) == 0) { + m_create_flags |= CREATE_FLAG_FORCE_MIRROR_ENABLE; + } if (image_options.get(RBD_IMAGE_OPTION_FEATURES, &m_features) != 0) { m_features = librbd::rbd_features_from_string( @@ -603,7 +606,7 @@ void CreateRequest::journal_create() { // only link to remote primary mirror uuid if in journal-based // mirroring mode bool use_primary_mirror_uuid = ( - m_force_non_primary && + !m_non_primary_global_image_id.empty() && m_mirror_image_mode == cls::rbd::MIRROR_IMAGE_MODE_JOURNAL); librbd::journal::TagData tag_data; @@ -635,9 +638,11 @@ void CreateRequest::handle_journal_create(int r) { template void CreateRequest::mirror_image_enable() { - if (((m_mirror_mode != cls::rbd::MIRROR_MODE_POOL) && !m_force_non_primary) || - ((m_create_flags & CREATE_FLAG_MIRROR_ENABLE_MASK) == - CREATE_FLAG_SKIP_MIRROR_ENABLE)) { + auto mirror_enable_flag = (m_create_flags & CREATE_FLAG_MIRROR_ENABLE_MASK); + + if ((m_mirror_mode != cls::rbd::MIRROR_MODE_POOL && + mirror_enable_flag != CREATE_FLAG_FORCE_MIRROR_ENABLE) || + (mirror_enable_flag == CREATE_FLAG_SKIP_MIRROR_ENABLE)) { complete(0); return; } diff --git a/src/librbd/image/CreateRequest.h b/src/librbd/image/CreateRequest.h index 632ba077ac964..ce924e34ae31c 100644 --- a/src/librbd/image/CreateRequest.h +++ b/src/librbd/image/CreateRequest.h @@ -123,7 +123,6 @@ private: CephContext *m_cct; int m_r_saved = 0; // used to return actual error after cleanup - bool m_force_non_primary; file_layout_t m_layout; std::string m_id_obj, m_header_obj, m_objmap_name; diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 3dbbcd00918d8..f4350c8ad27d9 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -311,6 +311,7 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { {RBD_IMAGE_OPTION_DATA_POOL, STR}, {RBD_IMAGE_OPTION_FLATTEN, UINT64}, {RBD_IMAGE_OPTION_CLONE_FORMAT, UINT64}, + {RBD_IMAGE_OPTION_MIRROR_IMAGE_MODE, UINT64}, }; std::string image_option_name(int optname) { @@ -341,6 +342,8 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { return "flatten"; case RBD_IMAGE_OPTION_CLONE_FORMAT: return "clone_format"; + case RBD_IMAGE_OPTION_MIRROR_IMAGE_MODE: + return "mirror_image_mode"; default: return "unknown (" + stringify(optname) + ")"; } @@ -689,15 +692,19 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { api::Config<>::apply_pool_overrides(io_ctx, &config); uint32_t create_flags = 0U; + uint64_t mirror_image_mode = RBD_MIRROR_IMAGE_MODE_JOURNAL; if (skip_mirror_enable) { create_flags = image::CREATE_FLAG_SKIP_MIRROR_ENABLE; + } else if (opts.get(RBD_IMAGE_OPTION_MIRROR_IMAGE_MODE, + &mirror_image_mode) == 0) { + create_flags = image::CREATE_FLAG_FORCE_MIRROR_ENABLE; } C_SaferCond cond; image::CreateRequest<> *req = image::CreateRequest<>::create( config, io_ctx, image_name, id, size, opts, create_flags, - cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, non_primary_global_image_id, - primary_mirror_uuid, op_work_queue, &cond); + static_cast(mirror_image_mode), + non_primary_global_image_id, primary_mirror_uuid, op_work_queue, &cond); req->send(); r = cond.wait(); diff --git a/src/librbd/mirror/EnableRequest.cc b/src/librbd/mirror/EnableRequest.cc index cb61631f48600..b99f9d71b306d 100644 --- a/src/librbd/mirror/EnableRequest.cc +++ b/src/librbd/mirror/EnableRequest.cc @@ -160,7 +160,8 @@ void EnableRequest::open_image() { auto ctx = create_context_callback< EnableRequest, &EnableRequest::handle_open_image>(this); - m_image_ctx->state->open(OPEN_FLAG_SKIP_OPEN_PARENT, ctx); + m_image_ctx->state->open(OPEN_FLAG_SKIP_OPEN_PARENT | + OPEN_FLAG_IGNORE_MIGRATING, ctx); } template diff --git a/src/test/librbd/test_librbd.cc b/src/test/librbd/test_librbd.cc index 86aa95c88b63b..d091fd7ca5a04 100644 --- a/src/test/librbd/test_librbd.cc +++ b/src/test/librbd/test_librbd.cc @@ -6592,6 +6592,34 @@ TEST_F(TestLibRBD, MirrorPeerAttributes) { ASSERT_EQ(0, rbd.mirror_mode_set(ioctx, RBD_MIRROR_MODE_DISABLED)); } +TEST_F(TestLibRBD, CreateWithMirrorEnabled) { + REQUIRE_FORMAT_V2(); + + librados::IoCtx ioctx; + ASSERT_EQ(0, _rados.ioctx_create(m_pool_name.c_str(), ioctx)); + + librbd::RBD rbd; + ASSERT_EQ(0, rbd.mirror_mode_set(ioctx, RBD_MIRROR_MODE_IMAGE)); + + librbd::ImageOptions image_options; + ASSERT_EQ(0, image_options.set( + RBD_IMAGE_OPTION_MIRROR_IMAGE_MODE, + static_cast(RBD_MIRROR_IMAGE_MODE_SNAPSHOT))); + + std::string image_name = get_temp_image_name(); + ASSERT_EQ(0, rbd.create4(ioctx, image_name.c_str(), 2<<20, image_options)); + + librbd::Image image; + ASSERT_EQ(0, rbd.open(ioctx, image, image_name.c_str(), NULL)); + + librbd::mirror_image_mode_t mirror_image_mode; + ASSERT_EQ(0, image.mirror_image_get_mode(&mirror_image_mode)); + ASSERT_EQ(RBD_MIRROR_IMAGE_MODE_SNAPSHOT, mirror_image_mode); + + ASSERT_EQ(0, image.mirror_image_disable(true)); + ASSERT_EQ(0, rbd.mirror_mode_set(ioctx, RBD_MIRROR_MODE_DISABLED)); +} + TEST_F(TestLibRBD, FlushCacheWithCopyupOnExternalSnapshot) { REQUIRE_FEATURE(RBD_FEATURE_LAYERING); -- 2.39.5