]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mgr/vol: move reusable parts from async_cloner
authorRishabh Dave <ridave@redhat.com>
Wed, 14 Feb 2024 09:52:47 +0000 (15:22 +0530)
committerRishabh Dave <ridave@redhat.com>
Tue, 16 Sep 2025 15:23:50 +0000 (20:53 +0530)
Signed-off-by: Rishabh Dave <ridave@redhat.com>
(cherry picked from commit 8c536f78907fe1d42e1df612604d5872019b501d)

src/pybind/mgr/volumes/fs/async_cloner.py
src/pybind/mgr/volumes/fs/operations/resolver.py
src/pybind/mgr/volumes/fs/operations/subvolume.py
src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py

index 685b2f03c78c06a40a71b5173cd2f476b13ca152..463c10005968aa599d5d8c76ff53c6ca39f6a19b 100644 (file)
@@ -14,10 +14,12 @@ from .exception import IndexException, MetadataMgrException, OpSmException, Volu
 from .fs_util import copy_file
 from .operations.versions.op_sm import SubvolumeOpSm
 from .operations.versions.subvolume_attrs import SubvolumeTypes, SubvolumeStates, SubvolumeActions
-from .operations.resolver import resolve
+from .operations.resolver import resolve_group_and_subvolume_name
 from .operations.volume import open_volume, open_volume_lockless
 from .operations.group import open_group
-from .operations.subvolume import open_subvol
+from .operations.subvolume import (open_subvol, open_subvol_in_group,
+                                   open_clone_subvol_pair_in_vol,
+                                   open_clone_subvol_pair_in_group)
 from .operations.clone_index import open_clone_index
 from .operations.template import SubvolumeOpType
 
@@ -49,33 +51,16 @@ def open_at_volume(fs_client, volspec, volname, groupname, subvolname, op_type):
                 yield subvolume
 
 @contextmanager
-def open_at_group(fs_client, fs_handle, volspec, groupname, subvolname, op_type):
-    with open_group(fs_handle, volspec, groupname) as group:
-        with open_subvol(fs_client.mgr, fs_handle, volspec, group, subvolname, op_type) as subvolume:
-            yield subvolume
-
-@contextmanager
-def open_at_group_unique(fs_client, fs_handle, volspec, s_groupname, s_subvolname, c_subvolume, c_groupname, c_subvolname, op_type):
+def open_at_group_unique(mgr, fs_handle, volspec, s_groupname, s_subvolname, c_subvolume, c_groupname, c_subvolname, op_type):
     # if a snapshot of a retained subvolume is being cloned to recreate the same subvolume, return
     # the clone subvolume as the source subvolume
     if s_groupname == c_groupname and s_subvolname == c_subvolname:
         yield c_subvolume
     else:
-        with open_at_group(fs_client, fs_handle, volspec, s_groupname, s_subvolname, op_type) as s_subvolume:
+        with open_subvol_in_group(mgr, fs_handle, volspec, s_groupname,
+                                  s_subvolname, op_type) as s_subvolume:
             yield s_subvolume
 
-
-@contextmanager
-def open_clone_subvolume_pair(fs_client, fs_handle, volspec, volname, groupname, subvolname):
-    with open_at_group(fs_client, fs_handle, volspec, groupname, subvolname, SubvolumeOpType.CLONE_INTERNAL) as clone_subvolume:
-        s_volname, s_groupname, s_subvolname, s_snapname = get_clone_source(clone_subvolume)
-        if groupname == s_groupname and subvolname == s_subvolname:
-            # use the same subvolume to avoid metadata overwrites
-            yield (clone_subvolume, clone_subvolume, s_snapname)
-        else:
-            with open_at_group(fs_client, fs_handle, volspec, s_groupname, s_subvolname, SubvolumeOpType.CLONE_SOURCE) as source_subvolume:
-                yield (clone_subvolume, source_subvolume, s_snapname)
-
 def get_clone_state(fs_client, volspec, volname, groupname, subvolname):
     with open_at_volume(fs_client, volspec, volname, groupname, subvolname, SubvolumeOpType.CLONE_INTERNAL) as subvolume:
         return subvolume.state
@@ -84,10 +69,6 @@ def set_clone_state(fs_client, volspec, volname, groupname, subvolname, state):
     with open_at_volume(fs_client, volspec, volname, groupname, subvolname, SubvolumeOpType.CLONE_INTERNAL) as subvolume:
         subvolume.state = (state, True)
 
-def get_clone_source(clone_subvolume):
-    source = clone_subvolume._get_clone_source()
-    return (source['volume'], source.get('group', None), source['subvolume'], source['snapshot'])
-
 def get_next_state_on_error(errnum):
     if errnum == -errno.EINTR:
         next_state = SubvolumeOpSm.transition(SubvolumeTypes.TYPE_CLONE,
@@ -221,9 +202,9 @@ def set_quota_on_clone(fs_handle, clone_volumes_pair):
 
 def do_clone(fs_client, volspec, volname, groupname, subvolname, should_cancel):
     with open_volume_lockless(fs_client, volname) as fs_handle:
-        with open_clone_subvolume_pair(fs_client, fs_handle, volspec, volname,
-                                       groupname, subvolname) \
-            as (subvol0, subvol1, subvol2):
+        with open_clone_subvol_pair_in_group(fs_client.mgr, fs_handle, volspec,
+                volname, groupname, subvolname, lockless=False) as \
+                (subvol0, subvol1, subvol2):
             src_path = subvol1.snapshot_data_path(subvol2)
             dst_path = subvol0.path
             # XXX: this is where cloning (of subvolume's snapshots) actually
@@ -232,14 +213,12 @@ def do_clone(fs_client, volspec, volname, groupname, subvolname, should_cancel):
             set_quota_on_clone(fs_handle, (subvol0, subvol1, subvol2))
 
 def update_clone_failure_status(fs_client, volspec, volname, groupname, subvolname, ve):
-    with open_volume_lockless(fs_client, volname) as fs_handle:
-        with open_clone_subvolume_pair(fs_client, fs_handle, volspec, volname,
-                                       groupname, subvolname) \
-            as (subvol0, subvol1, subvol2) :
-            if ve.errno == -errno.EINTR:
-                subvol0.add_clone_failure(-ve.errno, "user interrupted clone operation")
-            else:
-                subvol0.add_clone_failure(-ve.errno, ve.error_str)
+    with open_clone_subvol_pair_in_vol(fs_client, volspec, volname, groupname,
+            subvolname, lockless=False) as (subvol0, subvol1, subvol2):
+        if ve.errno == -errno.EINTR:
+            subvol0.add_clone_failure(-ve.errno, "user interrupted clone operation")
+        else:
+            subvol0.add_clone_failure(-ve.errno, ve.error_str)
 
 def log_clone_failure(volname, groupname, subvolname, ve):
     if ve.errno == -errno.EINTR:
@@ -265,24 +244,20 @@ def handle_clone_in_progress(fs_client, volspec, volname, index, groupname, subv
 
 def handle_clone_failed(fs_client, volspec, volname, index, groupname, subvolname, should_cancel):
     try:
-        with open_volume(fs_client, volname) as fs_handle:
-            # detach source but leave the clone section intact for later inspection
-            with open_clone_subvolume_pair(fs_client, fs_handle, volspec,
-                                           volname, groupname, subvolname) \
-                as (subvol0, subvol1, subvol2):
-                subvol1.detach_snapshot(subvol2, index)
+        # detach source but leave the clone section intact for later inspection
+        with open_clone_subvol_pair_in_vol(fs_client, volspec, volname, groupname,
+                subvolname) as (subvol0, subvol1, subvol2):
+            subvol1.detach_snapshot(subvol2, index)
     except (MetadataMgrException, VolumeException) as e:
         log.error("failed to detach clone from snapshot: {0}".format(e))
     return (None, True)
 
 def handle_clone_complete(fs_client, volspec, volname, index, groupname, subvolname, should_cancel):
     try:
-        with open_volume(fs_client, volname) as fs_handle:
-            with open_clone_subvolume_pair(fs_client, fs_handle, volspec,
-                                           volname, groupname, subvolname) \
-                as (subvol0, subvol1, subvol2):
-                subvol1.detach_snapshot(subvol2, index)
-                subvol0.remove_clone_source(flush=True)
+        with open_clone_subvol_pair_in_vol(fs_client, volspec, volname,
+                groupname, subvolname) as (subvol0, subvol1, subvol2):
+            subvol1.detach_snapshot(subvol2, index)
+            subvol0.remove_clone_source(flush=True)
     except (MetadataMgrException, VolumeException) as e:
         log.error("failed to detach clone from snapshot: {0}".format(e))
     return (None, True)
@@ -318,7 +293,7 @@ def start_clone_sm(fs_client, volspec, volname, index, groupname, subvolname, st
 
 def clone(fs_client, volspec, volname, index, clone_path, state_table, should_cancel, snapshot_clone_delay):
     log.info("cloning to subvolume path: {0}".format(clone_path))
-    resolved = resolve(volspec, clone_path)
+    resolved = resolve_group_and_subvolume_name(volspec, clone_path)
 
     groupname  = resolved[0]
     subvolname = resolved[1]
index c7ae8c1a3109a88b1b4b37a6ba0c340b85d3bbce..12e77c08837d70f48b055d814a98b396fc227963 100644 (file)
@@ -10,8 +10,8 @@ def splitall(path):
     return splitall(s[0]) + [s[1]]
 
 
-def resolve(vol_spec, path):
-    parts = splitall(path)
+def resolve_group_and_subvolume_name(vol_spec, sv_path):
+    parts = splitall(sv_path)
     if len(parts) != 4 or os.path.join(parts[0], parts[1]) != vol_spec.subvolume_prefix:
         return None
     groupname = None if parts[2] == Group.NO_GROUP_NAME else parts[2]
index eed34db6ee2e5050492977ce9ea7fad480a6b8b2..f982f73bf7df200037d35429cb1ac839781ed767 100644 (file)
@@ -1,7 +1,8 @@
 from contextlib import contextmanager
 
+from .volume import open_volume, open_volume_lockless
+from .group import open_group
 from .template import SubvolumeOpType
-
 from .versions import loaded_subvolumes
 
 def create_subvol(mgr, fs, vol_spec, group, subvolname, size, isolate_nspace, pool, mode, uid, gid):
@@ -72,3 +73,64 @@ def open_subvol(mgr, fs, vol_spec, group, subvolname, op_type):
     subvolume = loaded_subvolumes.get_subvolume_object(mgr, fs, vol_spec, group, subvolname)
     subvolume.open(op_type)
     yield subvolume
+
+
+@contextmanager
+def open_subvol_in_vol(vc, vol_spec, vol_name, group_name, subvol_name,
+                       op_type, lockless=False):
+    open_vol = open_volume_lockless if lockless else open_volume
+
+    with open_vol(vc, vol_name) as vol_handle:
+        with open_group(vol_handle, vol_spec, group_name) as group:
+            with open_subvol(vc.mgr, vol_handle, vol_spec, group, subvol_name,
+                             op_type) as subvol:
+                yield vol_handle, group, subvol
+
+
+@contextmanager
+def open_subvol_in_group(mgr, vol_handle, vol_spec, group_name, subvol_name,
+                         op_type, lockless=False):
+    with open_group(vol_handle, vol_spec, group_name) as group:
+        with open_subvol(mgr, vol_handle, vol_spec, group, subvol_name,
+                         op_type) as subvol:
+            yield subvol
+
+
+@contextmanager
+def open_clone_subvol_pair_in_vol(vc, vol_spec, vol_name, group_name,
+                                  subvol_name, lockless=False):
+    with open_subvol_in_vol(vc, vol_spec, vol_name, group_name, subvol_name,
+                            SubvolumeOpType.CLONE_INTERNAL, lockless) \
+                            as (vol_handle, _, dst_subvol):
+        src_volname, src_group_name, src_subvol_name, src_snap_name = \
+            dst_subvol.get_clone_source()
+
+        if group_name == src_group_name and subvol_name == src_subvol_name:
+            # use the same subvolume to avoid metadata overwrites
+            yield (dst_subvol, dst_subvol, src_snap_name)
+        else:
+            with open_subvol_in_group(vc.mgr, vol_handle, vol_spec,
+                                      src_group_name, src_subvol_name,
+                                      SubvolumeOpType.CLONE_SOURCE) \
+                                      as src_subvol:
+                yield (dst_subvol, src_subvol, src_snap_name)
+
+
+@contextmanager
+def open_clone_subvol_pair_in_group(mgr, vol_handle, vol_spec, volname,
+                                    group_name, subvol_name, lockless=False):
+    with open_subvol_in_group(mgr, vol_handle, vol_spec, group_name,
+                              subvol_name, SubvolumeOpType.CLONE_INTERNAL,
+                              lockless) as dst_subvol:
+        src_volname, src_group_name, src_subvol_name, src_snap_name = \
+            dst_subvol.get_clone_source()
+
+        if group_name == src_group_name and subvol_name == src_subvol_name:
+            # use the same subvolume to avoid metadata overwrites
+            yield (dst_subvol, dst_subvol, src_snap_name)
+        else:
+            with open_subvol_in_group(mgr, vol_handle, vol_spec,
+                                      src_group_name, src_subvol_name,
+                                      SubvolumeOpType.CLONE_SOURCE) \
+                                      as src_subvol:
+                yield (dst_subvol, src_subvol, src_snap_name)
index 338727d0baf36bcdc3903e89019aa71adf0238c5..265f4b06bd4c902a304140a3282beb86836fdbed 100644 (file)
@@ -673,6 +673,11 @@ class SubvolumeV1(SubvolumeBase, SubvolumeTemplate):
             raise VolumeException(-errno.EINVAL, "error fetching subvolume metadata")
         return clone_source
 
+    def get_clone_source(self):
+        src = self._get_clone_source()
+        return (src['volume'], src.get('group', None), src['subvolume'],
+                src['snapshot'])
+
     def _get_clone_failure(self):
         clone_failure = {
             'errno'     : self.metadata_mgr.get_option(MetadataManager.CLONE_FAILURE_SECTION, MetadataManager.CLONE_FAILURE_META_KEY_ERRNO),