]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-mirror: support mirroring regular non-mirror group snapshots
authorPrasanna Kumar Kalever <prasanna.kalever@redhat.com>
Mon, 22 Apr 2024 11:37:01 +0000 (17:07 +0530)
committerPrasanna Kumar Kalever <prasanna.kalever@redhat.com>
Thu, 24 Apr 2025 15:56:24 +0000 (21:26 +0530)
This commit also enable deep copying `.group` snaps.

$ rbd --cluster site-a snap ls pool1/test_image1 --all --debug-rbd=0
SNAPID  NAME                                                                                       SIZE     PROTECTED  TIMESTAMP                 NAMESPACE
     4  .group.2_10416b8b4567_104d6b8b4567                                                         128 MiB             Mon Apr 22 17:07:57 2024  group (pool1/test_group@group_snap1)
     7  .group.2_10416b8b4567_104f6b8b4567                                                         128 MiB             Mon Apr 22 17:07:59 2024  group (pool1/test_group@group_snap2)
     8  .mirror.primary.72855be4-1ffb-4094-8426-fb1d5f082c21.71b62dad-f515-43cf-91b2-bf1225c5a0fc  128 MiB             Mon Apr 22 17:08:03 2024  mirror (primary peer_uuids:[5f9ea7aa-fa5b-4d2e-a098-3afe006361aa])

$ rbd --cluster site-b snap ls pool1/test_image1 --all --debug-rbd=0
SNAPID  NAME                                                                                           SIZE     PROTECTED  TIMESTAMP                 NAMESPACE
     5  .group.2_10416b8b4567_104d6b8b4567                                                             128 MiB             Mon Apr 22 17:08:07 2024  group
     7  .group.2_10416b8b4567_104f6b8b4567                                                             128 MiB             Mon Apr 22 17:08:08 2024  group
     8  .mirror.non_primary.72855be4-1ffb-4094-8426-fb1d5f082c21.64488da7-3350-4d04-8e4d-90047182e004  128 MiB             Mon Apr 22 17:08:09 2024  mirror (non-primary peer_uuids:[] 6d963873-6679-483b-b05a-8bf2536f4fdf:8 copied)

$ rbd --cluster site-a group snap ls pool1/test_group --debug-rbd=0
NAME                                 STATUS
group_snap1                              ok
group_snap2                              ok
.mirror.2_10416b8b4567_10536b8b4567      ok

$ rbd --cluster site-b group snap ls pool1/test_group --debug-rbd=0
NAME                                 STATUS
.mirror.2_10376b8b4567_1037327b23c6      ok
group_snap1                              ok
group_snap2                              ok
.mirror.2_10416b8b4567_10536b8b4567      ok

Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
src/librbd/deep_copy/SnapshotCopyRequest.cc
src/tools/rbd_mirror/GroupReplayer.cc
src/tools/rbd_mirror/GroupReplayer.h
src/tools/rbd_mirror/ImageReplayer.cc
src/tools/rbd_mirror/Types.h
src/tools/rbd_mirror/group_replayer/BootstrapRequest.cc
src/tools/rbd_mirror/group_replayer/BootstrapRequest.h
src/tools/rbd_mirror/image_replayer/ReplayerListener.h
src/tools/rbd_mirror/image_replayer/snapshot/Replayer.cc
src/tools/rbd_mirror/image_replayer/snapshot/Replayer.h

index 1de77a3bfb10bea7251fb431384237a755e989b6..9507df4b906292f4fd2218ebf63fb49152d94455 100644 (file)
@@ -357,7 +357,8 @@ void SnapshotCopyRequest<I>::send_snap_create() {
 
     if (m_snap_seqs.find(src_snap_id) == m_snap_seqs.end()) {
       // the source snapshot is not in our mapping table, ...
-      if (std::holds_alternative<cls::rbd::UserSnapshotNamespace>(snap_namespace)) {
+      if (std::holds_alternative<cls::rbd::UserSnapshotNamespace>(snap_namespace) ||
+          std::holds_alternative<cls::rbd::GroupImageSnapshotNamespace>(snap_namespace)) {
         // ... create it since it's a user snapshot
         break;
       } else if (src_snap_id == m_src_snap_id_end) {
@@ -443,6 +444,10 @@ void SnapshotCopyRequest<I>::handle_snap_create(int r) {
 
   auto snap_it = m_dst_image_ctx->snap_ids.find(
       {cls::rbd::UserSnapshotNamespace(), m_snap_name});
+  if (snap_it == m_dst_image_ctx->snap_ids.end()) {
+    snap_it = m_dst_image_ctx->snap_ids.find(
+        {cls::rbd::GroupImageSnapshotNamespace(), m_snap_name});
+  }
   ceph_assert(snap_it != m_dst_image_ctx->snap_ids.end());
   librados::snap_t dst_snap_id = snap_it->second;
 
index de18bfdc25d1b268ff04a99d39eb6186de99dff3..061be0bc1d87c504552c764c5e8827d242bc1263 100644 (file)
@@ -4,11 +4,13 @@
 #include "include/stringify.h"
 #include "common/Formatter.h"
 #include "common/admin_socket.h"
+#include "common/Cond.h"
 #include "common/debug.h"
 #include "common/errno.h"
 #include "librbd/ImageCtx.h"
 #include "librbd/Utils.h"
 #include "librbd/asio/ContextWQ.h"
+#include "librbd/group/ListSnapshotsRequest.h"
 #include "tools/rbd_mirror/ImageReplayer.h"
 #include "tools/rbd_mirror/MirrorStatusUpdater.h"
 #include "tools/rbd_mirror/Threads.h"
@@ -332,7 +334,6 @@ void GroupReplayer<I>::start(Context *on_finish, bool manual, bool restart) {
       m_last_r = 0;
       m_state_desc.clear();
       m_local_group_snaps.clear();
-      m_remote_group_snaps.clear();
       m_image_replayers.clear();
       m_image_replayer_index.clear();
       m_get_remote_group_snap_ret_vals.clear();
@@ -378,7 +379,7 @@ void GroupReplayer<I>::stop(Context *on_finish, bool manual, bool restart) {
       }
     } else {
       dout(10) << "replayers still running" << dendl;
-      if (!is_stopped_()) {
+      if (!is_stopped_() || m_state == STATE_STOPPING) {
        if (m_state == STATE_STARTING) {
          dout(10) << "canceling start" << dendl;
          if (m_bootstrap_request != nullptr) {
@@ -536,7 +537,8 @@ void GroupReplayer<I>::bootstrap_group() {
     m_local_mirror_uuid, m_instance_watcher, m_local_status_updater,
     m_remote_group_peer.mirror_status_updater, m_cache_manager_handler,
     m_pool_meta_cache, &m_local_group_id, &m_remote_group_id,
-    &m_local_group_ctx, &m_image_replayers, &m_image_replayer_index, ctx);
+    &m_local_group_snaps, &m_local_group_ctx, &m_image_replayers,
+    &m_image_replayer_index, ctx);
 
   request->get();
   m_bootstrap_request = request;
@@ -858,6 +860,204 @@ void GroupReplayer<I>::set_mirror_group_status_update(
   }
 }
 
+template <typename I>
+void GroupReplayer<I>::create_regular_group_snapshot(
+    const std::string &remote_group_snap_name,
+    const std::string &remote_group_snap_id,
+    std::vector<cls::rbd::GroupImageStatus> *local_images,
+    Context *on_finish) {
+  // each image will have one snapshot specific to group snap, and so for each
+  // image get a ImageSnapshotSpec and prepare a vector
+  // for image :: <images in that group> {
+  //   * get snap whos name has group snap_id for that we can list snaps and
+  //     filter with remote_group_snap_id
+  //   * get its { pool_id, snap_id, image_id }
+  // }
+  // finally write to the object
+  dout(10) << dendl;
+  librados::ObjectWriteOperation op;
+  cls::rbd::GroupSnapshot group_snap{
+    remote_group_snap_id, // keeping it same as remote group snap id
+    cls::rbd::UserGroupSnapshotNamespace{},
+      remote_group_snap_name,
+      cls::rbd::GROUP_SNAPSHOT_STATE_INCOMPLETE};
+  librbd::cls_client::group_snap_set(&op, group_snap);
+  if (m_local_group_snaps.find(group_snap.id) == m_local_group_snaps.end()) {
+    m_local_group_snaps.insert(make_pair(group_snap.id, group_snap));
+  }
+
+  std::vector<cls::rbd::ImageSnapshotSpec> local_image_snap_specs;
+  local_image_snap_specs = std::vector<cls::rbd::ImageSnapshotSpec>(
+      local_images->size(), cls::rbd::ImageSnapshotSpec());
+  for (auto& image : *local_images) {
+    std::string image_header_oid = librbd::util::header_name(
+        image.spec.image_id);
+    ::SnapContext snapc;
+    int r = librbd::cls_client::get_snapcontext(&m_local_io_ctx,
+                                                image_header_oid, &snapc);
+    if (r < 0) {
+      derr << "get snap context failed: " << cpp_strerror(r) << dendl;
+      on_finish->complete(r);
+      return;
+    }
+
+    auto image_snap_name = ".group." + std::to_string(image.spec.pool_id) +
+                           "_" + m_remote_group_id + "_" + remote_group_snap_id;
+    // stored in reverse order
+    for (auto snap_id : snapc.snaps) {
+      cls::rbd::SnapshotInfo snap_info;
+      r = librbd::cls_client::snapshot_get(&m_local_io_ctx, image_header_oid,
+                                           snap_id, &snap_info);
+      if (r < 0) {
+        derr << "failed getting snap info for snap id: " << snap_id
+          << ", : " << cpp_strerror(r) << dendl;
+        on_finish->complete(r);
+        return;
+      }
+
+      // extract { pool_id, snap_id, image_id }
+      if (snap_info.name == image_snap_name) {
+        cls::rbd::ImageSnapshotSpec snap_spec;
+        snap_spec.pool = image.spec.pool_id;
+        snap_spec.image_id = image.spec.image_id;
+        snap_spec.snap_id = snap_info.id;
+
+        local_image_snap_specs.push_back(snap_spec);
+      }
+    }
+  }
+
+  group_snap.snaps = local_image_snap_specs;
+  group_snap.state = cls::rbd::GROUP_SNAPSHOT_STATE_COMPLETE;
+  librbd::cls_client::group_snap_set(&op, group_snap);
+  m_local_group_snaps[group_snap.id] = group_snap;
+
+  auto comp = create_rados_callback(
+      new LambdaContext([this, on_finish](int r) {
+        handle_create_regular_group_snapshot(r, on_finish);
+      }));
+  int r = m_local_io_ctx.aio_operate(
+      librbd::util::group_header_name(m_local_group_ctx.group_id), comp, &op);
+  ceph_assert(r == 0);
+  comp->release();
+}
+
+template <typename I>
+void GroupReplayer<I>::handle_create_regular_group_snapshot(
+    int r, Context *on_finish) {
+  dout(10) << "r=" << r << dendl;
+
+  if (r < 0) {
+    derr << "error creating local non-primary group snapshot: "
+         << cpp_strerror(r) << dendl;
+  }
+
+  on_finish->complete(0);
+}
+
+template <typename I>
+void GroupReplayer<I>::list_remote_group_snapshots(Context *on_finish) {
+  dout(10) << dendl;
+
+  remote_group_snaps.clear();
+  auto ctx = new LambdaContext(
+    [this, on_finish] (int r)  {
+        handle_list_remote_group_snapshots(r, on_finish);
+  });
+
+  auto req = librbd::group::ListSnapshotsRequest<I>::create(
+      m_remote_group_peer.io_ctx, m_remote_group_id, &remote_group_snaps, ctx);
+  req->send();
+}
+
+template <typename I>
+void GroupReplayer<I>::handle_list_remote_group_snapshots(int r,
+                                                          Context *on_finish) {
+  dout(10) << "r=" << r << dendl;
+  std::unique_lock locker{m_lock};
+
+  if (r < 0) {
+    derr << "error listing remote mirror group snapshots: " << cpp_strerror(r)
+         << dendl;
+    on_finish->complete(r);
+    return;
+  }
+
+  m_remote_group_snaps.clear();
+  for (auto it : remote_group_snaps) {
+    dout(10) << "found remote group snap id: " << it.id << dendl;
+    m_remote_group_snaps.insert(make_pair(it.id, it));
+  }
+
+  std::vector<cls::rbd::GroupImageStatus> local_images;
+  std::vector<C_SaferCond*> on_finishes;
+  for (auto it = m_remote_group_snaps.begin(); it != m_remote_group_snaps.end(); ++it) {
+    auto snap_type = cls::rbd::get_group_snap_namespace_type(
+        it->second.snapshot_namespace);
+    if (snap_type == cls::rbd::GROUP_SNAPSHOT_NAMESPACE_TYPE_USER) {
+      dout(10) << "found user snap, snap name: " << it->second.name
+               << ", remote group snap id: " << it->second.id << dendl;
+      if (local_images.empty()) {
+        r = local_group_image_list_by_id(&local_images);
+        if (r < 0) {
+          locker.unlock();
+          on_finish->complete(r);
+          return;
+        }
+      }
+      if (m_local_group_snaps.find(it->second.id) == m_local_group_snaps.end()) {
+        C_SaferCond* ctx = new C_SaferCond;
+        create_regular_group_snapshot(it->second.name,
+                                      it->second.id, &local_images, ctx);
+        on_finishes.push_back(ctx);
+      }
+    }
+  }
+
+  for (auto &finish : on_finishes) {
+    finish->wait();
+  }
+
+  locker.unlock();
+  on_finish->complete(0);
+}
+
+template <typename I>
+int GroupReplayer<I>::local_group_image_list_by_id(
+    std::vector<cls::rbd::GroupImageStatus> *image_ids) {
+  std::string group_header_oid = librbd::util::group_header_name(
+      m_local_group_ctx.group_id);
+
+  dout(10) << "listing images in local group id " << group_header_oid << dendl;
+  image_ids->clear();
+
+  int r = 0;
+  const int max_read = 1024;
+  cls::rbd::GroupImageSpec start_last;
+  do {
+    std::vector<cls::rbd::GroupImageStatus> image_ids_page;
+
+    r = librbd::cls_client::group_image_list(&m_local_io_ctx, group_header_oid,
+                                             start_last, max_read,
+                                             &image_ids_page);
+
+    if (r < 0) {
+      derr << "error reading image list from local group: "
+           << cpp_strerror(-r) << dendl;
+      return r;
+    }
+    image_ids->insert(image_ids->end(), image_ids_page.begin(),
+                      image_ids_page.end());
+
+    if (image_ids_page.size() > 0)
+      start_last = image_ids_page.rbegin()->spec;
+
+    r = image_ids_page.size();
+  } while (r == max_read);
+
+  return 0;
+}
+
 template <typename I>
 void GroupReplayer<I>::create_mirror_snapshot_start(
     const cls::rbd::MirrorSnapshotNamespace &remote_group_snap_ns,
@@ -1035,7 +1235,6 @@ void GroupReplayer<I>::handle_get_remote_group_snapshot(
   if (m_state == STATE_STOPPING) {
     dout(20) << "interrupted" << dendl;
     m_local_group_snaps.erase(remote_group_snap_id);
-    m_remote_group_snaps.erase(remote_group_snap_id);
     auto create_snap_requests = m_create_snap_requests[remote_group_snap_id];
     m_create_snap_requests.erase(remote_group_snap_id);
     bool shut_down_replay = m_pending_snap_create.empty() &&
@@ -1074,7 +1273,6 @@ void GroupReplayer<I>::handle_create_mirror_snapshot_start(
     r = 0;
   } else if (r < 0) {
     m_pending_snap_create.erase(remote_group_snap_id);
-    m_remote_group_snaps.erase(remote_group_snap_id);
     m_local_group_snaps.erase(remote_group_snap_id);
     shut_down_replay = m_state == STATE_STOPPING && !m_restart_requested &&
                        m_pending_snap_create.empty() &&
index 08e4d89f15b2a630c3da410c3be0f258530f1997..92c76459bf4f1a731cb847e7215fe7a176cc9288 100644 (file)
@@ -171,6 +171,10 @@ private:
     Listener(GroupReplayer *group_replayer) : group_replayer(group_replayer) {
     }
 
+    void list_remote_group_snapshots(Context *on_finish) override {
+      group_replayer->list_remote_group_snapshots(on_finish);
+    }
+
     void create_mirror_snapshot_start(
         const cls::rbd::MirrorSnapshotNamespace &remote_group_snap_ns,
         void *arg, int64_t *local_group_pool_id, std::string *local_group_id,
@@ -242,6 +246,7 @@ private:
   std::map<std::pair<int64_t, std::string>, ImageReplayer<ImageCtxT> *> m_image_replayer_index;
   std::map<std::string, cls::rbd::GroupSnapshot> m_local_group_snaps;
   std::map<std::string, cls::rbd::GroupSnapshot> m_remote_group_snaps;
+  std::vector<cls::rbd::GroupSnapshot> remote_group_snaps;
   std::map<std::string, int> m_get_remote_group_snap_ret_vals;
   std::map<std::string, std::map<ImageReplayer<ImageCtxT> *, Context *>> m_create_snap_requests;
   std::set<std::string> m_pending_snap_create;
@@ -291,6 +296,14 @@ private:
   void set_mirror_group_status_update(cls::rbd::MirrorGroupStatusState state,
                                       const std::string &desc);
 
+  void create_regular_group_snapshot(const std::string &remote_snap_name,
+                                     const std::string &remote_snap_id,
+                                     std::vector<cls::rbd::GroupImageStatus> *local_images,
+                                     Context *on_finish);
+  void handle_create_regular_group_snapshot(int r, Context *on_finish);
+  void list_remote_group_snapshots(Context *on_finish);
+  void handle_list_remote_group_snapshots(int r, Context *on_finish);
+  int local_group_image_list_by_id(std::vector<cls::rbd::GroupImageStatus> *image_ids);
   void create_mirror_snapshot_start(
       const cls::rbd::MirrorSnapshotNamespace &remote_group_snap_ns,
       ImageReplayer<ImageCtxT> *image_replayer, int64_t *local_group_pool_id,
index 98da0f3f588cb614c63a0bb620719032f7d634cc..22a705b77650c9dccbca8fc4cb7a6d9f3373cb53 100644 (file)
@@ -212,6 +212,15 @@ struct ImageReplayer<I>::ReplayerListener
     image_replayer->handle_replayer_notification();
   }
 
+  void list_remote_group_snapshots(Context *on_finish) override {
+    if (local_group_ctx == nullptr) {
+      on_finish->complete(0);
+      return;
+    }
+
+    local_group_ctx->listener->list_remote_group_snapshots(on_finish);
+  }
+
   void create_mirror_snapshot_start(
       const cls::rbd::MirrorSnapshotNamespace &remote_group_snap_ns,
       int64_t *local_group_pool_id, std::string *local_group_id,
index 997e0ee62a241362f0ff15ee3db7fb85068f11a5..9eb23936dc040a57f306a092b6cd36bc6b46261e 100644 (file)
@@ -183,6 +183,8 @@ struct GroupCtx {
     virtual ~Listener() {
     }
 
+    virtual void list_remote_group_snapshots(Context *on_finish) = 0;
+
     virtual void create_mirror_snapshot_start(
         const cls::rbd::MirrorSnapshotNamespace &remote_group_snap_ns,
         void *arg, int64_t *local_group_pool_id, std::string *local_group_id,
index 035e736672e7525d15e3b1fa8c0f0338d2a5dacc..aae48f8b7e9272b93b89d824defb3580c3e52556 100644 (file)
@@ -80,6 +80,7 @@ BootstrapRequest<I>::BootstrapRequest(
     PoolMetaCache *pool_meta_cache,
     std::string *local_group_id,
     std::string *remote_group_id,
+    std::map<std::string, cls::rbd::GroupSnapshot> *local_group_snaps,
     GroupCtx *local_group_ctx,
     std::list<std::pair<librados::IoCtx, ImageReplayer<I> *>> *image_replayers,
     std::map<std::pair<int64_t, std::string>, ImageReplayer<I> *> *image_replayer_index,
@@ -99,6 +100,7 @@ BootstrapRequest<I>::BootstrapRequest(
     m_pool_meta_cache(pool_meta_cache),
     m_local_group_id(local_group_id),
     m_remote_group_id(remote_group_id),
+    m_local_group_snaps(local_group_snaps),
     m_local_group_ctx(local_group_ctx),
     m_image_replayers(image_replayers),
     m_image_replayer_index(image_replayer_index),
@@ -301,7 +303,7 @@ void BootstrapRequest<I>::list_remote_group_snapshots() {
       &BootstrapRequest<I>::handle_list_remote_group_snapshots>(this);
 
   auto req = librbd::group::ListSnapshotsRequest<I>::create(m_remote_io_ctx,
-      *m_remote_group_id, true, true, &m_remote_group_snaps, ctx);
+      *m_remote_group_id, true, true, &remote_group_snaps, ctx);
   req->send();
 }
 
@@ -323,7 +325,7 @@ void BootstrapRequest<I>::handle_list_remote_group_snapshots(int r) {
 
   if (m_remote_mirror_group.state == cls::rbd::MIRROR_GROUP_STATE_ENABLED) {
     cls::rbd::MirrorSnapshotState state;
-    r = get_last_mirror_snapshot_state(m_remote_group_snaps, &state);
+    r = get_last_mirror_snapshot_state(remote_group_snaps, &state);
     if (r == -ENOENT) {
       derr << "failed to find remote mirror group snapshot" << dendl;
       finish(-EINVAL);
@@ -688,7 +690,7 @@ void BootstrapRequest<I>::list_local_group_snapshots() {
       &BootstrapRequest<I>::handle_list_local_group_snapshots>(this);
 
   auto req = librbd::group::ListSnapshotsRequest<I>::create(m_local_io_ctx,
-      *m_local_group_id, true, true, &m_local_group_snaps, ctx);
+      *m_local_group_id, true, true, &local_group_snaps, ctx);
   req->send();
 }
 
@@ -708,16 +710,20 @@ void BootstrapRequest<I>::handle_list_local_group_snapshots(int r) {
     return;
   }
 
+  for (auto it : local_group_snaps) {
+    m_local_group_snaps->insert(make_pair(it.id, it));
+  }
+
   if (m_local_mirror_group.state == cls::rbd::MIRROR_GROUP_STATE_ENABLED) {
     cls::rbd::MirrorSnapshotState state;
-    r = get_last_mirror_snapshot_state(m_local_group_snaps, &state);
+    r = get_last_mirror_snapshot_state(local_group_snaps, &state);
     if (r == -ENOENT) {
       derr << "failed to find local mirror group snapshot" << dendl;
     } else {
       if (state == cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED) {
         // if local snapshot is primary demoted, check if there is demote snapshot
         // in remote, if not then split brain
-        if (!is_demoted_snap_exists(m_remote_group_snaps)) {
+        if (!is_demoted_snap_exists(remote_group_snaps)) {
           finish(-EEXIST);
           return;
         }
index 2b0085e7df1f96474eb2dfc297febcd133d657c0..171ad1dcef080ecaae3bded48f4cabad26a8f8c1 100644 (file)
@@ -47,6 +47,7 @@ public:
       PoolMetaCache *pool_meta_cache,
       std::string *local_group_id,
       std::string *remote_group_id,
+      std::map<std::string, cls::rbd::GroupSnapshot> *local_group_snaps,
       GroupCtx *local_group_ctx,
       std::list<std::pair<librados::IoCtx, ImageReplayer<ImageCtxT> *>> *image_replayers,
       std::map<std::pair<int64_t, std::string>, ImageReplayer<ImageCtxT> *> *image_replayer_index,
@@ -55,7 +56,8 @@ public:
       threads, local_io_ctx, remote_io_ctx, global_group_id, local_mirror_uuid,
       instance_watcher, local_status_updater, remote_status_updater,
       cache_manager_handler, pool_meta_cache, local_group_id, remote_group_id,
-      local_group_ctx, image_replayers, image_replayer_index, on_finish);
+      local_group_snaps, local_group_ctx, image_replayers, image_replayer_index,
+      on_finish);
   }
 
   BootstrapRequest(
@@ -71,6 +73,7 @@ public:
       PoolMetaCache *pool_meta_cache,
       std::string *local_group_id,
       std::string *remote_group_id,
+      std::map<std::string, cls::rbd::GroupSnapshot> *local_group_snaps,
       GroupCtx *local_group_ctx,
       std::list<std::pair<librados::IoCtx, ImageReplayer<ImageCtxT> *>> *image_replayers,
       std::map<std::pair<int64_t, std::string>, ImageReplayer<ImageCtxT> *> *image_replayer_index,
@@ -166,6 +169,7 @@ private:
   PoolMetaCache *m_pool_meta_cache;
   std::string *m_local_group_id;
   std::string *m_remote_group_id;
+  std::map<std::string, cls::rbd::GroupSnapshot> *m_local_group_snaps;
   GroupCtx *m_local_group_ctx;
   std::list<std::pair<librados::IoCtx, ImageReplayer<ImageCtxT> *>> *m_image_replayers;
   std::map<std::pair<int64_t, std::string>, ImageReplayer<ImageCtxT> *> *m_image_replayer_index;
@@ -177,8 +181,8 @@ private:
   bool m_local_group_id_by_name = false;
   cls::rbd::MirrorGroup m_remote_mirror_group;
   cls::rbd::MirrorGroup m_local_mirror_group;
-  std::vector<cls::rbd::GroupSnapshot> m_remote_group_snaps;
-  std::vector<cls::rbd::GroupSnapshot> m_local_group_snaps;
+  std::vector<cls::rbd::GroupSnapshot> remote_group_snaps;
+  std::vector<cls::rbd::GroupSnapshot> local_group_snaps;
   bool m_remote_mirror_group_primary = false;
   bool m_local_mirror_group_primary = false;
   std::list<cls::rbd::GroupImageStatus> m_images;
index d41f3e3cb02d60436085aee8c3f2c67c7b88bcd7..bb5dadb26de07a28996a51634c3cfecedd2a1be6 100644 (file)
@@ -12,6 +12,7 @@ struct ReplayerListener {
   virtual ~ReplayerListener() {}
 
   virtual void handle_notification() = 0;
+  virtual void list_remote_group_snapshots(Context *on_finish) = 0;
 
   virtual void create_mirror_snapshot_start(
       const cls::rbd::MirrorSnapshotNamespace &remote_group_snap_ns,
index f05613a7aafb81d2d032008d4a492e8a7f3a05ce..a0a9babd63f738559cad25a0873f26c0ef5e7764 100644 (file)
@@ -951,7 +951,7 @@ void Replayer<I>::handle_get_remote_image_state(int r) {
     return;
   }
 
-  create_group_snap_start();
+  refresh_remote_group_snapshot_list();
 }
 
 template <typename I>
@@ -982,8 +982,7 @@ void Replayer<I>::handle_get_local_image_state(int r) {
 }
 
 template <typename I>
-void Replayer<I>::create_group_snap_start() {
-
+void Replayer<I>::refresh_remote_group_snapshot_list() {
   if (!m_remote_mirror_snap_ns.group_spec.is_valid() ||
       m_remote_mirror_snap_ns.group_snap_id.empty()) {
     create_non_primary_snapshot();
@@ -992,6 +991,31 @@ void Replayer<I>::create_group_snap_start() {
 
   dout(10) << dendl;
 
+  auto ctx = new LambdaContext(
+    [this](int r) {
+      handle_refresh_remote_group_snapshot_list(r);
+  });
+
+  m_replayer_listener->list_remote_group_snapshots(ctx);
+}
+
+template <typename I>
+void Replayer<I>::handle_refresh_remote_group_snapshot_list(int r) {
+  dout(10) << "r=" << r << dendl;
+
+  if (r < 0) {
+    dout(15) << "restarting replayer" << dendl;
+    load_local_image_meta();
+    return;
+  }
+
+  create_group_snap_start();
+}
+
+template <typename I>
+void Replayer<I>::create_group_snap_start() {
+  dout(10) << dendl;
+
   auto ctx = create_context_callback<
     Replayer<I>, &Replayer<I>::handle_create_group_snap_start>(this);
 
@@ -1006,8 +1030,13 @@ void Replayer<I>::handle_create_group_snap_start(int r) {
 
   if (r < 0 && r != -EEXIST) {
     if (r == -EAGAIN) {
-      dout(15) << "restarting replayer" << dendl;
-      load_local_image_meta();
+      auto ctx = new LambdaContext(
+        [this](int r) {
+          // retry after 1 sec
+          refresh_remote_group_snapshot_list();
+        });
+      std::lock_guard timer_locker{m_threads->timer_lock};
+      m_threads->timer->add_event_after(1, ctx);
     } else if (r == -ESTALE) {
       dout(15) << "waiting for shut down" << dendl;
       handle_replay_complete(r, "waiting for shut down");
index 40df08e0e0ff654eff73c524efde1f234fbd9f5c..da066669a9fcb0eb4f6b3f26507be0699df87ab7 100644 (file)
@@ -301,6 +301,9 @@ private:
   void get_local_image_state();
   void handle_get_local_image_state(int r);
 
+  void refresh_remote_group_snapshot_list();
+  void handle_refresh_remote_group_snapshot_list(int r);
+
   void create_group_snap_start();
   void handle_create_group_snap_start(int r);