From eaaa5719f76d4ad8af74c3e95baa9a7d37716f40 Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Wed, 20 Oct 2021 22:33:03 +0100 Subject: [PATCH] Use previous unallocated partition when determining 1 MiB reservation in resize/move dialog The create new and paste into new dialogs are both composing a new partition into the unallocated selected_partition they are passed. The starting sector of this unallocated partition is the first sector the newly composed partition could possibly have. To ensure it doesn't overlay with the partition table or EBR (Extended Boot Records) it calls MB_Needed_for_Boot_Record() to indicate if the first 1 MiB needs to be reserved in the dialog or not. Code: Dialog_Partition_New::set_data(..., selected_partition, ...) ... MIN_SPACE_BEFORE_MB = Dialog_Base_Partition::MB_Needed_for_Boot_Record(selected_partition); Dialog_Partition_Copy::set_data(selected_partition, ...) ... MIN_SPACE_BEFORE_MB = Dialog_Base_Partition::MB_Needed_for_Boot_Record(selected_partition); However the resize/move dialog is different. It is passed the existing selected_partition object and the vector of partitions from which it determines if there is a previous unallocated partition object or not. When there is no previous unallocated partition object, there is no need to reserve 1 MiB because the selected_partition can't be moved further to the left. In the other case when there is a previous unallocated partition object the start of the existing selected_partition can be moved to the left. However the code passes the selected_partition object to MB_Needed_for_Boot_Record() so doesn't have the first sector the newly composed partition could possibly have so doesn't reserve the first 1 MiB to prevent it overlapping with the partition table at the start of the drive. These two commits addressed this limitation: * Ensure 1 MiB reserved when moving extended partition to start of drive * Ensure 1 MiB reserved when moving partition to start of disk Code: Dialog_Partition_Resize_Move::set_data(selected_partition, ...) new_partition = selected_partition.clone(); if (selected_partition.type == TYPE_EXTENDED) Resize_Move_Extended(...); else Resoze_Move_Normal(...); Dialog_Partition_Resize_Move::Resize_Move_Normal(...) ... if (previous <= 0) MIN_SPACE_BEFORE_MB = 0; else { if (START < MEBIBYTE / new_partition->sector_size) MIN_SPACE_BEFORE_MB = 1; else MIN_SPACE_BEFORE_MB = Dialog_Base_Partition::MB_Needed_for_Boot_Record(*new_partition); } Dialog_Partition_Resize_Move::Resize_Move_Extended(...) ... if (previous <= 0) MIN_SPACE_BEFORE_MB = 0; else { if (START < MEBIBYTE / new_partition->sector_size) MIN_SPACE_BEFORE_MB = 1; else MIN_SPACE_BEFORE_MB = Dialog_Base_Partition::MB_Needed_for_Boot_Record(*new_partition); } So instead pass the previous unallocated partition object as that contains the left most start sector the newly composed partition could possibly have, therefore the check for overlapping the partition table in the first 1 MiB of the drive can succeed. --- src/Dialog_Partition_Resize_Move.cc | 37 +++++++++++++---------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/src/Dialog_Partition_Resize_Move.cc b/src/Dialog_Partition_Resize_Move.cc index 3064ea1b..dd5bd85d 100644 --- a/src/Dialog_Partition_Resize_Move.cc +++ b/src/Dialog_Partition_Resize_Move.cc @@ -118,11 +118,13 @@ void Dialog_Partition_Resize_Move::Resize_Move_Normal( const PartitionVector & p Sector previous, next ; previous = next = 0 ; + const Partition* prev_unalloc_partition = NULL; //also check the partitions file system ( if this is a 'resize-only' then previous should be 0 ) if (t >= 1 && partitions[t-1].type == TYPE_UNALLOCATED && ! this->fixed_start) { previous = partitions[t -1] .get_sector_length() ; START = partitions[t -1] .sector_start ; + prev_unalloc_partition = &partitions[t-1]; } else START = new_partition->sector_start; @@ -152,18 +154,14 @@ void Dialog_Partition_Resize_Move::Resize_Move_Normal( const PartitionVector & p } } - //Only calculate MIN_SPACE_BEFORE_MB if we have a previous (unallocated) partition. - // Otherwise there will not be enough graphical space to reserve a full 1 MiB for MBR/EBR. - // Since this is an existing partition, if an MBR/EBR was needed then it already exists with enough space. - if ( previous <= 0 ) + // Only need to use MIN_SPACE_BEFORE_MB to reserve 1 MiB to protect the partition + // table or EBR if there is a previous unallocated partition allowing the start of + // this selected partition to be resize/moved to the left. + if (prev_unalloc_partition == NULL) MIN_SPACE_BEFORE_MB = 0 ; else - { - if (START < MEBIBYTE / new_partition->sector_size) - MIN_SPACE_BEFORE_MB = 1 ; - else - MIN_SPACE_BEFORE_MB = Dialog_Base_Partition::MB_Needed_for_Boot_Record( *new_partition ); - } + MIN_SPACE_BEFORE_MB = Dialog_Base_Partition::MB_Needed_for_Boot_Record(*prev_unalloc_partition); + total_length = previous + new_partition->get_sector_length() + next; TOTAL_MB = Utils::round( Utils::sector_to_unit( total_length, new_partition->sector_size, UNIT_MIB ) ); @@ -245,11 +243,13 @@ void Dialog_Partition_Resize_Move::Resize_Move_Extended( const PartitionVector & Sector previous, next ; previous = next = 0 ; + const Partition* prev_unalloc_partition = NULL; //calculate length and start of previous if (t > 0 && partitions[t-1].type == TYPE_UNALLOCATED) { previous = partitions[t -1] .get_sector_length() ; START = partitions[t -1] .sector_start ; + prev_unalloc_partition = &partitions[t-1]; } else START = new_partition->sector_start; @@ -259,18 +259,15 @@ void Dialog_Partition_Resize_Move::Resize_Move_Extended( const PartitionVector & next = partitions[ t +1 ] .get_sector_length() ; //now we have enough data to calculate some important values.. - //Only calculate MIN_SPACE_BEFORE_MB if we have a previous (unallocated) partition. - // Otherwise there will not be enough graphical space to reserve a full 1 MiB for MBR/EBR. - // Since this is an existing partition, if an MBR/EBR was needed then it already exists with enough space. - if ( previous <= 0 ) + + // Only need to use MIN_SPACE_BEFORE_MB to reserve 1 MiB to protect the partition + // table or EBR if there is a previous unallocated partition allowing the start of + // this selected partition to be resize/moved to the left. + if (prev_unalloc_partition == NULL) MIN_SPACE_BEFORE_MB = 0 ; else - { - if (START < MEBIBYTE / new_partition->sector_size) - MIN_SPACE_BEFORE_MB = 1; - else - MIN_SPACE_BEFORE_MB = Dialog_Base_Partition::MB_Needed_for_Boot_Record(*new_partition); - } + MIN_SPACE_BEFORE_MB = Dialog_Base_Partition::MB_Needed_for_Boot_Record(*prev_unalloc_partition); + total_length = previous + new_partition->get_sector_length() + next; TOTAL_MB = Utils::round( Utils::sector_to_unit( total_length, new_partition->sector_size, UNIT_MIB ) ); MB_PER_PIXEL = TOTAL_MB / 500.00 ;