]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/librbd/mirror/snapshot/CreatePrimaryRequest.cc
update ceph source to reef 18.2.1
[ceph.git] / ceph / src / librbd / mirror / snapshot / CreatePrimaryRequest.cc
index fd6f9b5023d2a4cdb866f9a520418d628c350695..c8e3a4fe7a6e6f4abbac7dec654a1c61dd60e50e 100644 (file)
@@ -177,6 +177,7 @@ void CreatePrimaryRequest<I>::handle_refresh_image(int r) {
 
 template <typename I>
 void CreatePrimaryRequest<I>::unlink_peer() {
+  // TODO: Document semantics for unlink_peer
   uint64_t max_snapshots = m_image_ctx->config.template get_val<uint64_t>(
     "rbd_mirroring_max_mirroring_snapshots");
   ceph_assert(max_snapshots >= 3);
@@ -184,55 +185,61 @@ void CreatePrimaryRequest<I>::unlink_peer() {
   std::string peer_uuid;
   uint64_t snap_id = CEPH_NOSNAP;
 
-  for (auto &peer : m_mirror_peer_uuids) {
+  {
     std::shared_lock image_locker{m_image_ctx->image_lock};
-    size_t count = 0;
-    uint64_t unlink_snap_id = 0;
-    for (auto &snap_it : m_image_ctx->snap_info) {
-      auto info = std::get_if<cls::rbd::MirrorSnapshotNamespace>(
-        &snap_it.second.snap_namespace);
-      if (info == nullptr) {
-        continue;
-      }
-      if (info->state != cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY) {
-        // reset counters -- we count primary snapshots after the last promotion
-        count = 0;
-        unlink_snap_id = 0;
-        continue;
-      }
-      // call UnlinkPeerRequest only if the snapshot is linked with this peer
-      // or if it's not linked with any peer (happens if mirroring is enabled
-      // on a pool with no peers configured or if UnlinkPeerRequest gets
-      // interrupted)
-      if (!info->mirror_peer_uuids.empty() &&
-          info->mirror_peer_uuids.count(peer) == 0) {
-        continue;
-      }
-      if (info->mirror_peer_uuids.empty() || !info->complete) {
-        peer_uuid = peer;
-        snap_id = snap_it.first;
-        break;
-      }
-      count++;
-      if (count == max_snapshots) {
-        unlink_snap_id = snap_it.first;
-      }
-      if (count > max_snapshots) {
-        peer_uuid = peer;
-        snap_id = unlink_snap_id;
-        break;
+    for (const auto& peer : m_mirror_peer_uuids) {
+      for (const auto& snap_info_pair : m_image_ctx->snap_info) {
+        auto info = std::get_if<cls::rbd::MirrorSnapshotNamespace>(
+          &snap_info_pair.second.snap_namespace);
+        if (info == nullptr) {
+          continue;
+        }
+        if (info->mirror_peer_uuids.empty() ||
+            (info->mirror_peer_uuids.count(peer) != 0 &&
+             info->is_primary() && !info->complete)) {
+          peer_uuid = peer;
+          snap_id = snap_info_pair.first;
+          goto do_unlink;
+        }
       }
     }
-    if (snap_id != CEPH_NOSNAP) {
-      break;
+    for (const auto& peer : m_mirror_peer_uuids) {
+      size_t count = 0;
+      uint64_t unlink_snap_id = 0;
+      for (const auto& snap_info_pair : m_image_ctx->snap_info) {
+        auto info = std::get_if<cls::rbd::MirrorSnapshotNamespace>(
+          &snap_info_pair.second.snap_namespace);
+        if (info == nullptr) {
+          continue;
+        }
+        if (info->state != cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY) {
+          // reset counters -- we count primary snapshots after the last
+          // promotion
+          count = 0;
+          unlink_snap_id = 0;
+          continue;
+        }
+        if (info->mirror_peer_uuids.count(peer) == 0) {
+          // snapshot is not linked with this peer
+          continue;
+        }
+        count++;
+        if (count == max_snapshots) {
+          unlink_snap_id = snap_info_pair.first;
+        }
+        if (count > max_snapshots) {
+          peer_uuid = peer;
+          snap_id = unlink_snap_id;
+          goto do_unlink;
+        }
+      }
     }
   }
 
-  if (snap_id == CEPH_NOSNAP) {
-    finish(0);
-    return;
-  }
+  finish(0);
+  return;
 
+do_unlink:
   CephContext *cct = m_image_ctx->cct;
   ldout(cct, 15) << "peer=" << peer_uuid << ", snap_id=" << snap_id << dendl;