neil / rpms / python-blivet

Forked from rpms/python-blivet a year ago
Clone

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

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