From 51a8348dfd681dfd446c347a82e581f2ed52a4c6 Mon Sep 17 00:00:00 2001 From: Kotresh HR Date: Sat, 20 Jun 2026 13:28:56 +0530 Subject: [PATCH] tools/cephfs_mirror: Remove persisted dir stats 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 --- src/pybind/mgr/mirroring/fs/snapshot_mirror.py | 14 +++++++++----- src/tools/cephfs_mirror/FSMirror.cc | 6 +++--- src/tools/cephfs_mirror/FSMirror.h | 6 +++--- src/tools/cephfs_mirror/InstanceWatcher.cc | 6 ++++-- src/tools/cephfs_mirror/InstanceWatcher.h | 2 +- 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/pybind/mgr/mirroring/fs/snapshot_mirror.py b/src/pybind/mgr/mirroring/fs/snapshot_mirror.py index 884146109a4..237b12a945a 100644 --- a/src/pybind/mgr/mirroring/fs/snapshot_mirror.py +++ b/src/pybind/mgr/mirroring/fs/snapshot_mirror.py @@ -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(): diff --git a/src/tools/cephfs_mirror/FSMirror.cc b/src/tools/cephfs_mirror/FSMirror.cc index ac19f158694..9b88fd55b86 100644 --- a/src/tools/cephfs_mirror/FSMirror.cc +++ b/src/tools/cephfs_mirror/FSMirror.cc @@ -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) { diff --git a/src/tools/cephfs_mirror/FSMirror.h b/src/tools/cephfs_mirror/FSMirror.h index 594049baa6b..7757373c3fa 100644 --- a/src/tools/cephfs_mirror/FSMirror.h +++ b/src/tools/cephfs_mirror/FSMirror.h @@ -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 diff --git a/src/tools/cephfs_mirror/InstanceWatcher.cc b/src/tools/cephfs_mirror/InstanceWatcher.cc index 8cd7214b553..b8be5762497 100644 --- a/src/tools/cephfs_mirror/InstanceWatcher.cc +++ b/src/tools/cephfs_mirror/InstanceWatcher.cc @@ -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; } diff --git a/src/tools/cephfs_mirror/InstanceWatcher.h b/src/tools/cephfs_mirror/InstanceWatcher.h index 5a48085d28c..fd939a1af81 100644 --- a/src/tools/cephfs_mirror/InstanceWatcher.h +++ b/src/tools/cephfs_mirror/InstanceWatcher.h @@ -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, -- 2.47.3