From: Kotresh HR Date: Tue, 16 Aug 2022 11:41:33 +0000 (+0530) Subject: mgr/volumes: Remove stale snapshot user metadata X-Git-Tag: v18.0.0~202^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=65af2d123a1f1ef9c4b370e908ece588eec19a1f;p=ceph.git mgr/volumes: Remove stale snapshot user metadata This patch adds the capability to remove the stale snapshot user metadata while loading the subvolume if it is present. It can't be done in 'SubvolumeBase.discover' since v1 and v2 snapshot paths are different. This is done just after the discover before returning the specific version object. Fixes: https://tracker.ceph.com/issues/55976 Signed-off-by: Kotresh HR --- diff --git a/src/pybind/mgr/volumes/fs/operations/versions/__init__.py b/src/pybind/mgr/volumes/fs/operations/versions/__init__.py index 3dcdd7c10ab1..544afa165f97 100644 --- a/src/pybind/mgr/volumes/fs/operations/versions/__init__.py +++ b/src/pybind/mgr/volumes/fs/operations/versions/__init__.py @@ -95,7 +95,10 @@ class SubvolumeLoader(object): subvolume.discover() self.upgrade_to_v2_subvolume(subvolume) version = int(subvolume.metadata_mgr.get_global_option('version')) - return self._get_subvolume_version(version)(mgr, fs, vol_spec, group, subvolname, legacy=subvolume.legacy_mode) + subvolume_version_object = self._get_subvolume_version(version)(mgr, fs, vol_spec, group, subvolname, legacy=subvolume.legacy_mode) + subvolume_version_object.metadata_mgr.refresh() + subvolume_version_object.clean_stale_snapshot_metadata() + return subvolume_version_object except MetadataMgrException as me: if me.errno == -errno.ENOENT and upgrade: self.upgrade_legacy_subvolume(fs, subvolume) diff --git a/src/pybind/mgr/volumes/fs/operations/versions/metadata_manager.py b/src/pybind/mgr/volumes/fs/operations/versions/metadata_manager.py index 764f4bc25751..718735d91b13 100644 --- a/src/pybind/mgr/volumes/fs/operations/versions/metadata_manager.py +++ b/src/pybind/mgr/volumes/fs/operations/versions/metadata_manager.py @@ -4,6 +4,7 @@ import logging import sys import threading import configparser +import re import cephfs @@ -184,3 +185,16 @@ class MetadataManager(object): if not self.config.has_section(section): raise MetadataMgrException(-errno.ENOENT, "section '{0}' does not exist".format(section)) return item in [v[1] for v in self.config.items(section)] + + def has_snap_metadata_section(self): + sections = self.config.sections() + r = re.compile('SNAP_METADATA_.*') + for section in sections: + if r.match(section): + return True + return False + + def list_snaps_with_metadata(self): + sections = self.config.sections() + r = re.compile('SNAP_METADATA_.*') + return [section[len("SNAP_METADATA_"):] for section in sections if r.match(section)] diff --git a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py index 906b55e7b83d..3bae0707a6a4 100644 --- a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py +++ b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py @@ -136,6 +136,10 @@ class SubvolumeBase(object): """ Boolean declaring if subvolume can be purged """ raise NotImplementedError + def clean_stale_snapshot_metadata(self): + """ Clean up stale snapshot metadata """ + raise NotImplementedError + def load_config(self): try: self.fs.stat(self.legacy_config_path) diff --git a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py index 0e2a64d48eac..b5a10dd6c7f6 100644 --- a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py +++ b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py @@ -857,6 +857,22 @@ class SubvolumeV1(SubvolumeBase, SubvolumeTemplate): return [] raise + def clean_stale_snapshot_metadata(self): + """ Clean up stale snapshot metadata """ + if self.metadata_mgr.has_snap_metadata_section(): + snap_list = self.list_snapshots() + snaps_with_metadata_list = self.metadata_mgr.list_snaps_with_metadata() + for snap_with_metadata in snaps_with_metadata_list: + if snap_with_metadata.encode('utf-8') not in snap_list: + try: + self.metadata_mgr.remove_section(self.get_snap_section_name(snap_with_metadata)) + self.metadata_mgr.flush() + except MetadataMgrException as me: + log.error(f"Failed to remove stale snap metadata on snap={snap_with_metadata} " + f"subvol={self.subvol_name} group={self.group_name} reason={me.args[1]}, " + f"errno:{-me.args[0]}, {os.strerror(-me.args[0])}") + pass + def _add_snap_clone(self, track_id, snapname): self.metadata_mgr.add_section("clone snaps") self.metadata_mgr.update_section("clone snaps", track_id, snapname)