]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-mirror: rollback to last good snapshot just while force promote
authorPrasanna Kumar Kalever <prasanna.kalever@redhat.com>
Mon, 2 Sep 2024 08:54:35 +0000 (14:24 +0530)
committerPrasanna Kumar Kalever <prasanna.kalever@redhat.com>
Thu, 24 Apr 2025 15:56:25 +0000 (21:26 +0530)
fix the group membership to match the rollback snapshot

Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
src/cls/rbd/cls_rbd_types.h
src/librbd/api/Group.cc
src/librbd/api/Mirror.cc

index df112412cc6d1ae3384ec0f95d2d4918390100db..cfdf1b55517f3d1ee0c0ad1c4d21fd0a4fe8aba7 100644 (file)
@@ -584,7 +584,16 @@ struct GroupImageSpec {
 
   std::string image_key();
 
-  bool operator==(const GroupImageSpec&) const = default;
+  inline bool operator==(const GroupImageSpec& rhs) const {
+    return (pool_id == rhs.pool_id &&
+            image_id == rhs.image_id);
+  }
+  inline bool operator<(const GroupImageSpec& rhs) const {
+    if (pool_id != rhs.pool_id) {
+      return pool_id < rhs.pool_id;
+    }
+    return image_id < rhs.image_id;
+  }
 };
 WRITE_CLASS_ENCODER(GroupImageSpec);
 
index 62b8cac02615660daece415acc178779777f9789..b03749557199557a46c9ad29b0bd7a485834d0dc 100644 (file)
@@ -1144,7 +1144,7 @@ int Group<I>::snap_rollback(librados::IoCtx& group_ioctx,
 
   cls::rbd::GroupSnapshot *group_snap = nullptr;
   for (auto &snap : snaps) {
-    if (is_user_snapshot(snap) && snap.name == string(snap_name)) {
+    if (snap.name == string(snap_name)) {
       group_snap = &snap;
       break;
     }
index 9fa41145b14cc57bfb6ae26aebdca723c1fcf801..6ff5036a7c60fdf504c34db71473c85808a83e8a 100644 (file)
@@ -2933,6 +2933,118 @@ int Mirror<I>::group_promote(IoCtx& group_ioctx, const char *group_name,
     lderr(cct) << "group " << group_name
                << " is still primary within a remote cluster" << dendl;
     return -EBUSY;
+  } else if (force) {
+    std::vector<cls::rbd::GroupImageStatus> images;
+    r = Group<I>::group_image_list_by_id(group_ioctx, group_id, &images);
+    if (r < 0) {
+      lderr(cct) << "failed listing images in the group: " << group_name
+                 << " :" << cpp_strerror(r) << dendl;
+      return r;
+    }
+    std::vector<cls::rbd::GroupImageSpec> current_images;
+    for (const auto& image : images) {
+      if (image.state == cls::rbd::GROUP_IMAGE_LINK_STATE_ATTACHED) {
+        current_images.push_back(image.spec);
+      }
+    }
+    // rollback to last good group snapshot
+    std::vector<cls::rbd::GroupSnapshot> snaps;
+    C_SaferCond cond;
+    auto req = group::ListSnapshotsRequest<>::create(group_ioctx, group_id,
+                                                     true, true, &snaps, &cond);
+    req->send();
+    int r = cond.wait();
+    if (r < 0) {
+      lderr(cct) << "failed to list snapshots in the group " << group_name
+                 << " :" << cpp_strerror(r) << dendl;
+      return r;
+    }
+    auto snap =  snaps.rbegin();
+    for (; snap != snaps.rend(); ++snap) {
+      if (snap->state == cls::rbd::GROUP_SNAPSHOT_STATE_INCOMPLETE) {
+        continue;
+      }
+      break;
+    }
+    if (snap != snaps.rend()) {
+      // Check for group membership match
+      std::vector<cls::rbd::GroupImageSpec> rollback_images;
+      for (auto& it : snap->snaps) {
+        rollback_images.emplace_back(it.image_id, it.pool);
+      }
+
+      if (rollback_images != current_images) {
+        lderr(cct) << "group snapshot membership does not match group membership"
+                   << dendl;
+        // Fix the group membership
+        std::vector<cls::rbd::GroupImageSpec> delta_images;
+        std::set_difference(current_images.begin(), current_images.end(),
+                            rollback_images.begin(), rollback_images.end(),
+                            std::back_inserter(delta_images));
+
+        std::vector<cls::rbd::GroupImageSpec> removed_images; // from current membership
+        std::vector<cls::rbd::GroupImageSpec> inserted_images; // to current membership
+        if (!delta_images.empty()) {
+          for (auto &s : delta_images) {
+            if (std::find(rollback_images.begin(), rollback_images.end(), s)
+                != rollback_images.end()) {
+              removed_images.push_back(s);
+            } else {
+              inserted_images.push_back(s);
+            }
+          }
+        }
+        if (!removed_images.empty()) {
+          // insert back to membership
+          for (auto &s : removed_images) {
+            IoCtx image_ioctx;
+            r = librbd::util::create_ioctx(group_ioctx, "image", s.pool_id, {},
+                                           &image_ioctx);
+            if (r < 0) {
+              return r;
+            }
+
+            r = Group<I>::image_add(group_ioctx, group_name,
+                                    image_ioctx, s.image_id.c_str(), 0);
+            if (r < 0) {
+              lderr(cct) << "error inserting image to group: " << group_name
+                         << " :" << cpp_strerror(r) << dendl;
+              return r;
+            }
+          }
+        }
+
+        if(!inserted_images.empty()) {
+          // remove from the membershiip
+          for (auto &s : inserted_images) {
+            IoCtx image_ioctx;
+            r = librbd::util::create_ioctx(group_ioctx, "image", s.pool_id, {},
+                                           &image_ioctx);
+            if (r < 0) {
+              return r;
+            }
+            r = Group<I>::image_remove(group_ioctx, group_name,
+                                       image_ioctx, s.image_id.c_str(), 0);
+            if (r < 0 && r != -ENOENT) {
+              lderr(cct) << "error removing image from a group: " << group_name
+                         << " :" << cpp_strerror(r) << dendl;
+              return r;
+            }
+          }
+        }
+      } // Fixing membership done.
+
+      librbd::NoOpProgressContext prog_ctx;
+      r = Group<I>::snap_rollback(group_ioctx,
+                                  group_name, snap->name.c_str(), prog_ctx);
+      if (r < 0) {
+        lderr(cct) << "failed to rollback to group snapshot: " << snap->name
+                   << " :" << cpp_strerror(r) << dendl;
+        return r;
+      }
+      ldout(cct, 5) << "successfully rollbacked to group snapshot: "
+                    << snap->name << dendl;
+    } // Rollback to last good snapshot done
   }
 
   std::string group_snap_id = librbd::util::generate_image_id(group_ioctx);