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;
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;
+ }
}
}
}
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;
int mirror_image_status_summary(IoCtx& io_ctx,
std::map<mirror_image_status_state_t, int> *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);
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) {
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)
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));
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));