diff --git a/HACKING b/HACKING index 3f2d29fa..28d5cb47 100644 --- a/HACKING +++ b/HACKING @@ -24,10 +24,15 @@ partition usage and unallocated space ===================================== After addressing bug #499202 GParted now also displays unallocated space -as well as used and unused space for recognised file systems. The -unallocated space is shown graphically and the numeric figure is shown -in the Information Dialog if it is greater than zero. Additionally a -warning is reported if the unallocated space is considered too much. +as well as used and unused space for recognised file systems. Many file +systems which actually fill their partition report a small amount of +intrinsic unallocated space when mounted, but not when unmounted. To +avoid confusing the user and unnecessarily alarming them don't show +unallocated space below a threshold, 2 to 5% depending on partition +size. It is just included in the used figure instead. (This is +effectively how GParted behaved before bug #499202 was addressed). When +above the threshold unallocated space is shown graphically, the numeric +figure is shown in the Information Dialog and a is warning displayed. See the code and commit messages for more details. Worked example of partition and file system usage for a newly created @@ -54,8 +59,14 @@ used = fs_size - fs_free = 407128 - 406808 = 320 = 160.00 KiB unused = fs_free = 406808 = 198.64 MiB unallocated = ptn_size - fs_size = 409600 - 407128 = 2472 = 1.21 MiB + (Threshold %age for 200 MiB partition is approximately 4.675%) +threshold = ptn_size * pct = 19150 = 9.35 MiB + + (Unallocated is below threshold so is included in used figure) +disp_used = used + unallocated = 320 + 2472 = 2792 = 1.36 MiB +disp_unused = unused = 406808 = 198.64 MiB + Figures displayed in the Information dialog: Size: 200.00 MiB -Used: 160.00 KiB ( 0% ) -Unused: 198.64 MiB ( 99% ) -Unallocated: 1.21 MiB ( 1% ) +Used: 1.36 MiB ( 1% ) +Unused: 198.64 KiB ( 99% ) diff --git a/include/Partition.h b/include/Partition.h index 374e73f3..6c663ff6 100644 --- a/include/Partition.h +++ b/include/Partition.h @@ -73,8 +73,11 @@ public: bool busy ) ; void set_sector_usage( Sector sectors_fs_size, Sector sectors_fs_unused ) ; - bool significant_unallocated_space() const ; + bool sector_usage_known() const ; Sector estimated_min_size() const ; + Sector get_sectors_used() const ; + Sector get_sectors_unused() const ; + Sector get_sectors_unallocated() const ; void Set_Unallocated( const Glib::ustring & device_path, Sector sector_start, @@ -116,6 +119,7 @@ public: Sector sectors_used; Sector sectors_unused; Sector sectors_unallocated; //Difference between the size of the partition and the file system + Sector significant_threshold; //Threshold from intrinsic to significant unallocated sectors Gdk::Color color; bool inside_extended; bool busy; @@ -131,7 +135,7 @@ public: private: void sort_paths_and_remove_duplicates() ; - Sector get_significant_unallocated_sectors() const ; + Sector calc_significant_unallocated_sectors() const ; static bool compare_paths( const Glib::ustring & A, const Glib::ustring & B ) ; diff --git a/src/Dialog_Partition_Info.cc b/src/Dialog_Partition_Info.cc index fdd9a74f..5d4b8a87 100644 --- a/src/Dialog_Partition_Info.cc +++ b/src/Dialog_Partition_Info.cc @@ -136,10 +136,10 @@ void Dialog_Partition_Info::init_drawingarea() unused = 0 ; unallocated = 400 - BORDER *2 ; } - else if ( partition .sectors_used >= 0 && partition .sectors_unused >= 0 ) + else if ( partition .sector_usage_known() ) { - used = Utils::round( ( 400 - BORDER *2 ) / ( dlength / partition .sectors_used ) ) ; - unused = Utils::round( ( 400 - BORDER *2 ) / ( dlength / partition .sectors_unused ) ) ; + used = Utils::round( ( 400 - BORDER *2 ) / ( dlength / partition .get_sectors_used() ) ) ; + unused = Utils::round( ( 400 - BORDER *2 ) / ( dlength / partition .get_sectors_unused() ) ) ; unallocated = 400 - BORDER *2 - used - unused ; } else @@ -202,11 +202,14 @@ void Dialog_Partition_Info::Display_Info() top++, bottom++, Gtk::FILL ) ; - if ( partition.sectors_used != -1 ) + if ( partition .sector_usage_known() ) { + Sector used = partition .get_sectors_used() ; + Sector unused = partition .get_sectors_unused() ; + Sector unallocated = partition .get_sectors_unallocated() ; //calculate relative diskusage - int percent_unused = Utils::round( partition .sectors_unused * 100.0 / ptn_sectors ) ; - int percent_unallocated = Utils::round( partition .sectors_unallocated * 100.0 / ptn_sectors ) ; + int percent_unused = Utils::round( unused * 100.0 / ptn_sectors ) ; + int percent_unallocated = Utils::round( unallocated * 100.0 / ptn_sectors ) ; int percent_used = 100 - percent_unallocated - percent_unused ; //Used @@ -214,7 +217,7 @@ void Dialog_Partition_Info::Display_Info() 0, 1, top, bottom, Gtk::FILL ) ; - table ->attach( * Utils::mk_label( Utils::format_size( partition .sectors_used, partition .sector_size ), true, Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false, true ), + table ->attach( * Utils::mk_label( Utils::format_size( used, partition .sector_size ), true, Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false, true ), 1, 2, top, bottom, Gtk::FILL ) ; @@ -228,7 +231,7 @@ void Dialog_Partition_Info::Display_Info() 0, 1, top, bottom, Gtk::FILL ) ; - table ->attach( * Utils::mk_label( Utils::format_size( partition .sectors_unused, partition .sector_size ), true, Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false, true ), + table ->attach( * Utils::mk_label( Utils::format_size( unused, partition .sector_size ), true, Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false, true ), 1, 2, top, bottom, Gtk::FILL ) ; @@ -238,13 +241,13 @@ void Dialog_Partition_Info::Display_Info() Gtk::FILL ) ; //unallocated - if ( partition .sectors_unallocated > 0 ) + if ( unallocated > 0 ) { table ->attach( * Utils::mk_label( "" + Glib::ustring( _("Unallocated:") ) + "" ), 0, 1, top, bottom, Gtk::FILL ) ; - table ->attach( * Utils::mk_label( Utils::format_size( partition .sectors_unallocated, partition .sector_size ), true, Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false, true ), + table ->attach( * Utils::mk_label( Utils::format_size( unallocated, partition .sector_size ), true, Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false, true ), 1, 2, top, bottom, Gtk::FILL ) ; diff --git a/src/Dialog_Partition_Resize_Move.cc b/src/Dialog_Partition_Resize_Move.cc index 85596a64..b88c53ee 100644 --- a/src/Dialog_Partition_Resize_Move.cc +++ b/src/Dialog_Partition_Resize_Move.cc @@ -63,7 +63,7 @@ void Dialog_Partition_Resize_Move::Set_Data( const Partition & selected_partitio void Dialog_Partition_Resize_Move::Resize_Move_Normal( const std::vector & partitions ) { //little bit of paranoia ;) - if ( selected_partition .sectors_used == -1 && + if ( ! selected_partition .sector_usage_known() && selected_partition .status != STAT_NEW && selected_partition .filesystem != FS_LINUX_SWAP ) fs .shrink = GParted::FS::NONE ; diff --git a/src/DrawingAreaVisualDisk.cc b/src/DrawingAreaVisualDisk.cc index 9d45fb66..6f58b057 100644 --- a/src/DrawingAreaVisualDisk.cc +++ b/src/DrawingAreaVisualDisk.cc @@ -108,20 +108,21 @@ void DrawingAreaVisualDisk::set_static_data( const std::vector & part { //Use sum_sectors as the denominator to calculate fraction_used and // fraction_unallocated in case it doesn't equal partition_length. - Sector sum_sectors = partitions[ t ] .sectors_used - + partitions[ t ] .sectors_unused - + partitions[ t ] .sectors_unallocated ; - if ( partitions[ t ] .sectors_unallocated > 0 ) + Sector used = partitions[ t ] .get_sectors_used() ; + Sector unused = partitions[ t ] .get_sectors_unused() ; + Sector unallocated = partitions[ t ] .get_sectors_unallocated() ; + Sector sum_sectors = used + unused + unallocated ; + if ( unallocated > 0 ) visual_partitions .back() .fraction_unallocated = - partitions[ t ] .sectors_unallocated / static_cast( sum_sectors ) ; + unallocated / static_cast( sum_sectors ) ; else visual_partitions .back() .fraction_unallocated = 0.0 ; //Calculate fraction used from free space so any hidden overhead is counted as used - if ( partitions[ t ] .sectors_unused >= 0 ) + if ( unused >= 0 ) visual_partitions .back() .fraction_used = 1.0 - visual_partitions .back() .fraction_unallocated - - partitions[ t ] .sectors_unused / static_cast( sum_sectors ) ; + - unused / static_cast( sum_sectors ) ; } visual_partitions .back() .color = partitions[ t ] .color; diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc index a6bc845d..b5b74234 100644 --- a/src/GParted_Core.cc +++ b/src/GParted_Core.cc @@ -604,6 +604,11 @@ bool GParted_Core::snap_to_alignment( const Device & device, Partition & partiti return false ; } + //FIXME: I think that this if condition should be impossible because Partition::set_sector_usage(), + // and ::set_used() and ::Set_Unused() before that, don't allow setting file usage figures to be + // larger than the partition size. A btrfs file system spanning muiltiple partitions will have + // usage figures larger than any single partition but the figures will won't be set because of + // the above reasoning. Confirm condition is impossible and consider removing this code. if ( partition .get_sector_length() < partition .sectors_used ) { error = String::ucompose( @@ -1522,7 +1527,8 @@ void GParted_Core::set_used_sectors( std::vector & partitions ) } } - if ( partitions[ t ] .sectors_used == -1 ) + Sector unallocated ; + if ( ! partitions[ t ] .sector_usage_known() ) { temp = _("Unable to read the contents of this file system!") ; temp += "\n" ; @@ -1540,11 +1546,11 @@ void GParted_Core::set_used_sectors( std::vector & partitions ) } partitions[ t ] .messages .push_back( temp ) ; } - else if ( partitions[ t ] .significant_unallocated_space() ) + else if ( ( unallocated = partitions[ t ] .get_sectors_unallocated() ) > 0 ) { /* TO TRANSLATORS: looks like 1.28GiB of unallocated space within the partition. */ temp = String::ucompose( _("%1 of unallocated space within the partition."), - Utils::format_size( partitions[ t ] .sectors_unallocated, partitions[ t ] .sector_size ) ) ; + Utils::format_size( unallocated, partitions[ t ] .sector_size ) ) ; FS fs = get_fs( partitions[ t ] .filesystem ) ; if ( fs .check != GParted::FS::NONE && fs .grow != GParted::FS::NONE ) diff --git a/src/Partition.cc b/src/Partition.cc index d37d6f58..faf648ca 100644 --- a/src/Partition.cc +++ b/src/Partition.cc @@ -45,6 +45,7 @@ void Partition::Reset() uuid .clear() ; partition_number = sector_start = sector_end = sectors_used = sectors_unused = -1; sectors_unallocated = 0 ; + significant_threshold = 1 ; free_space_before = -1 ; sector_size = 0 ; color .set( "black" ) ; @@ -90,9 +91,10 @@ void Partition::set_sector_usage( Sector sectors_fs_size, Sector sectors_fs_unus && 0 <= sectors_fs_unused && sectors_fs_unused <= sectors_fs_size ) { - sectors_used = sectors_fs_size - sectors_fs_unused ; - sectors_unused = sectors_fs_unused ; - sectors_unallocated = length - sectors_fs_size ; + sectors_used = sectors_fs_size - sectors_fs_unused ; + sectors_unused = sectors_fs_unused ; + sectors_unallocated = length - sectors_fs_size ; + significant_threshold = calc_significant_unallocated_sectors() ; } else if ( sectors_fs_size == -1 ) { @@ -106,15 +108,14 @@ void Partition::set_sector_usage( Sector sectors_fs_size, Sector sectors_fs_unus sectors_used = -1 ; sectors_unused = -1 ; } - sectors_unallocated = 0 ; + sectors_unallocated = 0 ; + significant_threshold = 1 ; } } -bool Partition::significant_unallocated_space() const +bool Partition::sector_usage_known() const { - if ( get_sector_length() >= 0 && sectors_unallocated > 0 ) - return sectors_unallocated >= get_significant_unallocated_sectors() ; - return false ; + return sectors_used >= 0 && sectors_unused >= 0 ; } Sector Partition::estimated_min_size() const @@ -122,11 +123,45 @@ Sector Partition::estimated_min_size() const //Add unallocated sectors up to the significant threshold, to // account for any intrinsic unallocated sectors in the // file systems minimum partition size. - if ( sectors_used > 0 ) - return sectors_used + std::min( sectors_unallocated, get_significant_unallocated_sectors() ) ; + if ( sectors_used >= 0 ) + return sectors_used + std::min( sectors_unallocated, significant_threshold ) ; return -1 ; } +//Return user displayable used sectors. +// Only add unallocated sectors up to the significant threshold to +// account for any intrinsic unallocated sectors in the file system. +// Above the threshold just return the used sectors figure. +Sector Partition::get_sectors_used() const +{ + if ( sectors_used >= 0 ) + { + if ( sectors_unallocated < significant_threshold ) + return sectors_used + sectors_unallocated ; + else + return sectors_used ; + } + return -1 ; +} + +//Return user displayable unused sectors. +Sector Partition::get_sectors_unused() const +{ + return sectors_unused ; +} + +//Return user displayable unallocated sectors. +// Return zero below the significant unallocated sectors threshold, as +// the figure has been added to the displayable used sectors. Above the +// threshold just return the unallocated sectors figure. +Sector Partition::get_sectors_unallocated() const +{ + if ( sectors_unallocated < significant_threshold ) + return 0 ; + else + return sectors_unallocated ; +} + void Partition::Set_Unallocated( const Glib::ustring & device_path, Sector sector_start, Sector sector_end, @@ -297,19 +332,21 @@ bool Partition::compare_paths( const Glib::ustring & A, const Glib::ustring & B // 5% , ptn size <= 100 MiB // linear scaling from 5% down to 2%, 100 MiB < ptn size <= 1 GiB // 2% , 1 GiB < ptn size -Sector Partition::get_significant_unallocated_sectors() const +Sector Partition::calc_significant_unallocated_sectors() const { const double HIGHER_UNALLOCATED_FRACTION = 0.05 ; const double LOWER_UNALLOCATED_FRACTION = 0.02 ; Sector length = get_sector_length() ; Byte_Value byte_len = length * sector_size ; + Sector significant ; + if ( byte_len <= 0 ) { - return 0 ; + significant = 1; } else if ( byte_len <= 100 * MEBIBYTE ) { - return Utils::round( length * HIGHER_UNALLOCATED_FRACTION ) ; + significant = Utils::round( length * HIGHER_UNALLOCATED_FRACTION ) ; } else if ( byte_len <= 1 * GIBIBYTE ) { @@ -317,12 +354,15 @@ Sector Partition::get_significant_unallocated_sectors() const ( byte_len - 100 * MEBIBYTE ) * ( HIGHER_UNALLOCATED_FRACTION - LOWER_UNALLOCATED_FRACTION ) / ( 1 * GIBIBYTE - 100 * MEBIBYTE ) + LOWER_UNALLOCATED_FRACTION ; - return Utils::round( length * fraction ) ; + significant = Utils::round( length * fraction ) ; } else { - return Utils::round( length * LOWER_UNALLOCATED_FRACTION ) ; + significant = Utils::round( length * LOWER_UNALLOCATED_FRACTION ) ; } + if ( significant <= 1 ) + significant = 1; + return significant ; } Partition::~Partition() diff --git a/src/TreeView_Detail.cc b/src/TreeView_Detail.cc index 8ca97359..a47bc7bf 100644 --- a/src/TreeView_Detail.cc +++ b/src/TreeView_Detail.cc @@ -190,12 +190,14 @@ void TreeView_Detail::create_row( const Gtk::TreeRow & treerow, const Partition treerow[ treeview_detail_columns .size ] = Utils::format_size( partition .get_sector_length(), partition .sector_size ) ; //used + Sector used = partition .get_sectors_used() ; treerow[ treeview_detail_columns .used ] = - partition .sectors_used == -1 ? "---" : Utils::format_size( partition .sectors_used, partition .sector_size ) ; + used == -1 ? "---" : Utils::format_size( used, partition .sector_size ) ; //unused + Sector unused = partition .get_sectors_unused() ; treerow[ treeview_detail_columns .unused ] = - partition .sectors_unused == -1 ? "---" : Utils::format_size( partition .sectors_unused, partition .sector_size ) ; + unused == -1 ? "---" : Utils::format_size( unused, partition .sector_size ) ; //flags treerow[ treeview_detail_columns .flags ] = diff --git a/src/Win_GParted.cc b/src/Win_GParted.cc index 8c3be42a..d339e96c 100644 --- a/src/Win_GParted.cc +++ b/src/Win_GParted.cc @@ -969,7 +969,7 @@ void Win_GParted::set_valid_operations() { Byte_Value required_size ; if ( copied_partition .filesystem == GParted::FS_XFS ) - required_size = copied_partition .sectors_used * copied_partition .sector_size; + required_size = copied_partition .estimated_min_size() * copied_partition .sector_size; else required_size = copied_partition .get_byte_length() ;