Record unallocated space within a partition (#499202)

Currently GParted assumes that a file system fills its containing
partition.  This is not always true and can occur when resizing is
performed outside of GParted or a resize operation fails.  GParted
doesn't display any information about unallocated space to the user
and in most cases it is simply included in used space.

Add partition unallocated space accounting.  Make GParted record the
unallocated space for mounted file system and display a warning in the
Partition Information dialog when too much unallocated space is found.

Partition::set_sector_usage( fs_size, fs_unused ), is the new preferred
method of recording file system usage because it allows the unallocated
space in a partition to be calculated.  Partition::Set_Unused() and
Partition::set_used() are now deprecated.

NOTES:

1)  Set the minimum unallocated space to be 5% before considering it
    significant to avoid false reporting.  Worst case found was a
    mounted xfs file system in a 100MiB partition, which reports as
    ~4.7% unallocated according to file system size from statvfs().
    However, it reports as having no unallocated space using xfs
    specific tools.

2)  Unallocated space is only a graphical representation for the user.
    GParted must still use relevant tools to resize file systems before
    shrinking the data and can't assume all unallocated space exists
    after the file system at the end of the partition.

Bug #499202 - gparted does not see the difference if partition size
              differs from filesystem size
This commit is contained in:
Mike Fleetwood 2012-01-10 14:13:41 +00:00 committed by Curtis Gedak
parent 9aac0ae6e7
commit 8093ba2ebd
3 changed files with 80 additions and 6 deletions

View File

@ -51,9 +51,6 @@ enum PartitionAlignment {
// Indicator if start and end sectors must remain unchanged
};
//FIXME: we should make a difference between partition- and file system size.
//especially in the core this can make a difference when giving detailed feedback. With new cairosupport in gtkmm
//it's even possible to make stuff like this visible in the GUI in a nice and clear way
class Partition
{
public:
@ -77,6 +74,8 @@ public:
void Set_Unused( Sector sectors_unused ) ;
void set_used( Sector sectors_used ) ;
void set_sector_usage( Sector sectors_fs_size, Sector sectors_fs_unused ) ;
bool significant_unallocated_space() const ;
void Set_Unallocated( const Glib::ustring & device_path,
Sector sector_start,
@ -117,6 +116,7 @@ public:
Sector sector_end;
Sector sectors_used;
Sector sectors_unused;
Sector sectors_unallocated; //Difference between the size of the partition and the file system
Gdk::Color color;
bool inside_extended;
bool busy;

View File

@ -1486,7 +1486,15 @@ void GParted_Core::set_used_sectors( std::vector<Partition> & partitions )
if ( partitions[ t ] .get_mountpoints() .size() > 0 )
{
if ( statvfs( partitions[ t ] .get_mountpoint() .c_str(), &sfs ) == 0 )
partitions[ t ] .Set_Unused( sfs .f_bfree * (sfs .f_bsize / partitions[ t ] .sector_size) ) ;
{
Sector fs_size = static_cast<Sector>( sfs .f_blocks ) *
sfs .f_frsize /
partitions[ t ] .sector_size ;
Sector fs_free = static_cast<Sector>( sfs .f_bfree ) *
sfs .f_bsize /
partitions[ t ] .sector_size ;
partitions[ t ] .set_sector_usage( fs_size, fs_free ) ;
}
else
partitions[ t ] .messages .push_back(
"statvfs (" +
@ -1532,6 +1540,26 @@ void GParted_Core::set_used_sectors( std::vector<Partition> & partitions )
}
partitions[ t ] .messages .push_back( temp ) ;
}
else if ( partitions[ t ] .significant_unallocated_space() )
{
/* 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 ) ) ;
FS fs = get_fs( partitions[ t ] .filesystem ) ;
if ( fs .check != GParted::FS::NONE
&& fs .grow != GParted::FS::NONE )
{
temp += "\n" ;
/* TO TRANSLATORS: To grow the file system to fill the partition, select the partition and choose the menu item:
* means that the user can perform a check of the partition which will
* also grow the file system to fill the partition.
*/
temp += _("To grow the file system to fill the partition, select the partition and choose the menu item:") ;
temp += "\n" ;
temp += _("Partition --> Check.") ;
}
partitions[ t ] .messages .push_back( temp ) ;
}
}
else if ( partitions[ t ] .type == GParted::TYPE_EXTENDED )
set_used_sectors( partitions[ t ] .logicals ) ;

View File

@ -20,7 +20,9 @@
namespace GParted
{
#define SIGNIFICANT_UNALLOCATED_PERCENTAGE 5.0
Partition::Partition()
{
Reset() ;
@ -44,6 +46,7 @@ void Partition::Reset()
label .clear() ;
uuid .clear() ;
partition_number = sector_start = sector_end = sectors_used = sectors_unused = -1;
sectors_unallocated = 0 ;
free_space_before = -1 ;
sector_size = 0 ;
color .set( "black" ) ;
@ -80,24 +83,67 @@ void Partition::Set( const Glib::ustring & device_path,
this ->color .set( Utils::get_color( filesystem ) );
}
//Deprecated method of setting file system free space, which assumes
// the file system fills the partition.
void Partition::Set_Unused( Sector sectors_unused )
{
if ( sectors_unused <= get_sector_length() )
{
this ->sectors_unused = sectors_unused ;
this ->sectors_used = ( sectors_unused == -1 ) ? -1 : get_sector_length() - sectors_unused ;
this ->sectors_unallocated = 0 ;
}
}
//Deprecated method of setting file system used space, which assumes
// the file system fills the partition.
void Partition::set_used( Sector sectors_used )
{
if ( sectors_used < get_sector_length() )
{
this ->sectors_used = sectors_used ;
this ->sectors_unused = ( sectors_used == -1 ) ? -1 : get_sector_length() - sectors_used ;
this ->sectors_unallocated = 0 ;
}
}
//Preferred method of setting file system size and free space, which also
// calculates unallocated space. Set sectors_fs_size = -1 for unknown.
void Partition::set_sector_usage( Sector sectors_fs_size, Sector sectors_fs_unused )
{
Sector length = get_sector_length() ;
if ( 0 <= sectors_fs_size && sectors_fs_size <= length
&& 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 ;
}
else if ( sectors_fs_size == -1 )
{
if ( 0 <= sectors_fs_unused && sectors_fs_unused <= length )
{
sectors_used = length - sectors_fs_unused ;
sectors_unused = sectors_fs_unused ;
}
else
{
sectors_used = -1 ;
sectors_unused = -1 ;
}
sectors_unallocated = 0 ;
}
}
bool Partition::significant_unallocated_space() const
{
Sector length = get_sector_length() ;
if ( sectors_unallocated > 0 && length > 0 )
return ( sectors_unallocated * 100.0 / length > SIGNIFICANT_UNALLOCATED_PERCENTAGE ) ;
return false ;
}
void Partition::Set_Unallocated( const Glib::ustring & device_path,
Sector sector_start,
Sector sector_end,