[gparted] Don't show intrinsic unallocated space (#499202)



commit 7ebedc4bb3b81e85fb4c628a2a05308ada147d68
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Fri Jun 15 13:16:30 2012 +0100

    Don't show intrinsic unallocated space (#499202)
    
    Most file systems report intrinsic unallocated space using the statvfs()
    system call when mounted, but not using their own tools.  They are:
    ext2/3/4, fat16/32, hfs, nilfs2, reiserfs and xfs.  Showing either a
    little or no unallocated space, depending on whether a file system is
    mounted or not, could be confusing to the user.
    
    When all file systems are created filling their partitions the unused
    figure reported by statvfs() and their own tools are the same or very
    close.  Also the used plus unallocated figure from statvfs() agrees with
    the used figure from their own tools.
    
    For all file systems don't display intrinsic unallocated space (that
    below the threshold of 2 to 5%), instead include it as used space.  As
    soon as the amount of unallocated space becomes significant display it
    everywhere and also trigger the warning.
    
    For display purposes always use the new Partition methods:
    get_sectors_used(), get_sectors_unused(), and get_sectors_unallocated().
    When calculating new usage figures during Paste and Resize/Move
    operations directly access sectors_used, sectors_unused and
    sectors_unallocated members.
    
    Bug #499202 - gparted does not see the difference if partition size
                  differs from filesystem size

 HACKING                             |   25 +++++++++---
 include/Partition.h                 |    8 +++-
 src/Dialog_Partition_Info.cc        |   23 ++++++-----
 src/Dialog_Partition_Resize_Move.cc |    2 +-
 src/DrawingAreaVisualDisk.cc        |   15 ++++---
 src/GParted_Core.cc                 |   12 ++++-
 src/Partition.cc                    |   70 +++++++++++++++++++++++++++-------
 src/TreeView_Detail.cc              |    6 ++-
 src/Win_GParted.cc                  |    2 +-
 9 files changed, 115 insertions(+), 48 deletions(-)
---
diff --git a/HACKING b/HACKING
index 3f2d29f..28d5cb4 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 374e73f..6c663ff 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 fdd9a74..5d4b8a8 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( "<b>" + Glib::ustring( _("Unallocated:") ) + "</b>" ),
 					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 85596a6..b88c53e 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<Partition> & 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 9d45fb6..6f58b05 100644
--- a/src/DrawingAreaVisualDisk.cc
+++ b/src/DrawingAreaVisualDisk.cc
@@ -108,20 +108,21 @@ void DrawingAreaVisualDisk::set_static_data( const std::vector<Partition> & 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<double>( sum_sectors ) ;
+					unallocated / static_cast<double>( 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<double>( sum_sectors ) ;
+					    - unused / static_cast<double>( sum_sectors ) ;
 		}
 	
 		visual_partitions .back() .color = partitions[ t ] .color; 
diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc
index a6bc845..b5b7423 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<Partition> & 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<Partition> & 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 d37d6f5..faf648c 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 8ca9735..a47bc7b 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 8c3be42..d339e96 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() ;
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]