]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.cc
update sources to v12.2.3
[ceph.git] / ceph / src / tools / rbd_mirror / image_replayer / PrepareRemoteImageRequest.cc
index 2e620938ff40d8d982c43160a69c6e8ee4b4ed34..5fedab88a25386b28ffea335051ddc5525f5c2ba 100644 (file)
@@ -5,8 +5,13 @@
 #include "include/rados/librados.hpp"
 #include "cls/rbd/cls_rbd_client.h"
 #include "common/errno.h"
+#include "common/WorkQueue.h"
+#include "journal/Journaler.h"
+#include "journal/Settings.h"
 #include "librbd/ImageCtx.h"
 #include "librbd/Utils.h"
+#include "librbd/journal/Types.h"
+#include "tools/rbd_mirror/Threads.h"
 #include "tools/rbd_mirror/image_replayer/GetMirrorImageIdRequest.h"
 
 #define dout_context g_ceph_context
@@ -20,6 +25,7 @@ namespace rbd {
 namespace mirror {
 namespace image_replayer {
 
+using librbd::util::create_async_context_callback;
 using librbd::util::create_context_callback;
 using librbd::util::create_rados_callback;
 
@@ -38,7 +44,7 @@ void PrepareRemoteImageRequest<I>::get_remote_mirror_uuid() {
   librados::AioCompletion *aio_comp = create_rados_callback<
     PrepareRemoteImageRequest<I>,
     &PrepareRemoteImageRequest<I>::handle_get_remote_mirror_uuid>(this);
-  int r = m_io_ctx.aio_operate(RBD_MIRRORING, aio_comp, &op, &m_out_bl);
+  int r = m_remote_io_ctx.aio_operate(RBD_MIRRORING, aio_comp, &op, &m_out_bl);
   assert(r == 0);
   aio_comp->release();
 }
@@ -75,7 +81,8 @@ void PrepareRemoteImageRequest<I>::get_remote_image_id() {
   Context *ctx = create_context_callback<
     PrepareRemoteImageRequest<I>,
     &PrepareRemoteImageRequest<I>::handle_get_remote_image_id>(this);
-  auto req = GetMirrorImageIdRequest<I>::create(m_io_ctx, m_global_image_id,
+  auto req = GetMirrorImageIdRequest<I>::create(m_remote_io_ctx,
+                                                m_global_image_id,
                                                 m_remote_image_id, ctx);
   req->send();
 }
@@ -90,13 +97,123 @@ void PrepareRemoteImageRequest<I>::handle_get_remote_image_id(int r) {
     return;
   }
 
+  get_client();
+}
+
+template <typename I>
+void PrepareRemoteImageRequest<I>::get_client() {
+  dout(20) << dendl;
+
+  journal::Settings settings;
+  settings.commit_interval = g_ceph_context->_conf->get_val<double>(
+    "rbd_mirror_journal_commit_age");
+  settings.max_fetch_bytes = g_ceph_context->_conf->get_val<uint64_t>(
+    "rbd_mirror_journal_max_fetch_bytes");
+
+  assert(*m_remote_journaler == nullptr);
+  *m_remote_journaler = new Journaler(m_threads->work_queue, m_threads->timer,
+                                      &m_threads->timer_lock, m_remote_io_ctx,
+                                      *m_remote_image_id, m_local_mirror_uuid,
+                                      settings);
+
+  Context *ctx = create_async_context_callback(
+    m_threads->work_queue, create_context_callback<
+      PrepareRemoteImageRequest<I>,
+      &PrepareRemoteImageRequest<I>::handle_get_client>(this));
+  (*m_remote_journaler)->get_client(m_local_mirror_uuid, &m_client, ctx);
+}
+
+template <typename I>
+void PrepareRemoteImageRequest<I>::handle_get_client(int r) {
+  dout(20) << "r=" << r << dendl;
+
+  if (r == -ENOENT) {
+    dout(10) << "client not registered" << dendl;
+    register_client();
+  } else if (r < 0) {
+    derr << "failed to retrieve client: " << cpp_strerror(r) << dendl;
+    finish(r);
+  } else if (!decode_client_meta()) {
+    // require operator intervention since the data is corrupt
+    finish(-EBADMSG);
+  } else {
+    // skip registration if it already exists
+    *m_client_state = m_client.state;
+    finish(0);
+  }
+}
+
+template <typename I>
+void PrepareRemoteImageRequest<I>::register_client() {
+  dout(20) << dendl;
+
+  librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
+    m_local_image_id};
+  mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+
+  librbd::journal::ClientData client_data{mirror_peer_client_meta};
+  bufferlist client_data_bl;
+  ::encode(client_data, client_data_bl);
+
+  Context *ctx = create_async_context_callback(
+    m_threads->work_queue, create_context_callback<
+      PrepareRemoteImageRequest<I>,
+      &PrepareRemoteImageRequest<I>::handle_register_client>(this));
+  (*m_remote_journaler)->register_client(client_data_bl, ctx);
+}
+
+template <typename I>
+void PrepareRemoteImageRequest<I>::handle_register_client(int r) {
+  dout(20) << "r=" << r << dendl;
+
+  if (r < 0) {
+    derr << "failed to register with remote journal: " << cpp_strerror(r)
+         << dendl;
+    finish(r);
+    return;
+  }
+
+  *m_client_state = cls::journal::CLIENT_STATE_CONNECTED;
+  *m_client_meta = librbd::journal::MirrorPeerClientMeta(m_local_image_id);
+  m_client_meta->state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+
   finish(0);
 }
 
+template <typename I>
+bool PrepareRemoteImageRequest<I>::decode_client_meta() {
+  dout(20) << dendl;
+
+  librbd::journal::ClientData client_data;
+  bufferlist::iterator it = m_client.data.begin();
+  try {
+    ::decode(client_data, it);
+  } catch (const buffer::error &err) {
+    derr << "failed to decode client meta data: " << err.what() << dendl;
+    return false;
+  }
+
+  librbd::journal::MirrorPeerClientMeta *client_meta =
+    boost::get<librbd::journal::MirrorPeerClientMeta>(&client_data.client_meta);
+  if (client_meta == nullptr) {
+    derr << "unknown peer registration" << dendl;
+    return false;
+  }
+
+  *m_client_meta = *client_meta;
+  dout(20) << "client found: client_meta=" << *m_client_meta << dendl;
+  return true;
+}
+
 template <typename I>
 void PrepareRemoteImageRequest<I>::finish(int r) {
   dout(20) << "r=" << r << dendl;
 
+  if (r < 0) {
+    delete *m_remote_journaler;
+    *m_remote_journaler = nullptr;
+  }
+
   m_on_finish->complete(r);
   delete this;
 }