]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/volumes: Fix subvoume snapshot clone failure
authorKotresh HR <khiremat@redhat.com>
Wed, 12 Jan 2022 09:31:53 +0000 (15:01 +0530)
committerKotresh HR <khiremat@redhat.com>
Mon, 28 Feb 2022 11:56:04 +0000 (17:26 +0530)
Problem:
The subvolume snapshot clone fails if the quota on the source
has exceeded. Since the quota is not strictly enforced at the
byte range, this is a possibility.

Cause:
The quota on the clone is set prior to copying the data
from the source. Hence the quota mostly get enforced before
copying the entire data from the source resulting in the
clone failure.

Solution:
Enforce quota on the clone after the data is copied.

Fixes: https://tracker.ceph.com/issues/53848
Signed-off-by: Kotresh HR <khiremat@redhat.com>
(cherry picked from commit 18b85c53af36d89a8c53b40cfc44fe06816a9733)

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

index d2145eb1545884ecdc78bc3f2fd36825ccbde0ea..df3cb93582e9199e3c31fc899ee225ab04a11025 100644 (file)
@@ -4,6 +4,7 @@ import time
 import errno
 import logging
 from contextlib import contextmanager
+from typing import Dict, Union
 
 import cephfs
 
@@ -184,12 +185,27 @@ def bulk_copy(fs_handle, source_path, dst_path, should_cancel):
     if should_cancel():
         raise VolumeException(-errno.EINTR, "clone operation interrupted")
 
+def set_quota_on_clone(fs_handle, clone_volumes_pair):
+    attrs = {}  # type: Dict[str, Union[int, str, None]]
+    src_path = clone_volumes_pair[1].snapshot_data_path(clone_volumes_pair[2])
+    dst_path = clone_volumes_pair[0].path
+    try:
+        attrs["quota"] = int(fs_handle.getxattr(src_path,
+                                                'ceph.quota.max_bytes'
+                                                ).decode('utf-8'))
+    except cephfs.NoData:
+        attrs["quota"] = None
+
+    if attrs["quota"] is not None:
+        clone_volumes_pair[0].set_attrs(dst_path, attrs)
+
 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 clone_volumes:
             src_path = clone_volumes[1].snapshot_data_path(clone_volumes[2])
             dst_path = clone_volumes[0].path
             bulk_copy(fs_handle, src_path, dst_path, should_cancel)
+            set_quota_on_clone(fs_handle, clone_volumes)
 
 def log_clone_failure(volname, groupname, subvolname, ve):
     if ve.errno == -errno.EINTR:
index b735ccd3a6f2cb5136c11b3f16094a633800eeb1..d0cf3ec130c071b6f478f82457cb2407b96842cb 100644 (file)
@@ -150,6 +150,13 @@ class SubvolumeV1(SubvolumeBase, SubvolumeTemplate):
             # attributes of subvolume's content though, are synced during the cloning process.
             attrs = source_subvolume.get_attrs(source_subvolume.snapshot_data_path(snapname))
 
+            # The source of the clone may have exceeded its quota limit as
+            # CephFS quotas are imprecise. Cloning such a source may fail if
+            # the quota on the destination is set before starting the clone
+            # copy. So always set the quota on destination after cloning is
+            # successful.
+            attrs["quota"] = None
+
             # override snapshot pool setting, if one is provided for the clone
             if pool is not None:
                 attrs["data_pool"] = pool
index 1dd6f3fe3aa82e6eb0d02ff45fd5c46d7845d368..f90ec2a4be479f68f5966e4f83ff0dac89601012 100644 (file)
@@ -217,6 +217,13 @@ class SubvolumeV2(SubvolumeV1):
             # attributes of subvolume's content though, are synced during the cloning process.
             attrs = source_subvolume.get_attrs(source_subvolume.snapshot_data_path(snapname))
 
+            # The source of the clone may have exceeded its quota limit as
+            # CephFS quotas are imprecise. Cloning such a source may fail if
+            # the quota on the destination is set before starting the clone
+            # copy. So always set the quota on destination after cloning is
+            # successful.
+            attrs["quota"] = None
+
             # override snapshot pool setting, if one is provided for the clone
             if pool is not None:
                 attrs["data_pool"] = pool