diff --git a/pyanaconda/storage/devices.py b/pyanaconda/storage/devices.py
index da40d39..c809842 100644
--- a/pyanaconda/storage/devices.py
+++ b/pyanaconda/storage/devices.py
@@ -1088,6 +1088,7 @@ class PartitionDevice(StorageDevice):
                  size=None, grow=False, maxsize=None,
                  major=None, minor=None, bootable=None,
                  sysfsPath='', parents=None, exists=None,
+                 start=None, end=None,
                  partType=None, primary=False, weight=0):
         """ Create a PartitionDevice instance.
 
@@ -1126,6 +1127,8 @@ class PartitionDevice(StorageDevice):
         self.req_base_size = 0
         self.req_max_size = 0
         self.req_base_weight = 0
+        self.req_start_sector = None
+        self.req_end_sector = None
 
         self._bootable = False
 
@@ -1191,6 +1194,15 @@ class PartitionDevice(StorageDevice):
 
             self.req_base_weight = weight
 
+            if start is not None and end is None:
+                raise ValueError("must specify both start and end or neither")
+
+            if start is not None and end is not None and end <= start:
+                raise ValueError("requested end sector is before start")
+
+            self.req_start_sector = start
+            self.req_end_sector = end
+
     def __repr__(self):
         s = StorageDevice.__repr__(self)
         s += ("  grow = %(grow)s  max size = %(maxsize)s  bootable = %(bootable)s\n"
diff --git a/pyanaconda/storage/partitioning.py b/pyanaconda/storage/partitioning.py
index b00d5a4..7746e65 100644
--- a/pyanaconda/storage/partitioning.py
+++ b/pyanaconda/storage/partitioning.py
@@ -581,6 +581,16 @@ def partitionCompare(part1, part2):
     if part2.req_base_weight:
         ret += part2.req_base_weight
 
+    # requests that include a start sector must be allocated early
+    if part1.req_start_sector is not None and part2.req_start_sector is None:
+        ret -= 1000
+    elif part1.req_start_sector is None and part2.req_start_sector is not None:
+        ret += 1000
+    elif part1.req_start_sector is not None and \
+         part2.req_start_sector is not None and \
+         part1.req_disks == part2.req_disks:
+        ret += cmp(part1.req_start_sector, part2.req_start_sector) * 1000
+
     # more specific disk specs to the front of the list
     # req_disks being empty is equivalent to it being an infinitely long list
     if part1.req_disks and not part2.req_disks:
@@ -679,7 +689,7 @@ def getNextPartitionType(disk, no_primary=None):
     return part_type
 
 def getBestFreeSpaceRegion(disk, part_type, req_size,
-                           boot=None, best_free=None, grow=None):
+                           boot=None, best_free=None, grow=None, start=None):
     """ Return the "best" free region on the specified disk.
 
         For non-boot partitions, we return the largest free region on the
@@ -707,6 +717,7 @@ def getBestFreeSpaceRegion(disk, part_type, req_size,
                     (boolean)
             best_free -- current best free region for this partition
             grow -- indicates whether this is a growable request
+            start -- requested start sector
 
     """
     log.debug("getBestFreeSpaceRegion: disk=%s part_type=%d req_size=%dMB "
@@ -766,7 +777,8 @@ def getBestFreeSpaceRegion(disk, part_type, req_size,
             op = gt
         else:
             op = lt
-        if req_size <= free_size:
+        if req_size <= free_size and (start is None or
+                                      free_geom.containsSector(start)):
             if not best_free or op(free_geom.length, best_free.length):
                 best_free = free_geom
 
@@ -1152,7 +1164,8 @@ def allocatePartitions(storage, disks, partitions, freespace, bootloader=None):
                                           _part.req_size,
                                           best_free=current_free,
                                           boot=boot,
-                                          grow=_part.req_grow)
+                                          grow=_part.req_grow,
+                                          start=_part.req_start_sector)
 
             if best == free and not _part.req_primary and \
                new_part_type == parted.PARTITION_NORMAL:
@@ -1169,6 +1182,10 @@ def allocatePartitions(storage, disks, partitions, freespace, bootloader=None):
                                                   grow=_part.req_grow)
 
             if best and free != best:
+                if _part.req_start_sector is not None and \
+                   not best.containsSector(_part.req_end_sector):
+                    raise PartitioningError("no free region contains requested "
+                                            "start/end sectors")
                 update = True
                 if _part.req_grow:
                     log.debug("evaluating growth potential for new layout")
