]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
tools/cephfs_mirror: Remove persisted dir stats
authorKotresh HR <khiremat@redhat.com>
Sat, 20 Jun 2026 07:58:56 +0000 (13:28 +0530)
committerKotresh HR <khiremat@redhat.com>
Tue, 23 Jun 2026 15:19:29 +0000 (20:49 +0530)
When a directory is removed from mirroring, the persisted directory
stats need to be removed.  This patch handles the cleanup.

Omap keys must not be removed when mirrored directories are reshuffled
across cephfs-mirror daemons.  The mgr release notify now carries a
purging flag (set only during permanent removal, not reshuffle), and
the daemon removes persisted stats only when purging is true.  On
reshuffle with an in-progress sync, clear live current_syncing_snap
state and persist idle metrics so the acquiring daemon does not inherit
stale syncing omap entries.

Fixes: https://tracker.ceph.com/issues/76686
Signed-off-by: Kotresh HR <khiremat@redhat.com>
src/pybind/mgr/mirroring/fs/snapshot_mirror.py
src/tools/cephfs_mirror/FSMirror.cc
src/tools/cephfs_mirror/FSMirror.h
src/tools/cephfs_mirror/InstanceWatcher.cc
src/tools/cephfs_mirror/InstanceWatcher.h

index 884146109a417619442e872b3dcaac13041ca7d7..237b12a945a1ebd4a13488932f7f4e4cc36d8b7e 100644 (file)
@@ -181,10 +181,12 @@ class FSPolicy:
             return json.dumps({'dir_path': dir_path,
                                'mode': 'acquire'
                                })
-        def release_message(dir_path):
-            return json.dumps({'dir_path': dir_path,
-                               'mode': 'release'
-                               })
+        def release_message(dir_path, purging=False):
+            msg = {'dir_path': dir_path,
+                   'mode': 'release'}
+            if purging:
+                msg['purging'] = True
+            return json.dumps(msg)
         with self.lock:
             if not self.dir_paths or self.stopping.is_set():
                 return
@@ -211,7 +213,9 @@ class FSPolicy:
                 elif action_type == ActionType.ACQUIRE:
                     notifies[dir_path] = (lookup_info['instance_id'], acquire_message(dir_path))
                 elif action_type == ActionType.RELEASE:
-                    notifies[dir_path] = (lookup_info['instance_id'], release_message(dir_path))
+                    notifies[dir_path] = (lookup_info['instance_id'],
+                                          release_message(dir_path,
+                                                          lookup_info['purging']))
             if update_map or removals:
                 self.update_mapping(update_map, removals, callback=self.continue_action)
             for dir_path, message in notifies.items():
index ac19f158694bff47f9336e7946ebf3477f41d113..9b88fd55b86244c037177d443f75827568c22e92 100644 (file)
@@ -390,8 +390,8 @@ void FSMirror::handle_acquire_directory(string_view dir_path) {
   }
 }
 
-void FSMirror::handle_release_directory(string_view dir_path) {
-  dout(5) << ": dir_path=" << dir_path << dendl;
+void FSMirror::handle_release_directory(string_view dir_path, bool purging) {
+  dout(5) << ": dir_path=" << dir_path << ", purging=" << purging << dendl;
 
   {
     std::scoped_lock locker(m_lock);
@@ -402,7 +402,7 @@ void FSMirror::handle_release_directory(string_view dir_path) {
                                                    m_directories.size());
       for (auto &[peer, peer_replayer] : m_peer_replayers) {
         dout(10) << ": peer=" << peer << dendl;
-        peer_replayer->remove_directory(dir_path);
+        peer_replayer->remove_directory(dir_path, purging);
       }
     }
     if (m_perf_counters) {
index 594049baa6bceedfd48f46ae3f39bda155fde8d2..7757373c3fa368ec48ed7a2d071ceda5811dfe7e 100644 (file)
@@ -117,8 +117,8 @@ private:
       fs_mirror->handle_acquire_directory(dir_path);
     }
 
-    void release_directory(std::string_view dir_path) override {
-      fs_mirror->handle_release_directory(dir_path);
+    void release_directory(std::string_view dir_path, bool purging) override {
+      fs_mirror->handle_release_directory(dir_path, purging);
     }
 
   };
@@ -189,7 +189,7 @@ private:
   void handle_shutdown_instance_watcher(int r);
 
   void handle_acquire_directory(std::string_view dir_path);
-  void handle_release_directory(std::string_view dir_path);
+  void handle_release_directory(std::string_view dir_path, bool purging);
 };
 
 } // namespace mirror
index 8cd7214b5531c15def6315fd41ba1834fa905ca3..b8be5762497234317f66e056d0b6685d6e2d5a03 100644 (file)
@@ -87,21 +87,23 @@ void InstanceWatcher::handle_notify(uint64_t notify_id, uint64_t handle,
 
   std::string dir_path;
   std::string mode;
+  bool purging = false;
   try {
     JSONDecoder jd(bl);
     JSONDecoder::decode_json("dir_path", dir_path, &jd.parser, true);
     JSONDecoder::decode_json("mode", mode, &jd.parser, true);
+    JSONDecoder::decode_json("purging", purging, &jd.parser, false);
   } catch (const JSONDecoder::err &e) {
     derr << ": failed to decode notify json: " << e.what() << dendl;
   }
 
   dout(20) << ": notifier_id=" << notifier_id << ", dir_path=" << dir_path
-           << ", mode=" << mode << dendl;
+           << ", mode=" << mode << ", purging=" << purging << dendl;
 
   if (mode == "acquire") {
     m_listener.acquire_directory(dir_path);
   } else if (mode == "release") {
-    m_listener.release_directory(dir_path);
+    m_listener.release_directory(dir_path, purging);
   } else {
     derr << ": unknown mode" << dendl;
   }
index 5a48085d28cf28436d824b432aea1ac25ba95b64..fd939a1af8117b83f08b617fed7fdcd7ab3d4be8 100644 (file)
@@ -27,7 +27,7 @@ public:
     }
 
     virtual void acquire_directory(std::string_view dir_path) = 0;
-    virtual void release_directory(std::string_view dir_path) = 0;
+    virtual void release_directory(std::string_view dir_path, bool purging) = 0;
   };
 
   static InstanceWatcher *create(librados::IoCtx &ioctx,