]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
tools/cephfs_mirror: update checkpoint status during snapshot sync
authorKarthik U S <karthik.u.s1@ibm.com>
Sat, 16 May 2026 00:50:03 +0000 (06:20 +0530)
committerKarthik U S <karthik.u.s1@ibm.com>
Thu, 2 Jul 2026 09:19:03 +0000 (14:49 +0530)
When the sync completes or fails for a checkpointed snapshot, transition
the status of that checkpoint from CREATED/FAILED to COMPLETE/FAILED in
the do_sync_snaps() along with the timestamp of the event.

Fixes: https://tracker.ceph.com/issues/73454
Signed-off-by: Karthik U S <karthik.u.s1@ibm.com>
src/tools/cephfs_mirror/PeerReplayer.cc
src/tools/cephfs_mirror/PeerReplayer.h

index 1e9c2cf491a339a7d5a8074ea3e3b33dcdf59fb4..202f9b1f61fb1866e83bcded835a910c8f9dc343 100644 (file)
@@ -1373,6 +1373,105 @@ int PeerReplayer::build_snap_map(const std::string &dir_root,
   return rv;
 }
 
+void PeerReplayer::checkpoint_sync_complete(const std::string &dir_root,
+                                            uint64_t synced_snap_id,
+                                            const std::string &snap_name) {
+  dout(10) << ": dir_root=" << dir_root << " synced_snap_id=" << synced_snap_id
+           << " snap_name=" << snap_name << dendl;
+
+  // Read snapshot metadata
+  auto snap_path = snapshot_path(m_cct, dir_root, snap_name);
+  std::map<std::string, std::string> snap_metadata;
+  int r = read_snap_metadata(m_local_mount, snap_path, &snap_metadata);
+  if (r < 0) {
+    derr << ": failed to read snap metadata for snap_name=" << snap_name
+         << " dir_root=" << dir_root << ": " << cpp_strerror(r) << dendl;
+    return;
+  }
+
+  // Check if this snapshot has a checkpoint
+  if (!has_checkpoint(snap_metadata)) {
+    dout(10) << ": no checkpoint for snap_id=" << synced_snap_id << dendl;
+    return;
+  }
+
+  // Read checkpoint info
+  CheckpointInfo info = read_checkpoint_metadata(synced_snap_id, snap_name, snap_metadata);
+
+  // Skip if already complete
+  if (info.status == CheckpointStatus::COMPLETE) {
+    dout(10) << ": checkpoint already complete for snap_id=" << synced_snap_id << dendl;
+    return;
+  }
+
+  // Update status to COMPLETE
+  info.status = CheckpointStatus::COMPLETE;
+  info.updated_at = ceph_clock_now();
+  info.error_msg.clear();
+
+  r = write_checkpoint_metadata(m_cct, m_local_mount, dir_root, snap_name, snap_metadata, info);
+  if (r < 0) {
+    derr << ": failed to mark checkpoint completed for snap_id=" << synced_snap_id
+         << " snap_name=" << snap_name << " dir_root=" << dir_root
+         << ": " << cpp_strerror(r) << dendl;
+    return;
+  }
+
+  dout(10) << ": marked checkpoint completed for snap_id=" << synced_snap_id
+           << " snap_name=" << snap_name << dendl;
+}
+
+void PeerReplayer::checkpoint_sync_failed(const std::string &dir_root,
+                                          uint64_t snap_id,
+                                          const std::string &snap_name,
+                                          int err) {
+  dout(10) << ": dir_root=" << dir_root << " snap_id=" << snap_id
+           << " snap_name=" << snap_name << " err=" << err
+           << " (" << cpp_strerror(err) << ")" << dendl;
+
+  // Read snapshot metadata
+  auto snap_path = snapshot_path(m_cct, dir_root, snap_name);
+  std::map<std::string, std::string> snap_metadata;
+  int r = read_snap_metadata(m_local_mount, snap_path, &snap_metadata);
+  if (r < 0) {
+    derr << ": failed to read snap metadata for snap_name=" << snap_name
+         << " dir_root=" << dir_root << ": " << cpp_strerror(r) << dendl;
+    return;
+  }
+
+  // Check if this snapshot has a checkpoint
+  if (!has_checkpoint(snap_metadata)) {
+    dout(10) << ": no checkpoint for snap_id=" << snap_id << dendl;
+    return;
+  }
+
+  // Read checkpoint info
+  CheckpointInfo info = read_checkpoint_metadata(snap_id, snap_name, snap_metadata);
+
+  // Only update if it's in CREATED or FAILED status (to update error message)
+  if (info.status != CheckpointStatus::CREATED && info.status != CheckpointStatus::FAILED) {
+    dout(10) << ": checkpoint not in CREATED or FAILED status, current status="
+             << checkpoint_status_to_string(info.status) << dendl;
+    return;
+  }
+
+  // Update status to FAILED with sync error message
+  info.status = CheckpointStatus::FAILED;
+  info.updated_at = ceph_clock_now();
+  info.error_msg = string("snapshot synchronization failed: ") + cpp_strerror(err);
+
+  r = write_checkpoint_metadata(m_cct, m_local_mount, dir_root, snap_name, snap_metadata, info);
+  if (r < 0) {
+    derr << ": failed to mark checkpoint failed for snap_id=" << snap_id
+         << " snap_name=" << snap_name << " dir_root=" << dir_root
+         << ": " << cpp_strerror(r) << dendl;
+    return;
+  }
+
+  dout(10) << ": marked checkpoint failed for snap_id=" << snap_id
+           << " snap_name=" << snap_name << dendl;
+}
+
 int PeerReplayer::propagate_snap_deletes(const std::string &dir_root,
                                          const std::set<std::string> &snaps) {
   dout(5) << ": dir_root=" << dir_root << ", deleted snapshots=" << snaps << dendl;
@@ -3058,6 +3157,7 @@ int PeerReplayer::do_sync_snaps(const std::string &dir_root) {
     if (r < 0) {
       derr << ": failed to synchronize dir_root=" << dir_root
            << ", snapshot=" << it->second << dendl;
+      checkpoint_sync_failed(dir_root, it->first, it->second, r);
       clear_current_syncing_snap(dir_root);
       return r;
     }
@@ -3076,6 +3176,7 @@ int PeerReplayer::do_sync_snaps(const std::string &dir_root) {
 
     set_last_synced_stat(dir_root, it->first, it->second, duration);
     persist_dir_sync_stat(dir_root);
+    checkpoint_sync_complete(dir_root, it->first, it->second);
     if (--snaps_per_cycle == 0) {
       break;
     }
index 60cd81239df3661ff90cee6cf7ebe15e981510ad..4cf99201bb4473734949395aee165e4dcc36ae15 100644 (file)
@@ -10,6 +10,7 @@
 #include "ServiceDaemon.h"
 #include "Types.h"
 #include "json_spirit/json_spirit.h"
+#include "Checkpoint.h"
 
 #include <deque>
 #include <functional>
@@ -766,6 +767,11 @@ private:
   int build_snap_map(const std::string &dir_root, std::map<uint64_t, std::string> *snap_map,
                      bool is_remote=false);
 
+  void checkpoint_sync_complete(const std::string &dir_root, uint64_t synced_snap_id,
+                                const std::string &snap_name);
+  void checkpoint_sync_failed(const std::string &dir_root, uint64_t snap_id,
+                              const std::string &snap_name, int err);
+
   int propagate_snap_deletes(const std::string &dir_root, const std::set<std::string> &snaps);
   int propagate_snap_renames(const std::string &dir_root,
                              const std::set<std::pair<std::string,std::string>> &snaps);