Blame SOURCES/0010-Use-bigger-chunk-size-for-thinpools-bigger-than-15.8.patch

3709d2
From 06cafbbbbff0aae3634eb2908d25d0dc46c2048b Mon Sep 17 00:00:00 2001
3709d2
From: Vojtech Trefny <vtrefny@redhat.com>
3709d2
Date: Tue, 9 Nov 2021 15:52:48 +0100
3709d2
Subject: [PATCH] Use bigger chunk size for thinpools bigger than ~15.88 TiB
3709d2
3709d2
With our default chunk size of 64 KiB we cannot create bigger
3709d2
thin pools than 15.88 TiB. Unfortunately we need to specify chunk
3709d2
size to be able to calculate thin metadata properly so we can't
3709d2
simply leave this to LVM to determine the correct chunk size.
3709d2
---
3709d2
 blivet/devicelibs/lvm.py       | 11 +++++++++++
3709d2
 blivet/devices/lvm.py          |  6 +++---
3709d2
 tests/devices_test/lvm_test.py | 11 +++++++++++
3709d2
 3 files changed, 25 insertions(+), 3 deletions(-)
3709d2
3709d2
diff --git a/blivet/devicelibs/lvm.py b/blivet/devicelibs/lvm.py
3709d2
index d56a76ed..cb6f655e 100644
3709d2
--- a/blivet/devicelibs/lvm.py
3709d2
+++ b/blivet/devicelibs/lvm.py
3709d2
@@ -20,6 +20,7 @@
3709d2
 # Author(s): Dave Lehman <dlehman@redhat.com>
3709d2
 #
3709d2
 
3709d2
+import math
3709d2
 import os
3709d2
 import re
3709d2
 
3709d2
@@ -51,6 +52,7 @@ LVM_THINP_MIN_METADATA_SIZE = Size("2 MiB")
3709d2
 LVM_THINP_MAX_METADATA_SIZE = Size("16 GiB")
3709d2
 LVM_THINP_MIN_CHUNK_SIZE = Size("64 KiB")
3709d2
 LVM_THINP_MAX_CHUNK_SIZE = Size("1 GiB")
3709d2
+LVM_THINP_ADDRESSABLE_CHUNK_SIZE = Size("17455015526400 B")  # 15.88 TiB
3709d2
 
3709d2
 raid_levels = raid.RAIDLevels(["linear", "striped", "raid1", "raid4", "raid5", "raid6", "raid10"])
3709d2
 raid_seg_types = list(itertools.chain.from_iterable([level.names for level in raid_levels if level.name != "linear"]))
3709d2
@@ -225,3 +227,12 @@ def is_lvm_name_valid(name):
3709d2
         return False
3709d2
 
3709d2
     return True
3709d2
+
3709d2
+
3709d2
+def recommend_thpool_chunk_size(thpool_size):
3709d2
+    # calculation of the recommended chunk size by LVM is so complicated that we
3709d2
+    # can't really replicate it, but we know that 64 KiB chunk size gives us
3709d2
+    # upper limit of ~15.88 TiB so we will just add 64 KiB to the chunk size
3709d2
+    # for every ~15.88 TiB of thinpool data size
3709d2
+    return min(math.ceil(thpool_size / LVM_THINP_ADDRESSABLE_CHUNK_SIZE) * LVM_THINP_MIN_CHUNK_SIZE,
3709d2
+               LVM_THINP_MAX_CHUNK_SIZE)
3709d2
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py
3709d2
index 51d785d9..c61eeb4b 100644
3709d2
--- a/blivet/devices/lvm.py
3709d2
+++ b/blivet/devices/lvm.py
3709d2
@@ -1634,9 +1634,9 @@ class LVMThinPoolMixin(object):
3709d2
             return
3709d2
 
3709d2
         # we need to know chunk size to calculate recommended metadata size
3709d2
-        if self._chunk_size == 0:
3709d2
-            self._chunk_size = Size(blockdev.LVM_DEFAULT_CHUNK_SIZE)
3709d2
-            log.debug("Using default chunk size: %s", self._chunk_size)
3709d2
+        if self._chunk_size == 0 or enforced:
3709d2
+            self._chunk_size = lvm.recommend_thpool_chunk_size(self._size)
3709d2
+            log.debug("Using recommended chunk size: %s", self._chunk_size)
3709d2
 
3709d2
         old_md_size = self._metadata_size
3709d2
         old_pmspare_size = self.vg.pmspare_size
3709d2
diff --git a/tests/devices_test/lvm_test.py b/tests/devices_test/lvm_test.py
3709d2
index 4156d0bf..336c5b99 100644
3709d2
--- a/tests/devices_test/lvm_test.py
3709d2
+++ b/tests/devices_test/lvm_test.py
3709d2
@@ -442,6 +442,17 @@ class LVMDeviceTest(unittest.TestCase):
3709d2
             self.assertFalse(pool.exists)
3709d2
             self.assertTrue(lvm.lvremove.called)
3709d2
 
3709d2
+    def test_lvmthinpool_chunk_size(self):
3709d2
+        pv = StorageDevice("pv1", fmt=blivet.formats.get_format("lvmpv"),
3709d2
+                           size=Size("100 TiB"))
3709d2
+        vg = LVMVolumeGroupDevice("testvg", parents=[pv])
3709d2
+        pool = LVMLogicalVolumeDevice("pool1", parents=[vg], size=Size("500 MiB"), seg_type="thin-pool")
3709d2
+        self.assertEqual(pool.chunk_size, Size("64 KiB"))
3709d2
+
3709d2
+        pool.size = Size("16 TiB")
3709d2
+        pool.autoset_md_size(enforced=True)
3709d2
+        self.assertEqual(pool.chunk_size, Size("128 KiB"))
3709d2
+
3709d2
 
3709d2
 class TypeSpecificCallsTest(unittest.TestCase):
3709d2
     def test_type_specific_calls(self):
3709d2
-- 
3709d2
2.31.1
3709d2