From: Mykola Golub Date: Thu, 2 Mar 2017 16:18:18 +0000 (+0100) Subject: librbd: relax "is parent mirrored" check when enabling mirroring for pool X-Git-Tag: v10.2.10~113^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=8f23ea4fc0938c35998193ea76d7a029422b89b0;p=ceph.git 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 (cherry picked from commit fe31bca22f90ce02f461d6421a4f66539db888d3) --- diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 9fecb1e1688f..edd5f165e9c5 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -3089,7 +3089,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; @@ -3112,16 +3112,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; + } } } } @@ -3627,7 +3636,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 c08ad9f69c26..5c7ac85759c3 100644 --- a/src/librbd/internal.h +++ b/src/librbd/internal.h @@ -215,7 +215,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 bbebbbaf8690..81a6f62d4d67 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -1328,7 +1328,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) { @@ -2873,7 +2873,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 1ade21f081da..921817d2d209 100644 --- a/src/test/librbd/test_librbd.cc +++ b/src/test/librbd/test_librbd.cc @@ -4552,6 +4552,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 bb65c5561c59..14ae20a6ae97 100644 --- a/src/test/rbd_mirror/test_ImageReplayer.cc +++ b/src/test/rbd_mirror/test_ImageReplayer.cc @@ -426,7 +426,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));