From c478822ba684182b02cbb4ccb28690e8b4de319b Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Thu, 20 Feb 2020 13:47:18 -0500 Subject: [PATCH] rbd-mirror: implement basic status feedback for snapshot mirroring The feedback includes the newest remote mirror snapshot timestamp, the newest completely synced local mirror snapshot timestamp, and optionally the in-progress sync snapshot timestamp and percent complete. Fixes: https://tracker.ceph.com/issues/44103 Signed-off-by: Jason Dillaman --- .../image_replayer/snapshot/Replayer.cc | 106 +++++++++++++++++- .../image_replayer/snapshot/Replayer.h | 1 + 2 files changed, 105 insertions(+), 2 deletions(-) diff --git a/src/tools/rbd_mirror/image_replayer/snapshot/Replayer.cc b/src/tools/rbd_mirror/image_replayer/snapshot/Replayer.cc index 7f8b4d6017a..7aa653abb5e 100644 --- a/src/tools/rbd_mirror/image_replayer/snapshot/Replayer.cc +++ b/src/tools/rbd_mirror/image_replayer/snapshot/Replayer.cc @@ -4,6 +4,7 @@ #include "Replayer.h" #include "common/debug.h" #include "common/errno.h" +#include "include/stringify.h" #include "common/Timer.h" #include "common/WorkQueue.h" #include "cls/rbd/cls_rbd_client.h" @@ -23,6 +24,7 @@ #include "tools/rbd_mirror/image_replayer/Utils.h" #include "tools/rbd_mirror/image_replayer/snapshot/ApplyImageStateRequest.h" #include "tools/rbd_mirror/image_replayer/snapshot/StateBuilder.h" +#include "tools/rbd_mirror/image_replayer/snapshot/Utils.h" #define dout_context g_ceph_context #define dout_subsys ceph_subsys_rbd_mirror @@ -37,6 +39,28 @@ namespace mirror { namespace image_replayer { namespace snapshot { +namespace { + +template +std::pair get_newest_mirror_snapshot( + I* image_ctx) { + for (auto snap_info_it = image_ctx->snap_info.rbegin(); + snap_info_it != image_ctx->snap_info.rend(); ++snap_info_it) { + const auto& snap_ns = snap_info_it->second.snap_namespace; + auto mirror_ns = boost::get< + cls::rbd::MirrorSnapshotNamespace>(&snap_ns); + if (mirror_ns == nullptr || !mirror_ns->complete) { + continue; + } + + return {snap_info_it->first, &snap_info_it->second}; + } + + return {CEPH_NOSNAP, nullptr}; +} + +} // anonymous namespace + using librbd::util::create_async_context_callback; using librbd::util::create_context_callback; using librbd::util::create_rados_callback; @@ -170,7 +194,82 @@ bool Replayer::get_replay_status(std::string* description, Context* on_finish) { dout(10) << dendl; - *description = "NOT IMPLEMENTED"; + std::unique_lock locker{m_lock}; + if (m_state != STATE_REPLAYING && m_state != STATE_IDLE) { + locker.unlock(); + + derr << "replay not running" << dendl; + on_finish->complete(-EAGAIN); + return false; + } + + std::shared_lock local_image_locker{ + m_state_builder->local_image_ctx->image_lock}; + auto [local_snap_id, local_snap_info] = get_newest_mirror_snapshot( + m_state_builder->local_image_ctx); + + std::shared_lock remote_image_locker{ + m_state_builder->remote_image_ctx->image_lock}; + auto [remote_snap_id, remote_snap_info] = get_newest_mirror_snapshot( + m_state_builder->remote_image_ctx); + + if (remote_snap_info == nullptr) { + remote_image_locker.unlock(); + local_image_locker.unlock(); + locker.unlock(); + + derr << "remote image does not contain mirror snapshots" << dendl; + on_finish->complete(-EAGAIN); + return false; + } + + std::string replay_state = "idle"; + if (m_remote_snap_id_end != CEPH_NOSNAP) { + replay_state = "syncing"; + } + + *description = + "{" + "\"replay_state\": \"" + replay_state + "\", " + + "\"remote_snapshot_timestamp\": " + + stringify(remote_snap_info->timestamp.sec()); + + auto matching_remote_snap_id = util::compute_remote_snap_id( + m_state_builder->local_image_ctx->image_lock, + m_state_builder->local_image_ctx->snap_info, + local_snap_id, m_state_builder->remote_mirror_uuid); + auto matching_remote_snap_it = + m_state_builder->remote_image_ctx->snap_info.find(matching_remote_snap_id); + if (matching_remote_snap_id != CEPH_NOSNAP && + matching_remote_snap_it != + m_state_builder->remote_image_ctx->snap_info.end()) { + // use the timestamp from the matching remote image since + // the local snapshot would just be the time the snapshot was + // synced and not the consistency point in time. + *description += ", " + "\"local_snapshot_timestamp\": " + + stringify(matching_remote_snap_it->second.timestamp.sec()); + } + + matching_remote_snap_it = m_state_builder->remote_image_ctx->snap_info.find( + m_remote_snap_id_end); + if (m_remote_snap_id_end != CEPH_NOSNAP && + matching_remote_snap_it != + m_state_builder->remote_image_ctx->snap_info.end()) { + *description += ", " + "\"syncing_snapshot_timestamp\": " + + stringify(remote_snap_info->timestamp.sec()) + ", " + + "\"syncing_percent\": " + stringify(static_cast( + 100 * m_local_mirror_snap_ns.last_copied_object_number / + static_cast(std::max(1U, m_local_object_count)))); + } + + *description += + "}"; + + local_image_locker.unlock(); + remote_image_locker.unlock(); + locker.unlock(); on_finish->complete(-EEXIST); return true; } @@ -241,6 +340,7 @@ void Replayer::scan_local_mirror_snapshots( m_local_snap_id_start = 0; m_local_snap_id_end = CEPH_NOSNAP; m_local_mirror_snap_ns = {}; + m_local_object_count = 0; m_remote_snap_id_start = 0; m_remote_snap_id_end = CEPH_NOSNAP; @@ -641,7 +741,9 @@ void Replayer::handle_copy_image_progress(uint64_t object_number, << "object_count=" << object_count << dendl; std::unique_lock locker{m_lock}; - m_local_mirror_snap_ns.last_copied_object_number = object_number; + m_local_mirror_snap_ns.last_copied_object_number = std::min( + object_number, object_count); + m_local_object_count = object_count; update_non_primary_snapshot(false); } diff --git a/src/tools/rbd_mirror/image_replayer/snapshot/Replayer.h b/src/tools/rbd_mirror/image_replayer/snapshot/Replayer.h index 23cbfeb2f91..8fc1406a98a 100644 --- a/src/tools/rbd_mirror/image_replayer/snapshot/Replayer.h +++ b/src/tools/rbd_mirror/image_replayer/snapshot/Replayer.h @@ -194,6 +194,7 @@ private: uint64_t m_local_snap_id_start = 0; uint64_t m_local_snap_id_end = CEPH_NOSNAP; cls::rbd::MirrorSnapshotNamespace m_local_mirror_snap_ns; + uint64_t m_local_object_count = 0; std::string m_remote_mirror_peer_uuid; uint64_t m_remote_snap_id_start = 0; -- 2.39.5