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

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