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