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: v11.2.1~80^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=474d504dd67378588d2dd243b06b844737ab64d5;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 f53a81edc25..0ae8e012185 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -2478,7 +2478,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; @@ -2501,16 +2501,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; + } } } } @@ -3025,7 +3034,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 550eecf9ac5..912da6d1dbf 100644 --- a/src/librbd/internal.h +++ b/src/librbd/internal.h @@ -214,7 +214,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 abbc873ff5c..e6e4ebab06d 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -1380,7 +1380,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) { @@ -2965,7 +2965,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 3f32df1dbe6..0e4e880e77d 100644 --- a/src/test/librbd/test_librbd.cc +++ b/src/test/librbd/test_librbd.cc @@ -4781,6 +4781,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 5bd6c53a469..ed4dc16a00c 100644 --- a/src/test/rbd_mirror/test_ImageReplayer.cc +++ b/src/test/rbd_mirror/test_ImageReplayer.cc @@ -429,7 +429,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));