From 9a8aca38f4f94e9b250f0941864230860a4735ac Mon Sep 17 00:00:00 2001 From: Patrick Donnelly Date: Fri, 26 Jan 2024 16:37:15 -0500 Subject: [PATCH] pybind/mgr/volumes: block quiesce for critical .meta file This file must remain accessible during quiesce to allow snapshots to be taken on a subvolume. Signed-off-by: Patrick Donnelly (cherry picked from commit 0308f215ae7a6392de4dbd658c6d4334c1c98e9d) --- .../fs/operations/versions/subvolume_base.py | 13 +++++++++++++ .../volumes/fs/operations/versions/subvolume_v1.py | 3 +++ .../volumes/fs/operations/versions/subvolume_v2.py | 3 +++ 3 files changed, 19 insertions(+) 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 8fbe177e5f4..a8afcc36807 100644 --- a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py +++ b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py @@ -69,6 +69,19 @@ class SubvolumeBase(object): def config_path(self): return os.path.join(self.base_path, b".meta") + def mark_meta(self): + """ + Set "ceph.quiesce.block" flag on the .meta file inode. It must remain + available while a subvolume is quiesced in order to allow some + interactions with the subvolume, snapshots in particular. + """ + try: + self.fs.setxattr(self.config_path, 'ceph.quiesce.block', b'1', 0) + except cephfs.InvalidValue: + raise VolumeException(-errno.EINVAL, "invalid value specified for ceph.quiesce.block") + except cephfs.Error as e: + raise VolumeException(-e.args[0], e.args[1]) + @property def legacy_dir(self): return (os.path.join(self.vol_spec.base_dir.encode('utf-8'), 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 90f35a4c90b..5f81a630505 100644 --- a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py +++ b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py @@ -111,6 +111,7 @@ class SubvolumeV1(SubvolumeBase, SubvolumeTemplate): qpath = subvol_path.decode('utf-8') self.init_config(SubvolumeV1.VERSION, subvolume_type, qpath, initial_state) self.mark_subvolume() + self.mark_meta() except (VolumeException, MetadataMgrException, cephfs.Error) as e: try: log.info("cleaning up subvolume with path: {0}".format(self.subvolname)) @@ -180,6 +181,7 @@ class SubvolumeV1(SubvolumeBase, SubvolumeTemplate): # create directory and set attributes self.fs.mkdirs(subvol_path, attrs.get("mode")) self.mark_subvolume() + self.mark_meta() self.set_attrs(subvol_path, attrs) # persist subvolume metadata and clone source @@ -244,6 +246,7 @@ class SubvolumeV1(SubvolumeBase, SubvolumeTemplate): st = self.fs.stat(subvol_path) # unconditionally mark as subvolume, to handle pre-existing subvolumes without the mark self.mark_subvolume() + self.mark_meta() self.uid = int(st.st_uid) self.gid = int(st.st_gid) 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 55d7f945b77..089d5ae1c01 100644 --- a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v2.py +++ b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v2.py @@ -189,6 +189,7 @@ class SubvolumeV2(SubvolumeV1): # Create the subvolume metadata file which manages auth-ids if it doesn't exist self.auth_mdata_mgr.create_subvolume_metadata_file(self.group.groupname, self.subvolname) + self.mark_meta() except (VolumeException, MetadataMgrException, cephfs.Error) as e: try: self._remove_on_failure(subvol_path, retained) @@ -243,6 +244,7 @@ class SubvolumeV2(SubvolumeV1): self.metadata_mgr.init(SubvolumeV2.VERSION, subvolume_type.value, qpath, initial_state.value) self.add_clone_source(source_volname, source_subvolume, snapname) self.metadata_mgr.flush() + self.mark_meta() except (VolumeException, MetadataMgrException, cephfs.Error) as e: try: self._remove_on_failure(subvol_path, retained) @@ -300,6 +302,7 @@ class SubvolumeV2(SubvolumeV1): self.metadata_mgr.refresh() # unconditionally mark as subvolume, to handle pre-existing subvolumes without the mark self.mark_subvolume() + self.mark_meta() etype = self.subvol_type if op_type not in self.allowed_ops_by_type(etype): -- 2.39.5