From ba199cf4c1865b7c6befe28175f2fd5ddd8a1b4d Mon Sep 17 00:00:00 2001 From: neeraj pratap singh Date: Tue, 27 Aug 2024 15:08:41 +0530 Subject: [PATCH] mgr/vol: fix subvolume removal with retained snapshots when osd is full The order of operation done for subvolume removal with retain-snapshot option set to true, is reversed. The metadata is updated first followed by a rename operation on the uuid directory. If the metadata update operation fails, then the remove operations is failed thereby, keeping the subvolume metadata consistent with the uuid path. Fixes: https://tracker.ceph.com/issues/67330 Signed-off-by: Neeraj Pratap Singh --- .../fs/operations/versions/subvolume_v2.py | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v2.py b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v2.py index a67c971b8db..1313a2ba701 100644 --- a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v2.py +++ b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v2.py @@ -341,14 +341,14 @@ class SubvolumeV2(SubvolumeV1): except cephfs.Error as e: raise VolumeException(-e.args[0], e.args[1]) - def trash_incarnation_dir(self): + def trash_incarnation_dir(self, subvol_path): """rename subvolume (uuid component) to trash""" self.create_trashcan() try: - bname = os.path.basename(self.path) + bname = os.path.basename(subvol_path) tpath = os.path.join(self.trash_dir, bname) - log.debug("trash: {0} -> {1}".format(self.path, tpath)) - self.fs.rename(self.path, tpath) + log.debug(f"trash: {subvol_path} -> {tpath}") + self.fs.rename(subvol_path, tpath) self._link_dir(tpath, bname) except cephfs.Error as e: raise VolumeException(-e.args[0], e.args[1]) @@ -378,13 +378,20 @@ class SubvolumeV2(SubvolumeV1): self.auth_mdata_mgr.delete_subvolume_metadata_file(self.group.groupname, self.subvolname) return if self.state != SubvolumeStates.STATE_RETAINED: - self.trash_incarnation_dir() - self.metadata_mgr.remove_section(MetadataManager.USER_METADATA_SECTION) - self.metadata_mgr.update_global_section(MetadataManager.GLOBAL_META_KEY_PATH, "") - self.metadata_mgr.update_global_section(MetadataManager.GLOBAL_META_KEY_STATE, SubvolumeStates.STATE_RETAINED.value) - self.metadata_mgr.flush() - # Delete the volume meta file, if it's not already deleted - self.auth_mdata_mgr.delete_subvolume_metadata_file(self.group.groupname, self.subvolname) + try: + # save subvol path for later use(renaming subvolume to trash) before deleting path section from .meta + subvol_path = self.path + self.metadata_mgr.update_global_section(MetadataManager.GLOBAL_META_KEY_PATH, "") + self.metadata_mgr.update_global_section(MetadataManager.GLOBAL_META_KEY_STATE, SubvolumeStates.STATE_RETAINED.value) + self.metadata_mgr.remove_section(MetadataManager.USER_METADATA_SECTION) + self.metadata_mgr.flush() + self.trash_incarnation_dir(subvol_path) + # Delete the volume meta file, if it's not already deleted + self.auth_mdata_mgr.delete_subvolume_metadata_file(self.group.groupname, self.subvolname) + except MetadataMgrException as e: + log.error(f"failed to write config: {e}") + raise VolumeException(e.args[0], e.args[1]) + def info(self): if self.state != SubvolumeStates.STATE_RETAINED: -- 2.39.5