Fix rollback when growing a partition by more than twice fails (#791875)

Attempt to grow a partition to more than twice it's size.  If committing
that change to the partition fails in such a way that the new larger
partition boundaries are not written to the disk drive then rolling back
will fail with libparted error:
    Can't have overlapping partitions.

Example operation details:

    Grow /dev/sdb8 from 1.00 GiB to 2.20 GiB
    * calibrate /dev/sdb8                                      (SUCCESS)
    * check file system on /dev/sdb8 for errors and (if poss...(SUCCESS)
    * grow partition from 1.00 GiB to 2.20 GiB                 (ERROR)
    * attempt to rollback failed change to the partition       (ERROR)
        original start: 7350272
        original end:   9447423
        original size:  2097152 (1.00 GiB)
      * libparted messages                                     (ERROR)
          Can't have overlapping partitions.

What happened is that resize_move_partition() passed the new Partition
object to resize_move_partition_implement() as the source partition for
the rollback, and than called ped_disk_partition_by_sector() with a
sector in the middle to identify the partition to be changed.  However
the new partition was never written to the drive so in the middle was
outside the old smaller partition.  Therefore libparted identified empty
space after the partition, rather than the partition itself, as the
intended target so when ped_disk_set_partition_geom() was called it
reported error "Can't have overlapping partitions" because it thought
another partition was being created with the same boundaries as the old
partition, rather than the boundaries of the old partition being
updated.

The same error also occurs when rolling back a failed partition change
as part of a move operation when the middle of the new partition falls
outside of the boundaries of the old partition.

Fix by making a temporary Partition object from the intersection of the
old and new partition boundaries just to be used to identify the
partition being changed to libparted.  As this is only rolling back a
single step adjusting the partition boundaries as part of a resize
and/or move operation, the old and new partition boundaries must
intersect (and in fact that intersection contains the file system data).

Bug 791875 - Rollback specific failed partition change steps
This commit is contained in:
Mike Fleetwood 2017-12-30 12:11:44 +00:00 committed by Curtis Gedak
parent 0b5bf83b22
commit f54dd10707
1 changed files with 13 additions and 1 deletions

View File

@ -2778,11 +2778,21 @@ bool GParted_Core::resize_move_partition( const Partition & partition_old,
operationdetail.add_child(
OperationDetail( _("attempt to rollback failed change to the partition") ) );
// Create a temporary partition which is the intersection of the old and
// new partitions so that the middle sector can be used to identify the
// partition needing rollback, whether or not the above failed partition
// change made it to the drive or not.
Partition *partition_intersection = partition_new.clone();
partition_intersection->sector_start = std::max( partition_old.sector_start,
partition_new.sector_start );
partition_intersection->sector_end = std::min( partition_old.sector_end,
partition_new.sector_end );
Partition *partition_restore = partition_old.clone();
// Ensure that old partition boundaries are not modified
partition_restore->alignment = ALIGN_STRICT;
bool rollback_success = resize_move_partition_implement( partition_new, *partition_restore,
bool rollback_success = resize_move_partition_implement( *partition_intersection, *partition_restore,
new_start, new_end );
operationdetail.get_last_child().add_child(
@ -2799,6 +2809,8 @@ bool GParted_Core::resize_move_partition( const Partition & partition_old,
delete partition_restore;
partition_restore = NULL;
delete partition_intersection;
partition_intersection = NULL;
operationdetail.get_last_child().set_success_and_capture_errors( rollback_success );
}