]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd/api: disallow mirror image operations on a group's member image
authorRamana Raja <rraja@redhat.com>
Thu, 20 Feb 2025 00:09:32 +0000 (19:09 -0500)
committerPrasanna Kumar Kalever <prasanna.kalever@redhat.com>
Thu, 24 Apr 2025 15:56:31 +0000 (21:26 +0530)
Disallow the following mirror image APIs when called directly on an
image that is member of a group:
- mirror image demote
- mirror image disable
- mirror image enable
- mirror image promote
- mirror image resync
- mirror image snapshot

Only allow mirror operations on a group's member image via the mirror
group APIs.

Signed-off-by: Ramana Raja <rraja@redhat.com>
src/librbd/api/Mirror.cc
src/librbd/api/Mirror.h

index fcaa0879ed68ede4d2b450e7b36455ea9f2e8fd3..a6a7450c6149d0e8c594b21805e93794867b5b96 100644 (file)
@@ -640,6 +640,14 @@ int Mirror<I>::image_enable(I *ictx,
     return r;
   }
 
+  if (group_snap_id.empty() &&
+      (ictx->group_spec.pool_id != RBD_GROUP_INVALID_POOL)) {
+    r = -EINVAL;
+    lderr(cct) << "cannot enable mirroring on an image that is member of a group"
+               << cpp_strerror(r) << dendl;
+    return r;
+  }
+
   cls::rbd::MirrorMode mirror_mode;
   r = cls_client::mirror_mode_get(&ictx->md_ctx, &mirror_mode);
   if (r < 0) {
@@ -710,6 +718,11 @@ int Mirror<I>::image_enable(I *ictx,
 
 template <typename I>
 int Mirror<I>::image_disable(I *ictx, bool force) {
+  return Mirror<I>::image_disable(ictx, force, false);
+}
+
+template <typename I>
+int Mirror<I>::image_disable(I *ictx, bool force, bool allow_group_member) {
   CephContext *cct = ictx->cct;
   ldout(cct, 20) << "ictx=" << ictx << dendl;
 
@@ -719,6 +732,14 @@ int Mirror<I>::image_disable(I *ictx, bool force) {
     return r;
   }
 
+  if (!allow_group_member &&
+      (ictx->group_spec.pool_id != RBD_GROUP_INVALID_POOL)) {
+    r = -EINVAL;
+    lderr(cct) << "cannot disable mirroring on an image that is member of a group"
+               << cpp_strerror(r) << dendl;
+    return r;
+  }
+
   cls::rbd::MirrorMode mirror_mode;
   r = cls_client::mirror_mode_get(&ictx->md_ctx, &mirror_mode);
   if (r < 0) {
@@ -930,6 +951,14 @@ void Mirror<I>::image_promote(I *ictx,
         return;
       }
 
+      if (group_snap_id.empty() &&
+          (ictx->group_spec.pool_id != RBD_GROUP_INVALID_POOL)) {
+        lderr(ictx->cct) << "cannot promote an image that is member of a group"
+                         << cpp_strerror(-EINVAL) << dendl;
+        on_promote->complete(-EINVAL);
+        return;
+      }
+
       auto req = mirror::PromoteRequest<>::create(*ictx, force,
                                                   ictx->group_spec.pool_id,
                                                   ictx->group_spec.group_id,
@@ -984,6 +1013,14 @@ void Mirror<I>::image_demote(I *ictx,
         return;
       }
 
+      if (group_snap_id.empty() &&
+          (ictx->group_spec.pool_id != RBD_GROUP_INVALID_POOL)) {
+        lderr(ictx->cct) << "cannot demote an image that is member of a group"
+                         << cpp_strerror(-EINVAL) << dendl;
+        on_cleanup->complete(-EINVAL);
+        return;
+      }
+
       auto req = mirror::DemoteRequest<>::create(*ictx,
                                                  ictx->group_spec.pool_id,
                                                  ictx->group_spec.group_id,
@@ -1012,6 +1049,13 @@ int Mirror<I>::image_resync(I *ictx) {
     return r;
   }
 
+  if (ictx->group_spec.pool_id != RBD_GROUP_INVALID_POOL) {
+    r = -EINVAL;
+    lderr(cct) << "cannot resync image that is member of a group"
+               << cpp_strerror(r) << dendl;
+    return r;
+  }
+
   cls::rbd::MirrorImage mirror_image;
   mirror::PromotionState promotion_state;
   std::string primary_mirror_uuid;
@@ -2386,6 +2430,15 @@ void Mirror<I>::image_snapshot_create(I *ictx, uint32_t flags,
         return;
       }
 
+      if (group_snap_id.empty() &&
+          (ictx->group_spec.pool_id != RBD_GROUP_INVALID_POOL)) {
+        lderr(ictx->cct) << "cannot create mirror snapshot of an image "
+                         << "that is member of a group"
+                         << cpp_strerror(-EINVAL) << dendl;
+        on_finish->complete(-EINVAL);
+        return;
+      }
+
       auto ctx = new C_ImageSnapshotCreate<I>(ictx, snap_create_flags,
                                               ictx->group_spec.pool_id,
                                               ictx->group_spec.group_id,
@@ -2803,7 +2856,7 @@ int Mirror<I>::group_enable(IoCtx& group_ioctx, const char *group_name,
       if (snap_ids[i] == CEPH_NOSNAP) {
         continue;
       }
-      r = image_disable(image_ctxs[i], false);
+      r = image_disable(image_ctxs[i], false, true);
       if (r < 0) {
         lderr(cct) << "failed to disable mirroring on image: "
                    << image_ctxs[i]->name << cpp_strerror(r) << dendl;
@@ -2923,7 +2976,7 @@ int Mirror<I>::group_disable(IoCtx& group_ioctx, const char *group_name,
   for (auto image_ctx : image_ctxs) {
     ldout(cct, 10) << "attempting to disable image with id " << image_ctx->id
                    << ": " << cpp_strerror(r) << dendl;
-    r = image_disable(image_ctx, force);
+    r = image_disable(image_ctx, force, true);
     if (r < 0) {
       lderr(cct) << "failed to disable mirroring on image: " << image_ctx->name
                  << cpp_strerror(r) << dendl;
index 22ab9d95dfb79ffc990f76cd1499f18f4acfa369..6e5c4358090da891334c32e426ed041cc9211d8b 100644 (file)
@@ -96,6 +96,8 @@ struct Mirror {
                           bool relax_same_pool_parent_check,
                           uint64_t *snap_id);
   static int image_disable(ImageCtxT *ictx, bool force);
+  static int image_disable(ImageCtxT *ictx, bool force,
+                           bool allow_group_member);
   static int image_promote(ImageCtxT *ictx, bool force);
   static void image_promote(ImageCtxT *ictx, bool force, Context *on_finish);
   static void image_promote(ImageCtxT *ictx,