From a17bd659e26708a20b64b7a8d733debd761eb7ba Mon Sep 17 00:00:00 2001 From: Dan Bungert Date: Wed, 9 Mar 2022 16:28:41 -0700 Subject: [PATCH 1/3] filesystem: move MiB constant to fix import loop --- subiquity/common/filesystem/manipulator.py | 3 +-- subiquity/models/filesystem.py | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/subiquity/common/filesystem/manipulator.py b/subiquity/common/filesystem/manipulator.py index 3fba58f9..18d9e760 100644 --- a/subiquity/common/filesystem/manipulator.py +++ b/subiquity/common/filesystem/manipulator.py @@ -21,13 +21,12 @@ from subiquity.common.filesystem import boot, gaps from subiquity.common.types import Bootloader from subiquity.models.filesystem import ( align_up, + MiB, Partition, ) log = logging.getLogger('subiquity.common.filesystem.manipulator') - -MiB = 1024 * 1024 BIOS_GRUB_SIZE_BYTES = 1 * MiB PREP_GRUB_SIZE_BYTES = 8 * MiB diff --git a/subiquity/models/filesystem.py b/subiquity/models/filesystem.py index ee0189cb..0ff62c3e 100644 --- a/subiquity/models/filesystem.py +++ b/subiquity/models/filesystem.py @@ -33,9 +33,10 @@ from probert.storage import StorageInfo from subiquity.common.types import Bootloader, OsProber - log = logging.getLogger('subiquity.models.filesystem') +MiB = 1024 * 1024 + def _set_backlinks(obj): if obj.id is None: From d0ccc98aadc489abc4cca24549c654b2a94df74f Mon Sep 17 00:00:00 2001 From: Dan Bungert Date: Wed, 9 Mar 2022 15:05:40 -0700 Subject: [PATCH 2/3] filesystem: add alignment data --- subiquity/models/filesystem.py | 40 ++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/subiquity/models/filesystem.py b/subiquity/models/filesystem.py index 0ff62c3e..3e343166 100644 --- a/subiquity/models/filesystem.py +++ b/subiquity/models/filesystem.py @@ -576,6 +576,10 @@ class Disk(_Device): _info = attr.ib(default=None) + def alignment_data(self): + ptable = self.ptable_for_new_partition() + return self._m._partition_alignment_data[ptable] + def info_for_display(self): bus = self._info.raw.get('ID_BUS', None) major = self._info.raw.get('MAJOR', None) @@ -928,12 +932,44 @@ def align_down(size, block_size=1 << 20): return size & ~(block_size - 1) +@attr.s(auto_attribs=True) +class PartitionAlignmentData: + part_align: int + min_gap_size: int + min_start_offset: int + min_end_offset: int + primary_part_limit: int + ebr_space: int = 0 + + class FilesystemModel(object): - lower_size_limit = 128 * (1 << 20) - target = None + _partition_alignment_data = { + 'gpt': PartitionAlignmentData( + part_align=MiB, + min_gap_size=MiB, + min_start_offset=GPT_OVERHEAD//2, + min_end_offset=GPT_OVERHEAD//2, + primary_part_limit=128), + 'msdos': PartitionAlignmentData( + part_align=MiB, + min_gap_size=MiB, + min_start_offset=GPT_OVERHEAD//2, + min_end_offset=0, + ebr_space=MiB, + primary_part_limit=4), + # XXX check this one!! + 'vtoc': PartitionAlignmentData( + part_align=MiB, + min_gap_size=MiB, + min_start_offset=GPT_OVERHEAD//2, + min_end_offset=0, + ebr_space=MiB, + primary_part_limit=3), + } + @classmethod def is_mounted_filesystem(self, fstype): if fstype in [None, 'swap']: From 2d325473ac24adb634087675731ba70313618c42 Mon Sep 17 00:00:00 2001 From: Dan Bungert Date: Wed, 9 Mar 2022 17:05:31 -0700 Subject: [PATCH 3/3] filesystem: test for gap vs align agreement --- subiquity/models/tests/test_filesystem.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/subiquity/models/tests/test_filesystem.py b/subiquity/models/tests/test_filesystem.py index 02c46855..034166bb 100644 --- a/subiquity/models/tests/test_filesystem.py +++ b/subiquity/models/tests/test_filesystem.py @@ -661,3 +661,20 @@ class TestAutoInstallConfig(unittest.TestCase): self.assertTrue(disk1p1.id in rendered_ids) self.assertTrue(disk2.id in rendered_ids) self.assertTrue(disk2p1.id in rendered_ids) + + +class TestAlignmentData(unittest.TestCase): + def test_alignment_gaps_coherence(self): + for ptable in 'gpt', 'msdos', 'vtoc': + model = make_model(Bootloader.NONE) + disk1 = make_disk(model, ptable=ptable) + gaps_max = gaps.largest_gap_size(disk1) + + align_data = disk1.alignment_data() + align_max = (disk1.size - align_data.min_start_offset + - align_data.min_end_offset) + + # The alignment data currently has a better notion of end + # information, so gaps produces numbers that are too small by 1MiB + # for ptable != 'gpt' + self.assertTrue(gaps_max <= align_max, f'ptable={ptable}')