From fe31bca22f90ce02f461d6421a4f66539db888d3 Mon Sep 17 00:00:00 2001 From: Mykola Golub Date: Thu, 2 Mar 2017 17:18:18 +0100 Subject: [PATCH] librbd: relax "is parent mirrored" check when enabling mirroring for pool If the parent is in the same pool and has the journaling feature enabled we can assume the mirroring will eventually be enabled for it. Fixes: http://tracker.ceph.com/issues/19130 Signed-off-by: Mykola Golub --- src/librbd/internal.cc | 27 +++++++++++++++-------- src/librbd/internal.h | 2 +- src/librbd/librbd.cc | 4 ++-- src/test/librbd/test_librbd.cc | 19 ++++++++++++++++ src/test/rbd_mirror/test_ImageReplayer.cc | 2 +- 5 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 6f32a9f9996..1286727f083 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -2305,7 +2305,7 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force, return cls_client::metadata_list(&ictx->md_ctx, ictx->header_oid, start, max, pairs); } - int mirror_image_enable(ImageCtx *ictx) { + int mirror_image_enable(ImageCtx *ictx, bool relax_same_pool_parent_check) { CephContext *cct = ictx->cct; ldout(cct, 20) << "mirror_image_enable " << ictx << dendl; @@ -2328,16 +2328,25 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force, return -EINVAL; } - // is mirroring not enabled for the parent? + // is mirroring not enabled for the parent? { RWLock::RLocker l(ictx->parent_lock); ImageCtx *parent = ictx->parent; - if(parent) { - cls::rbd::MirrorImage mirror_image_internal; - r = cls_client::mirror_image_get(&(parent->md_ctx), parent->id, &mirror_image_internal); - if (r == -ENOENT) { - lderr(cct) << "mirroring is not enabled for the parent" << dendl; - return -EINVAL; + if (parent) { + if (relax_same_pool_parent_check && + parent->md_ctx.get_id() == ictx->md_ctx.get_id()) { + if (!parent->test_features(RBD_FEATURE_JOURNALING)) { + lderr(cct) << "journaling is not enabled for the parent" << dendl; + return -EINVAL; + } + } else { + cls::rbd::MirrorImage mirror_image_internal; + r = cls_client::mirror_image_get(&(parent->md_ctx), parent->id, + &mirror_image_internal); + if (r == -ENOENT) { + lderr(cct) << "mirroring is not enabled for the parent" << dendl; + return -EINVAL; + } } } } @@ -2851,7 +2860,7 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force, return r; } - r = mirror_image_enable(img_ctx); + r = mirror_image_enable(img_ctx, true); if (r < 0) { lderr(cct) << "error enabling mirroring for image " << img_pair.first << ": " << cpp_strerror(r) << dendl; diff --git a/src/librbd/internal.h b/src/librbd/internal.h index 9fed529d016..9a21161a3d7 100644 --- a/src/librbd/internal.h +++ b/src/librbd/internal.h @@ -218,7 +218,7 @@ namespace librbd { int mirror_image_status_summary(IoCtx& io_ctx, std::map *states); - int mirror_image_enable(ImageCtx *ictx); + int mirror_image_enable(ImageCtx *ictx, bool relax_same_pool_parent_check); int mirror_image_disable(ImageCtx *ictx, bool force); int mirror_image_promote(ImageCtx *ictx, bool force); int mirror_image_demote(ImageCtx *ictx); diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index 762696b9da0..584b6e994a3 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -1537,7 +1537,7 @@ namespace librbd { int Image::mirror_image_enable() { ImageCtx *ictx = (ImageCtx *)ctx; - return librbd::mirror_image_enable(ictx); + return librbd::mirror_image_enable(ictx, false); } int Image::mirror_image_disable(bool force) { @@ -3268,7 +3268,7 @@ extern "C" int rbd_metadata_list(rbd_image_t image, const char *start, uint64_t extern "C" int rbd_mirror_image_enable(rbd_image_t image) { librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; - return librbd::mirror_image_enable(ictx); + return librbd::mirror_image_enable(ictx, false); } extern "C" int rbd_mirror_image_disable(rbd_image_t image, bool force) diff --git a/src/test/librbd/test_librbd.cc b/src/test/librbd/test_librbd.cc index d65f2b38418..c182e6cd260 100644 --- a/src/test/librbd/test_librbd.cc +++ b/src/test/librbd/test_librbd.cc @@ -5121,6 +5121,25 @@ TEST_F(TestLibRBD, Mirror) { ASSERT_EQ(0, rbd.mirror_mode_set(ioctx, RBD_MIRROR_MODE_IMAGE)); ASSERT_EQ(0, rbd.mirror_mode_get(ioctx, &mirror_mode)); + + // Add some images to the pool + int order = 0; + ASSERT_EQ(0, create_image_pp(rbd, ioctx, "parent", 2 << 20, &order)); + bool old_format; + uint64_t features; + ASSERT_EQ(0, get_features(&old_format, &features)); + if ((features & RBD_FEATURE_LAYERING) != 0) { + librbd::Image parent; + ASSERT_EQ(0, rbd.open(ioctx, parent, "parent", NULL)); + ASSERT_EQ(0, parent.snap_create("parent_snap")); + ASSERT_EQ(0, parent.close()); + ASSERT_EQ(0, rbd.open(ioctx, parent, "parent", "parent_snap")); + ASSERT_EQ(0, parent.snap_protect("parent_snap")); + ASSERT_EQ(0, parent.close()); + ASSERT_EQ(0, rbd.clone(ioctx, "parent", "parent_snap", ioctx, "child", + features, &order)); + } + ASSERT_EQ(RBD_MIRROR_MODE_IMAGE, mirror_mode); ASSERT_EQ(0, rbd.mirror_mode_set(ioctx, RBD_MIRROR_MODE_POOL)); diff --git a/src/test/rbd_mirror/test_ImageReplayer.cc b/src/test/rbd_mirror/test_ImageReplayer.cc index e7668a07a7b..554d044c1ab 100644 --- a/src/test/rbd_mirror/test_ImageReplayer.cc +++ b/src/test/rbd_mirror/test_ImageReplayer.cc @@ -433,7 +433,7 @@ TEST_F(TestImageReplayer, BootstrapMirrorDisabling) ASSERT_EQ(0, librbd::mirror_mode_set(m_remote_ioctx, RBD_MIRROR_MODE_IMAGE)); librbd::ImageCtx *ictx; open_remote_image(&ictx); - ASSERT_EQ(0, librbd::mirror_image_enable(ictx)); + ASSERT_EQ(0, librbd::mirror_image_enable(ictx, false)); cls::rbd::MirrorImage mirror_image; ASSERT_EQ(0, librbd::cls_client::mirror_image_get(&m_remote_ioctx, ictx->id, &mirror_image)); -- 2.39.5