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,
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)) {
}
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;
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();
}
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;
}
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();
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);
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;
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;
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
}
dout(20) << dendl;
+ update_progress("GET_REMOTE_TAGS");
Context *ctx = create_context_callback<
BootstrapRequest<I>, &BootstrapRequest<I>::handle_get_remote_tags>(this);
}
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;
}
{
Mutex::Locker locker(m_lock);
-
m_image_sync->put();
m_image_sync = nullptr;
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;