From 610b59b272ba6207c3c50bf191d198cc4f4b4118 Mon Sep 17 00:00:00 2001 From: Christian Rohmann Date: Sun, 13 Dec 2020 15:07:10 +0100 Subject: [PATCH] Add support for RBD fast-diff feature for backups stored in Ceph This change enables the FAST_DIFF feature for backup images stored via Ceph RBD. It is enabled together with EXCLUSIVE_LOCK and OBJECT_MAP as required. With FAST_DIFF enabled, the generation of diffs between images and snapshots as well as determining the actual data usage of a snapshot is sped up significantly. Closes-Bug #1907964 Change-Id: I5e35de28007558267f9215cbac03a38d7c74612c (cherry picked from commit 0e8807388209086ee60e1c9f11a48ed6191e4178) (cherry picked from commit cbf9def32b31bcc3d4894d05e6fe665005006492) --- cinder/backup/drivers/ceph.py | 47 ++++++++++++------- .../unit/backup/drivers/test_backup_ceph.py | 15 ++++++ .../notes/bug-1907964-9277e5ddec2abeda.yaml | 11 +++++ 3 files changed, 56 insertions(+), 17 deletions(-) create mode 100644 releasenotes/notes/bug-1907964-9277e5ddec2abeda.yaml diff --git a/cinder/backup/drivers/ceph.py b/cinder/backup/drivers/ceph.py index 1252e609b9f..05c7a158904 100644 --- a/cinder/backup/drivers/ceph.py +++ b/cinder/backup/drivers/ceph.py @@ -244,6 +244,11 @@ class CephBackupDriver(driver.BackupDriver): """Determine if journaling is supported by our version of librbd.""" return hasattr(self.rbd, 'RBD_FEATURE_JOURNALING') + @property + def _supports_fast_diff(self): + """Determine if fast-diff is supported by our version of librbd.""" + return hasattr(self.rbd, 'RBD_FEATURE_FAST_DIFF') + def _get_rbd_support(self): """Determine RBD features supported by our version of librbd.""" old_format = True @@ -255,24 +260,22 @@ class CephBackupDriver(driver.BackupDriver): old_format = False features |= self.rbd.RBD_FEATURE_STRIPINGV2 - # journaling requires exclusive_lock; check both together if CONF.backup_ceph_image_journals: - if self._supports_exclusive_lock and self._supports_journaling: - old_format = False - features |= (self.rbd.RBD_FEATURE_EXCLUSIVE_LOCK | - self.rbd.RBD_FEATURE_JOURNALING) - else: - # FIXME (tasker): when the backup manager supports loading the - # driver during its initialization, this exception should be - # moved to the driver's initialization so that it can stop - # the service from starting when the underyling RBD does not - # support the requested features. - LOG.error("RBD journaling not supported - unable to " - "support per image mirroring in backup pool") - raise exception.BackupInvalidCephArgs( - _("Image Journaling set but RBD backend does " - "not support journaling") - ) + LOG.debug("RBD journaling supported by backend and requested " + "via config. Enabling it together with " + "exclusive-lock") + old_format = False + features |= (self.rbd.RBD_FEATURE_EXCLUSIVE_LOCK | + self.rbd.RBD_FEATURE_JOURNALING) + + # NOTE(christian_rohmann): Check for fast-diff support and enable it + if self._supports_fast_diff: + LOG.debug("RBD also supports fast-diff, enabling it " + "together with exclusive-lock and object-map") + old_format = False + features |= (self.rbd.RBD_FEATURE_EXCLUSIVE_LOCK | + self.rbd.RBD_FEATURE_OBJECT_MAP | + self.rbd.RBD_FEATURE_FAST_DIFF) return (old_format, features) @@ -294,6 +297,16 @@ class CephBackupDriver(driver.BackupDriver): with rbd_driver.RADOSClient(self, self._ceph_backup_pool): pass + # NOTE(christian_rohmann): Check features required for journaling + if CONF.backup_ceph_image_journals: + if not self._supports_exclusive_lock and self._supports_journaling: + LOG.error("RBD journaling not supported - unable to " + "support per image mirroring in backup pool") + raise exception.BackupInvalidCephArgs( + _("Image Journaling set but RBD backend does " + "not support journaling") + ) + def _connect_to_rados(self, pool=None): """Establish connection to the backup Ceph cluster.""" client = eventlet.tpool.Proxy(self.rados.Rados( diff --git a/cinder/tests/unit/backup/drivers/test_backup_ceph.py b/cinder/tests/unit/backup/drivers/test_backup_ceph.py index 8afdea46291..3d02f9b70df 100644 --- a/cinder/tests/unit/backup/drivers/test_backup_ceph.py +++ b/cinder/tests/unit/backup/drivers/test_backup_ceph.py @@ -238,11 +238,15 @@ class BackupCephTestCase(test.TestCase): del self.service.rbd.RBD_FEATURE_STRIPINGV2 del self.service.rbd.RBD_FEATURE_EXCLUSIVE_LOCK del self.service.rbd.RBD_FEATURE_JOURNALING + del self.service.rbd.RBD_FEATURE_OBJECT_MAP + del self.service.rbd.RBD_FEATURE_FAST_DIFF self.assertFalse(hasattr(self.service.rbd, 'RBD_FEATURE_LAYERING')) self.assertFalse(hasattr(self.service.rbd, 'RBD_FEATURE_STRIPINGV2')) self.assertFalse(hasattr(self.service.rbd, 'RBD_FEATURE_EXCLUSIVE_LOCK')) self.assertFalse(hasattr(self.service.rbd, 'RBD_FEATURE_JOURNALING')) + self.assertFalse(hasattr(self.service.rbd, 'RBD_FEATURE_OBJECT_MAP')) + self.assertFalse(hasattr(self.service.rbd, 'RBD_FEATURE_FAST_DIFF')) oldformat, features = self.service._get_rbd_support() self.assertTrue(oldformat) @@ -282,6 +286,17 @@ class BackupCephTestCase(test.TestCase): self.assertFalse(oldformat) self.assertEqual(1 | 2 | 4 | 64, features) + # + # test that FAST_DIFF is enabled if supported by RBD + # this also enables OBJECT_MAP as required by Ceph + # + self.service.rbd.RBD_FEATURE_OBJECT_MAP = 8 + self.service.rbd.RBD_FEATURE_FAST_DIFF = 16 + + oldformat, features = self.service._get_rbd_support() + self.assertFalse(oldformat) + self.assertEqual(1 | 2 | 4 | 8 | 16 | 64, features) + @common_mocks def test_get_backup_snap_name(self): snap_name = 'backup.%s.snap.3824923.1412' % (uuid.uuid4()) diff --git a/releasenotes/notes/bug-1907964-9277e5ddec2abeda.yaml b/releasenotes/notes/bug-1907964-9277e5ddec2abeda.yaml new file mode 100644 index 00000000000..1802a2e403c --- /dev/null +++ b/releasenotes/notes/bug-1907964-9277e5ddec2abeda.yaml @@ -0,0 +1,11 @@ +--- +fixes: + - | + RBD driver `bug #1907964 + `_: Add support + for fast-diff on backup images stored in Ceph. + Provided fast-diff is supported by the backend it will automatically be + enabled and used. + With fast-diff enabled, the generation of diffs between images and + snapshots as well as determining the actual data usage of a snapshot + is speed up significantly. \ No newline at end of file