From: Patrick Donnelly Date: Fri, 26 Jan 2024 21:37:15 +0000 (-0500) Subject: pybind/mgr/volumes: block quiesce for critical .meta file X-Git-Tag: testing/wip-root-testing-20240411.174241~89^2~25 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=9a8aca38f4f94e9b250f0941864230860a4735ac;p=ceph-ci.git 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) --- 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):