neil / rpms / python-blivet

Forked from rpms/python-blivet a year ago
Clone

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

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