]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/tools/rbd_mirror/image_replayer/BootstrapRequest.cc
update sources to v12.2.3
[ceph.git] / ceph / src / tools / rbd_mirror / image_replayer / BootstrapRequest.cc
index 4dadc744f6c9e6ef777a9805cad862cb76fb0131..2c24ef1f7d5e07e27831088f44dc3147de1a7940 100644 (file)
@@ -51,6 +51,7 @@ BootstrapRequest<I>::BootstrapRequest(
         const std::string &local_mirror_uuid,
         const std::string &remote_mirror_uuid,
         Journaler *journaler,
+        cls::journal::ClientState *client_state,
         MirrorPeerClientMeta *client_meta,
         Context *on_finish,
         bool *do_resync,
@@ -64,8 +65,8 @@ BootstrapRequest<I>::BootstrapRequest(
     m_timer(timer), m_timer_lock(timer_lock),
     m_local_mirror_uuid(local_mirror_uuid),
     m_remote_mirror_uuid(remote_mirror_uuid), m_journaler(journaler),
-    m_client_meta(client_meta), m_progress_ctx(progress_ctx),
-    m_do_resync(do_resync),
+    m_client_state(client_state), m_client_meta(client_meta),
+    m_progress_ctx(progress_ctx), m_do_resync(do_resync),
     m_lock(unique_lock_name("BootstrapRequest::m_lock", this)) {
 }
 
@@ -74,6 +75,12 @@ BootstrapRequest<I>::~BootstrapRequest() {
   assert(m_remote_image_ctx == nullptr);
 }
 
+template <typename I>
+bool BootstrapRequest<I>::is_syncing() const {
+  Mutex::Locker locker(m_lock);
+  return (m_image_sync != nullptr);
+}
+
 template <typename I>
 void BootstrapRequest<I>::send() {
   *m_do_resync = false;
@@ -137,70 +144,6 @@ void BootstrapRequest<I>::handle_get_remote_tag_class(int r) {
   m_remote_tag_class = client_meta->tag_class;
   dout(10) << ": remote tag class=" << m_remote_tag_class << dendl;
 
-  get_client();
-}
-
-template <typename I>
-void BootstrapRequest<I>::get_client() {
-  dout(20) << dendl;
-
-  update_progress("GET_CLIENT");
-
-  Context *ctx = create_context_callback<
-    BootstrapRequest<I>, &BootstrapRequest<I>::handle_get_client>(
-      this);
-  m_journaler->get_client(m_local_mirror_uuid, &m_client, ctx);
-}
-
-template <typename I>
-void BootstrapRequest<I>::handle_get_client(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  if (r == -ENOENT) {
-    dout(10) << ": client not registered" << dendl;
-  } else if (r < 0) {
-    derr << ": failed to retrieve client: " << cpp_strerror(r) << dendl;
-    finish(r);
-    return;
-  } else if (decode_client_meta()) {
-    // skip registration if it already exists
-    open_remote_image();
-    return;
-  }
-
-  register_client();
-}
-
-template <typename I>
-void BootstrapRequest<I>::register_client() {
-  dout(20) << dendl;
-
-  update_progress("REGISTER_CLIENT");
-
-  // record an place-holder record
-  librbd::journal::ClientData client_data{
-    librbd::journal::MirrorPeerClientMeta{m_local_image_id}};
-  bufferlist client_data_bl;
-  ::encode(client_data, client_data_bl);
-
-  Context *ctx = create_context_callback<
-    BootstrapRequest<I>, &BootstrapRequest<I>::handle_register_client>(
-      this);
-  m_journaler->register_client(client_data_bl, ctx);
-}
-
-template <typename I>
-void BootstrapRequest<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_meta = librbd::journal::MirrorPeerClientMeta(m_local_image_id);
   open_remote_image();
 }
 
@@ -267,8 +210,14 @@ void BootstrapRequest<I>::handle_is_primary(int r) {
     return;
   }
 
+  if (!m_client_meta->image_id.empty()) {
+    // have an image id -- use that to open the image since a deletion (resync)
+    // will leave the old image id registered in the peer
+    m_local_image_id = m_client_meta->image_id;
+  }
+
   if (m_local_image_id.empty()) {
-    create_local_image();
+    update_client_image();
     return;
   }
 
@@ -305,7 +254,7 @@ void BootstrapRequest<I>::handle_update_client_state(int r) {
   if (r < 0) {
     derr << ": failed to update client: " << cpp_strerror(r) << dendl;
   } else {
-    m_client_meta->state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;;
+    m_client_meta->state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
   }
 
   close_remote_image();
@@ -333,7 +282,7 @@ void BootstrapRequest<I>::handle_open_local_image(int r) {
   if (r == -ENOENT) {
     assert(*m_local_image_ctx == nullptr);
     dout(10) << ": local image missing" << dendl;
-    create_local_image();
+    unregister_client();
     return;
   } else if (r == -EREMOTEIO) {
     assert(*m_local_image_ctx == nullptr);
@@ -373,7 +322,7 @@ void BootstrapRequest<I>::handle_open_local_image(int r) {
     return;
   }
 
-  if (m_client.state == cls::journal::CLIENT_STATE_DISCONNECTED) {
+  if (*m_client_state == cls::journal::CLIENT_STATE_DISCONNECTED) {
     dout(10) << ": client flagged disconnected -- skipping bootstrap" << dendl;
     // The caller is expected to detect disconnect initializing remote journal.
     m_ret_val = 0;
@@ -381,57 +330,82 @@ void BootstrapRequest<I>::handle_open_local_image(int r) {
     return;
   }
 
-  update_client_image();
+  get_remote_tags();
 }
 
 template <typename I>
-void BootstrapRequest<I>::create_local_image() {
+void BootstrapRequest<I>::unregister_client() {
   dout(20) << dendl;
+  update_progress("UNREGISTER_CLIENT");
 
   m_local_image_id = "";
-  update_progress("CREATE_LOCAL_IMAGE");
-
-  m_remote_image_ctx->snap_lock.get_read();
-  std::string image_name = m_remote_image_ctx->name;
-  m_remote_image_ctx->snap_lock.put_read();
-
   Context *ctx = create_context_callback<
-    BootstrapRequest<I>, &BootstrapRequest<I>::handle_create_local_image>(
+    BootstrapRequest<I>, &BootstrapRequest<I>::handle_unregister_client>(
       this);
-  CreateImageRequest<I> *request = CreateImageRequest<I>::create(
-    m_local_io_ctx, m_work_queue, m_global_image_id, m_remote_mirror_uuid,
-    image_name, m_remote_image_ctx, &m_local_image_id, ctx);
-  request->send();
+  m_journaler->unregister_client(ctx);
 }
 
 template <typename I>
-void BootstrapRequest<I>::handle_create_local_image(int r) {
+void BootstrapRequest<I>::handle_unregister_client(int r) {
   dout(20) << ": r=" << r << dendl;
-
   if (r < 0) {
-    derr << ": failed to create local image: " << cpp_strerror(r) << dendl;
+    derr << ": failed to unregister with remote journal: " << cpp_strerror(r)
+         << dendl;
     m_ret_val = r;
     close_remote_image();
     return;
   }
 
-  open_local_image();
+  *m_client_meta = librbd::journal::MirrorPeerClientMeta("");
+  register_client();
 }
 
 template <typename I>
-void BootstrapRequest<I>::update_client_image() {
+void BootstrapRequest<I>::register_client() {
   dout(20) << dendl;
 
-  update_progress("UPDATE_CLIENT_IMAGE");
+  update_progress("REGISTER_CLIENT");
+
+  librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
+    m_local_image_id};
+  mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
 
-  if (m_client_meta->image_id == (*m_local_image_ctx)->id) {
-    // already registered local image with remote journal
-    get_remote_tags();
+  librbd::journal::ClientData client_data{mirror_peer_client_meta};
+  bufferlist client_data_bl;
+  ::encode(client_data, client_data_bl);
+
+  Context *ctx = create_context_callback<
+    BootstrapRequest<I>, &BootstrapRequest<I>::handle_register_client>(
+      this);
+  m_journaler->register_client(client_data_bl, ctx);
+}
+
+template <typename I>
+void BootstrapRequest<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;
+    m_ret_val = r;
+    close_remote_image();
     return;
   }
-  m_local_image_id = (*m_local_image_ctx)->id;
 
+  *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;
+
+  is_primary();
+}
+
+template <typename I>
+void BootstrapRequest<I>::update_client_image() {
   dout(20) << dendl;
+  update_progress("UPDATE_CLIENT_IMAGE");
+
+  assert(m_local_image_id.empty());
+  m_local_image_id = librbd::util::generate_image_id<I>(m_local_io_ctx);
 
   librbd::journal::MirrorPeerClientMeta client_meta{m_local_image_id};
   client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
@@ -453,28 +427,56 @@ void BootstrapRequest<I>::handle_update_client_image(int r) {
   if (r < 0) {
     derr << ": failed to update client: " << cpp_strerror(r) << dendl;
     m_ret_val = r;
-    close_local_image();
+    close_remote_image();
     return;
   }
 
   if (m_canceled) {
     dout(10) << ": request canceled" << dendl;
     m_ret_val = -ECANCELED;
-    close_local_image();
+    close_remote_image();
     return;
   }
 
   *m_client_meta = {m_local_image_id};
   m_client_meta->state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
-  get_remote_tags();
+  create_local_image();
 }
 
 template <typename I>
-void BootstrapRequest<I>::get_remote_tags() {
+void BootstrapRequest<I>::create_local_image() {
   dout(20) << dendl;
+  update_progress("CREATE_LOCAL_IMAGE");
 
-  update_progress("GET_REMOTE_TAGS");
+  m_remote_image_ctx->snap_lock.get_read();
+  std::string image_name = m_remote_image_ctx->name;
+  m_remote_image_ctx->snap_lock.put_read();
+
+  Context *ctx = create_context_callback<
+    BootstrapRequest<I>, &BootstrapRequest<I>::handle_create_local_image>(
+      this);
+  CreateImageRequest<I> *request = CreateImageRequest<I>::create(
+    m_local_io_ctx, m_work_queue, m_global_image_id, m_remote_mirror_uuid,
+    image_name, m_local_image_id, m_remote_image_ctx, ctx);
+  request->send();
+}
 
+template <typename I>
+void BootstrapRequest<I>::handle_create_local_image(int r) {
+  dout(20) << ": r=" << r << dendl;
+
+  if (r < 0) {
+    derr << ": failed to create local image: " << cpp_strerror(r) << dendl;
+    m_ret_val = r;
+    close_remote_image();
+    return;
+  }
+
+  open_local_image();
+}
+
+template <typename I>
+void BootstrapRequest<I>::get_remote_tags() {
   if (m_client_meta->state == librbd::journal::MIRROR_PEER_STATE_SYNCING) {
     // optimization -- no need to compare remote tags if we just created
     // the image locally or sync was interrupted
@@ -483,6 +485,7 @@ void BootstrapRequest<I>::get_remote_tags() {
   }
 
   dout(20) << dendl;
+  update_progress("GET_REMOTE_TAGS");
 
   Context *ctx = create_context_callback<
     BootstrapRequest<I>, &BootstrapRequest<I>::handle_get_remote_tags>(this);
@@ -637,24 +640,26 @@ void BootstrapRequest<I>::image_sync() {
   }
 
   dout(20) << dendl;
-  update_progress("IMAGE_SYNC");
-
-  Context *ctx = create_context_callback<
-    BootstrapRequest<I>, &BootstrapRequest<I>::handle_image_sync>(
-      this);
-
   {
     Mutex::Locker locker(m_lock);
     if (m_canceled) {
       m_ret_val = -ECANCELED;
     } else {
       assert(m_image_sync == nullptr);
+
+      Context *ctx = create_context_callback<
+        BootstrapRequest<I>, &BootstrapRequest<I>::handle_image_sync>(this);
       m_image_sync = ImageSync<I>::create(
           *m_local_image_ctx, m_remote_image_ctx, m_timer, m_timer_lock,
           m_local_mirror_uuid, m_journaler, m_client_meta, m_work_queue,
           m_instance_watcher, ctx, m_progress_ctx);
 
       m_image_sync->get();
+
+      m_lock.Unlock();
+      update_progress("IMAGE_SYNC");
+      m_lock.Lock();
+
       m_image_sync->send();
       return;
     }
@@ -670,7 +675,6 @@ void BootstrapRequest<I>::handle_image_sync(int r) {
 
   {
     Mutex::Locker locker(m_lock);
-
     m_image_sync->put();
     m_image_sync = nullptr;
 
@@ -740,36 +744,6 @@ void BootstrapRequest<I>::handle_close_remote_image(int r) {
   finish(m_ret_val);
 }
 
-template <typename I>
-bool BootstrapRequest<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;
-  } else if (!client_meta->image_id.empty()) {
-    // have an image id -- use that to open the image
-    m_local_image_id = client_meta->image_id;
-  }
-
-  *m_client_meta = *client_meta;
-
-  dout(20) << ": client found: image_id=" << m_local_image_id
-          << ", client_meta=" << *m_client_meta << dendl;
-  return true;
-}
-
 template <typename I>
 void BootstrapRequest<I>::update_progress(const std::string &description) {
   dout(20) << ": " << description << dendl;