X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=ceph%2Fsrc%2Ftools%2Frbd_mirror%2FImageReplayer.cc;h=f68d51d40d8d1aebb1f2f6aaadd03e4b8be43916;hb=c07f9fc5a4f48397831383549fb0482b93480643;hp=b025566d5315125bc4d3d1d00bc27e231e5d49fc;hpb=9439ae556f035e65c9c107ae13ddd09457dbbecd;p=ceph.git diff --git a/ceph/src/tools/rbd_mirror/ImageReplayer.cc b/ceph/src/tools/rbd_mirror/ImageReplayer.cc index b025566d5..f68d51d40 100644 --- a/ceph/src/tools/rbd_mirror/ImageReplayer.cc +++ b/ceph/src/tools/rbd_mirror/ImageReplayer.cc @@ -271,7 +271,7 @@ void ImageReplayer::RemoteJournalerListener::handle_update( template ImageReplayer::ImageReplayer(Threads *threads, - shared_ptr image_deleter, + ImageDeleter* image_deleter, InstanceWatcher *instance_watcher, RadosRef local, const std::string &local_mirror_uuid, @@ -326,6 +326,21 @@ ImageReplayer::~ImageReplayer() delete m_asok_hook; } +template +image_replayer::HealthState ImageReplayer::get_health_state() const { + Mutex::Locker locker(m_lock); + + if (!m_mirror_image_status_state) { + return image_replayer::HEALTH_STATE_OK; + } else if (*m_mirror_image_status_state == + cls::rbd::MIRROR_IMAGE_STATUS_STATE_SYNCING || + *m_mirror_image_status_state == + cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN) { + return image_replayer::HEALTH_STATE_WARNING; + } + return image_replayer::HEALTH_STATE_ERROR; +} + template void ImageReplayer::add_remote_image(const std::string &mirror_uuid, const std::string &image_id, @@ -445,7 +460,7 @@ void ImageReplayer::bootstrap() { dout(20) << dendl; if (m_remote_images.empty()) { - on_start_fail(0, "waiting for primary remote image"); + on_start_fail(-EREMOTEIO, "waiting for primary remote image"); return; } @@ -500,8 +515,8 @@ void ImageReplayer::handle_bootstrap(int r) { if (r == -EREMOTEIO) { m_local_image_tag_owner = ""; - dout(5) << "remote image is non-primary or local image is primary" << dendl; - on_start_fail(0, "remote image is non-primary or local image is primary"); + dout(5) << "remote image is non-primary" << dendl; + on_start_fail(-EREMOTEIO, "remote image is non-primary"); return; } else if (r == -EEXIST) { m_local_image_tag_owner = ""; @@ -682,7 +697,7 @@ void ImageReplayer::on_start_fail(int r, const std::string &desc) Mutex::Locker locker(m_lock); assert(m_state == STATE_STARTING); m_state = STATE_STOPPING; - if (r < 0 && r != -ECANCELED) { + if (r < 0 && r != -ECANCELED && r != -EREMOTEIO) { derr << "start failed: " << cpp_strerror(r) << dendl; } else { dout(20) << "start canceled" << dendl; @@ -1302,15 +1317,30 @@ void ImageReplayer::send_mirror_status_update(const OptionalState &opt_state) State state; std::string state_desc; int last_r; - bool bootstrapping; bool stopping_replay; + + OptionalMirrorImageStatusState mirror_image_status_state{ + boost::make_optional(false, cls::rbd::MirrorImageStatusState{})}; + image_replayer::BootstrapRequest* bootstrap_request = nullptr; { Mutex::Locker locker(m_lock); state = m_state; state_desc = m_state_desc; + mirror_image_status_state = m_mirror_image_status_state; last_r = m_last_r; - bootstrapping = (m_bootstrap_request != nullptr); stopping_replay = (m_local_image_ctx != nullptr); + + if (m_bootstrap_request != nullptr) { + bootstrap_request = m_bootstrap_request; + bootstrap_request->get(); + } + } + + bool syncing = false; + if (bootstrap_request != nullptr) { + syncing = bootstrap_request->is_syncing(); + bootstrap_request->put(); + bootstrap_request = nullptr; } if (opt_state) { @@ -1321,9 +1351,10 @@ void ImageReplayer::send_mirror_status_update(const OptionalState &opt_state) status.up = true; switch (state) { case STATE_STARTING: - if (bootstrapping) { + if (syncing) { status.state = cls::rbd::MIRROR_IMAGE_STATUS_STATE_SYNCING; status.description = state_desc.empty() ? "syncing" : state_desc; + mirror_image_status_state = status.state; } else { status.state = cls::rbd::MIRROR_IMAGE_STATUS_STATE_STARTING_REPLAY; status.description = "starting replay"; @@ -1351,6 +1382,7 @@ void ImageReplayer::send_mirror_status_update(const OptionalState &opt_state) return; } status.description = "replaying, " + desc; + mirror_image_status_state = boost::none; } break; case STATE_STOPPING: @@ -1361,18 +1393,35 @@ void ImageReplayer::send_mirror_status_update(const OptionalState &opt_state) } // FALLTHROUGH case STATE_STOPPED: - if (last_r < 0) { + if (last_r == -EREMOTEIO) { + status.state = cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN; + status.description = state_desc; + mirror_image_status_state = status.state; + } else if (last_r < 0) { status.state = cls::rbd::MIRROR_IMAGE_STATUS_STATE_ERROR; status.description = state_desc; + mirror_image_status_state = status.state; } else { status.state = cls::rbd::MIRROR_IMAGE_STATUS_STATE_STOPPED; status.description = state_desc.empty() ? "stopped" : state_desc; + mirror_image_status_state = boost::none; } break; default: assert(!"invalid state"); } + { + Mutex::Locker locker(m_lock); + m_mirror_image_status_state = mirror_image_status_state; + } + + // prevent the status from ping-ponging when failed replays are restarted + if (mirror_image_status_state && + *mirror_image_status_state == cls::rbd::MIRROR_IMAGE_STATUS_STATE_ERROR) { + status.state = *mirror_image_status_state; + } + dout(20) << "status=" << status << dendl; librados::ObjectWriteOperation op; librbd::cls_client::mirror_image_status_set(&op, m_global_image_id, status); @@ -1590,7 +1639,8 @@ void ImageReplayer::handle_shut_down(int r) { if (m_stopping_for_resync) { m_image_deleter->schedule_image_delete(m_local, m_local_pool_id, - m_global_image_id); + m_global_image_id, + true); m_stopping_for_resync = false; } }