#define dout_prefix *_dout << "rbd::mirror::" << *this << " " \
<< __func__ << ": "
-extern PerfCounters *g_perf_counters;
-
namespace rbd {
namespace mirror {
unregister_admin_socket_hook();
ceph_assert(m_state_builder == nullptr);
ceph_assert(m_on_start_finish == nullptr);
- ceph_assert(m_on_stop_finish == nullptr);
+ ceph_assert(m_on_stop_contexts.empty());
ceph_assert(m_bootstrap_request == nullptr);
ceph_assert(m_update_status_task == nullptr);
delete m_replayer_listener;
m_manual_stop = false;
m_delete_requested = false;
m_restart_requested = false;
+ m_status_removed = false;
if (on_finish != nullptr) {
ceph_assert(m_on_start_finish == nullptr);
m_on_start_finish = on_finish;
}
- ceph_assert(m_on_stop_finish == nullptr);
+ ceph_assert(m_on_stop_contexts.empty());
}
}
m_delete_requested = true;
on_start_fail(0, "remote image no longer exists");
return;
+ } else if (r == -ERESTART) {
+ on_start_fail(r, "image in transient state, try again");
+ return;
} else if (r < 0) {
on_start_fail(r, "error bootstrapping replay");
return;
image_replayer::BootstrapRequest<I> *bootstrap_request = nullptr;
bool shut_down_replay = false;
- bool running = true;
+ bool is_stopped = false;
{
std::lock_guard locker{m_lock};
- if (restart) {
- m_restart_requested = true;
- }
-
if (!is_running_()) {
- running = false;
+ if (manual && !m_manual_stop) {
+ dout(10) << "marking manual" << dendl;
+ m_manual_stop = true;
+ }
if (!restart && m_restart_requested) {
dout(10) << "canceling restart" << dendl;
m_restart_requested = false;
}
+ if (is_stopped_()) {
+ dout(10) << "already stopped" << dendl;
+ is_stopped = true;
+ } else {
+ dout(10) << "joining in-flight stop" << dendl;
+ if (on_finish != nullptr) {
+ m_on_stop_contexts.push_back(on_finish);
+ }
+ }
} else {
- if (!is_stopped_()) {
- if (m_state == STATE_STARTING) {
- dout(10) << "canceling start" << dendl;
- if (m_bootstrap_request != nullptr) {
- bootstrap_request = m_bootstrap_request;
- bootstrap_request->get();
- }
- } else {
- dout(10) << "interrupting replay" << dendl;
- shut_down_replay = true;
- }
-
- ceph_assert(m_on_stop_finish == nullptr);
- std::swap(m_on_stop_finish, on_finish);
- m_stop_requested = true;
- m_manual_stop = manual;
+ if (m_state == STATE_STARTING) {
+ dout(10) << "canceling start" << dendl;
+ if (m_bootstrap_request != nullptr) {
+ bootstrap_request = m_bootstrap_request;
+ bootstrap_request->get();
+ }
+ } else {
+ dout(10) << "interrupting replay" << dendl;
+ shut_down_replay = true;
}
+
+ ceph_assert(m_on_stop_contexts.empty());
+ if (on_finish != nullptr) {
+ m_on_stop_contexts.push_back(on_finish);
+ }
+ m_stop_requested = true;
+ m_manual_stop = manual;
}
}
+ if (is_stopped) {
+ if (on_finish) {
+ on_finish->complete(-EINVAL);
+ }
+ return;
+ }
+
// avoid holding lock since bootstrap request will update status
if (bootstrap_request != nullptr) {
dout(10) << "canceling bootstrap" << dendl;
bootstrap_request->put();
}
- if (!running) {
- dout(20) << "not running" << dendl;
- if (on_finish) {
- on_finish->complete(-EINVAL);
- }
- return;
- }
-
if (shut_down_replay) {
on_stop_journal_replay();
- } else if (on_finish != nullptr) {
- on_finish->complete(0);
}
}
dout(0) << "remote image no longer exists: scheduling deletion" << dendl;
unregister_asok_hook = true;
std::swap(delete_requested, m_delete_requested);
+ m_delete_in_progress = true;
}
std::swap(resync_requested, m_resync_requested);
return;
}
- if (m_local_status_updater->exists(m_global_image_id)) {
- dout(15) << "removing local mirror image status" << dendl;
- auto ctx = new LambdaContext([this, r](int) {
- handle_shut_down(r);
- });
- m_local_status_updater->remove_mirror_image_status(m_global_image_id, ctx);
- return;
- }
-
- if (m_remote_image_peer.mirror_status_updater != nullptr &&
- m_remote_image_peer.mirror_status_updater->exists(m_global_image_id)) {
- dout(15) << "removing remote mirror image status" << dendl;
+ if (!m_status_removed) {
auto ctx = new LambdaContext([this, r](int) {
- handle_shut_down(r);
- });
- m_remote_image_peer.mirror_status_updater->remove_mirror_image_status(
- m_global_image_id, ctx);
+ m_status_removed = true;
+ handle_shut_down(r);
+ });
+ remove_image_status(m_delete_in_progress, ctx);
return;
}
dout(10) << "stop complete" << dendl;
Context *on_start = nullptr;
- Context *on_stop = nullptr;
+ Contexts on_stop_contexts;
{
std::lock_guard locker{m_lock};
std::swap(on_start, m_on_start_finish);
- std::swap(on_stop, m_on_stop_finish);
+ on_stop_contexts = std::move(m_on_stop_contexts);
m_stop_requested = false;
ceph_assert(m_state == STATE_STOPPING);
m_state = STATE_STOPPED;
on_start->complete(r);
r = 0;
}
- if (on_stop != nullptr) {
- dout(10) << "on stop finish complete, r=" << r << dendl;
- on_stop->complete(r);
+ for (auto ctx : on_stop_contexts) {
+ dout(10) << "on stop finish " << ctx << " complete, r=" << r << dendl;
+ ctx->complete(r);
}
}
register_admin_socket_hook();
}
+template <typename I>
+void ImageReplayer<I>::remove_image_status(bool force, Context *on_finish)
+{
+ auto ctx = new LambdaContext([this, force, on_finish](int) {
+ remove_image_status_remote(force, on_finish);
+ });
+
+ if (m_local_status_updater->exists(m_global_image_id)) {
+ dout(15) << "removing local mirror image status" << dendl;
+ if (force) {
+ m_local_status_updater->remove_mirror_image_status(
+ m_global_image_id, true, ctx);
+ } else {
+ m_local_status_updater->remove_refresh_mirror_image_status(
+ m_global_image_id, ctx);
+ }
+ return;
+ }
+
+ ctx->complete(0);
+}
+
+template <typename I>
+void ImageReplayer<I>::remove_image_status_remote(bool force, Context *on_finish)
+{
+ if (m_remote_image_peer.mirror_status_updater != nullptr &&
+ m_remote_image_peer.mirror_status_updater->exists(m_global_image_id)) {
+ dout(15) << "removing remote mirror image status" << dendl;
+ if (force) {
+ m_remote_image_peer.mirror_status_updater->remove_mirror_image_status(
+ m_global_image_id, true, on_finish);
+ } else {
+ m_remote_image_peer.mirror_status_updater->remove_refresh_mirror_image_status(
+ m_global_image_id, on_finish);
+ }
+ return;
+ }
+ if (on_finish) {
+ on_finish->complete(0);
+ }
+}
+
template <typename I>
std::ostream &operator<<(std::ostream &os, const ImageReplayer<I> &replayer)
{