[PATCH 2/2] Align free regions before choosing one.

David Lehman dlehman at redhat.com
Fri Jun 26 22:01:33 UTC 2015


By aligning the start sector of free regions we improve our ability to
select an appropriate free region in which to place a new partition.
When the start sector alignment is not taken into consideration the
possibility arises that aligning the start sector will shrink the size
of the free region below the requested size of the partition.

Related: rhbz#1181494
---
 blivet/partitioning.py | 41 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 36 insertions(+), 5 deletions(-)

diff --git a/blivet/partitioning.py b/blivet/partitioning.py
index 5df0485..665d1a0 100644
--- a/blivet/partitioning.py
+++ b/blivet/partitioning.py
@@ -572,7 +572,8 @@ def getNextPartitionType(disk, no_primary=None):
     return part_type
 
 def getBestFreeSpaceRegion(disk, part_type, req_size, start=None,
-                           boot=None, best_free=None, grow=None):
+                           boot=None, best_free=None, grow=None,
+                           alignment=None):
     """ Return the "best" free region on the specified disk.
 
         For non-boot partitions, we return the largest free region on the
@@ -601,6 +602,8 @@ def getBestFreeSpaceRegion(disk, part_type, req_size, start=None,
         :type best_free: :class:`parted.Geometry`
         :keyword grow: indicates whether this is a growable request
         :type grow: bool
+        :keyword alignment: disk alignment requirements
+        :type alignment: :class:`parted.Alignment`
 
     """
     log.debug("getBestFreeSpaceRegion: disk=%s part_type=%d req_size=%s "
@@ -608,8 +611,32 @@ def getBestFreeSpaceRegion(disk, part_type, req_size, start=None,
               disk.device.path, part_type, req_size, boot, best_free, grow,
               start)
     extended = disk.getExtendedPartition()
+    alignment = alignment or parted.Alignment(offset=0, grainSize=1)
 
     for free_geom in disk.getFreeSpaceRegions():
+        # align the start sector of the free region since we will be aligning
+        # the start sector of the partition
+        if start is not None and \
+           not alignment.isAligned(free_geom, free_geom.start):
+            log.debug("aligning start sector of region %d-%d", free_geom.start,
+                                                               free_geom.end)
+            try:
+                aligned_start = alignment.alignUp(free_geom, free_geom.start)
+            except ArithmeticError:
+                aligned_start = None
+            else:
+                # parted tends to align down when it cannot align up
+                if aligned_start < free_geom.start:
+                    aligned_start = None
+
+            if aligned_start is None:
+                log.debug("failed to align start sector -- skipping region")
+                continue
+
+            free_geom = parted.Geometry(device=free_geom.device,
+                                        start=aligned_start,
+                                        end=free_geom.end)
+
         log.debug("checking %d-%d (%s)", free_geom.start, free_geom.end,
                                          Size(free_geom.getLength(unit="B")))
         if start is not None and not free_geom.containsSector(start):
@@ -1095,7 +1122,8 @@ def allocatePartitions(storage, disks, partitions, freespace):
                                           start=_part.req_start_sector,
                                           best_free=current_free,
                                           boot=boot,
-                                          grow=_part.req_grow)
+                                          grow=_part.req_grow,
+                                          alignment=disklabel.alignment)
 
             if best == free and not _part.req_primary and \
                new_part_type == parted.PARTITION_NORMAL:
@@ -1110,7 +1138,8 @@ def allocatePartitions(storage, disks, partitions, freespace):
                                                   start=_part.req_start_sector,
                                                   best_free=current_free,
                                                   boot=boot,
-                                                  grow=_part.req_grow)
+                                                  grow=_part.req_grow,
+                                                  alignment=disklabel.alignment)
 
             if best and free != best:
                 update = True
@@ -1146,7 +1175,8 @@ def allocatePartitions(storage, disks, partitions, freespace):
                                                                req_size,
                                                                start=_part.req_start_sector,
                                                                boot=boot,
-                                                               grow=_part.req_grow)
+                                                               grow=_part.req_grow,
+                                                               alignment=disklabel.alignment)
                                 if not _free:
                                     log.info("not enough space after adding "
                                              "extended partition for growth test")
@@ -1264,7 +1294,8 @@ def allocatePartitions(storage, disks, partitions, freespace):
                                           aligned_size,
                                           start=_part.req_start_sector,
                                           boot=boot,
-                                          grow=_part.req_grow)
+                                          grow=_part.req_grow,
+                                          alignment=disklabel.alignment)
             if not free:
                 raise PartitioningError(_("not enough free space after "
                                         "creating extended partition"))
-- 
2.4.3



More information about the anaconda-patches mailing list