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

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