From 023164edec805a18cb9cd8076aba78f591239fd9 Mon Sep 17 00:00:00 2001 From: Vratislav Podzimek Date: Tue, 16 Sep 2014 15:36:58 +0200 Subject: [PATCH] Make sure autopart requests fit in somewhere When doing LVM/BTRFS autopart we implicitly schedule one partition on each disk as a device for LVM/BTRFS. Those implicitly scheduled partitions are requested to be at least 500 MiB big and grow if possible. That's fine and works well until we have many small disks (e.g. DASDs) and need to fit another partition (for e.g. swap) that is in combination with the 500MiB implicit partition bigger than any disk we have. Thus we need to make sure all our partition requests fit somewhere with the implicitly scheduled partitions by making the latter ones smaller or by removing them if needed. Related: rhbz#1202877 (cherry picked from commit a6d17f94b959c9ed2b3eb1f8aa56de58951a0865) Conflicts: blivet/devices.py blivet/partitioning.py --- blivet/devices/partition.py | 5 ++++- blivet/partitioning.py | 29 +++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/blivet/devices/partition.py b/blivet/devices/partition.py index bbc637bfd..62e34ce46 100644 --- a/blivet/devices/partition.py +++ b/blivet/devices/partition.py @@ -736,7 +736,10 @@ def _setSize(self, newsize): raise ValueError("new size must of type Size") if not self.exists: - raise errors.DeviceError("device does not exist", self.name) + # device does not exist (a partition request), just set basic values + self._size = newsize + self.req_size = newsize + self.req_base_size = newsize if newsize > self.disk.size: raise ValueError("partition size would exceed disk size") diff --git a/blivet/partitioning.py b/blivet/partitioning.py index 8b5269287..8e0776321 100644 --- a/blivet/partitioning.py +++ b/blivet/partitioning.py @@ -115,7 +115,7 @@ def _scheduleImplicitPartitions(storage, disks, min_luks_entropy=0): return devs -def _schedulePartitions(storage, disks, min_luks_entropy=0, requests=None): +def _schedulePartitions(storage, disks, implicit_devices, min_luks_entropy=0, requests=None): """ Schedule creation of autopart/reqpart partitions. This only schedules the requests for actual partitions. @@ -242,8 +242,29 @@ def _schedulePartitions(storage, disks, min_luks_entropy=0, requests=None): parents=dev) storage.createDevice(luks_dev) - # make sure preexisting broken lvm/raid configs get out of the way - return + if storage.autoPartType in (AUTOPART_TYPE_LVM, AUTOPART_TYPE_LVM_THINP, + AUTOPART_TYPE_BTRFS): + # doing LVM/BTRFS -- make sure the newly created partition fits in some + # free space together with one of the implicitly requested partitions + smallest_implicit = sorted(implicit_devices, key=lambda d: d.size)[0] + if (request.size + smallest_implicit.size) > all_free[0]: + # not enough space to allocate the smallest implicit partition + # and the request, make the implicit partition smaller with + # fixed size in order to make space for the request + new_size = all_free[0] - request.size + + # subtract the size from the biggest free region and reorder the + # list + all_free[0] -= request.size + all_free.sort(reverse=True) + + if new_size > Size(0): + smallest_implicit.size = new_size + else: + implicit_devices.remove(smallest_implicit) + storage.destroyDevice(smallest_implicit) + + return implicit_devices def _scheduleVolumes(storage, devs): """ Schedule creation of autopart lvm/btrfs volumes. @@ -419,7 +440,7 @@ def doAutoPartition(storage, data, min_luks_entropy=0): raise NotEnoughFreeSpaceError(_("Not enough free space on disks for " "automatic partitioning")) - _schedulePartitions(storage, disks, min_luks_entropy=min_luks_entropy) + devs = _schedulePartitions(storage, disks, devs, min_luks_entropy=min_luks_entropy) # run the autopart function to allocate and grow partitions doPartitioning(storage)