Use newer btrfs multi-tool control command first

Btrfsctl and btrfs-show were depreciated in October 2011 and have been
superseeded by the newer btrfs multi-tool control command.  Use btrfs as
first choice, falling back to btrfsctl and btrfs-show when not found.
This commit is contained in:
Mike Fleetwood 2011-11-11 20:50:53 +00:00 committed by Curtis Gedak
parent 7ba1d417c5
commit a580abbc30
1 changed files with 100 additions and 35 deletions

View File

@ -22,24 +22,57 @@
namespace GParted namespace GParted
{ {
bool btrfs_found = false ;
FS btrfs::get_filesystem_support() FS btrfs::get_filesystem_support()
{ {
FS fs ; FS fs ;
fs .filesystem = GParted::FS_BTRFS ; fs .filesystem = GParted::FS_BTRFS ;
if ( ! Glib::find_program_in_path( "btrfs-show" ) .empty() )
{
fs .read = GParted::FS::EXTERNAL ;
fs .read_label = FS::EXTERNAL ;
}
if ( ! Glib::find_program_in_path( "mkfs.btrfs" ) .empty() ) if ( ! Glib::find_program_in_path( "mkfs.btrfs" ) .empty() )
fs .create = GParted::FS::EXTERNAL ; fs .create = GParted::FS::EXTERNAL ;
if ( ! Glib::find_program_in_path( "btrfsck" ) .empty() ) if ( ! Glib::find_program_in_path( "btrfsck" ) .empty() )
fs .check = GParted::FS::EXTERNAL ; fs .check = GParted::FS::EXTERNAL ;
//resizing of btrfs requires btrfsctl, mount, and umount btrfs_found = ( ! Glib::find_program_in_path( "btrfs" ) .empty() ) ;
if ( btrfs_found )
{
//Use newer btrfs multi-tool control command. No need
// to test for filesystem show and filesystem resize
// sub-commands as they were always included.
fs .read = GParted::FS::EXTERNAL ;
fs .read_label = FS::EXTERNAL ;
//Resizing of btrfs requires mount, umount as well as
// btrfs filesystem resize
if ( ! Glib::find_program_in_path( "mount" ) .empty()
&& ! Glib::find_program_in_path( "umount" ) .empty()
&& fs .check
)
{
fs .grow = FS::EXTERNAL ;
if ( fs .read ) //needed to determine a minimum file system size.
fs .shrink = FS::EXTERNAL ;
}
//Test for labelling capability in btrfs command
if ( ! Utils::execute_command( "btrfs filesystem label --help", output, error, true ) )
fs .write_label = FS::EXTERNAL;
}
else
{
//Fall back to using btrfs-show and btrfsctl, which
// were depreciated October 2011
if ( ! Glib::find_program_in_path( "btrfs-show" ) .empty() )
{
fs .read = GParted::FS::EXTERNAL ;
fs .read_label = FS::EXTERNAL ;
}
//Resizing of btrfs requires btrfsctl, mount, and umount
if ( ! Glib::find_program_in_path( "btrfsctl" ) .empty() if ( ! Glib::find_program_in_path( "btrfsctl" ) .empty()
&& ! Glib::find_program_in_path( "mount" ) .empty() && ! Glib::find_program_in_path( "mount" ) .empty()
&& ! Glib::find_program_in_path( "umount" ) .empty() && ! Glib::find_program_in_path( "umount" ) .empty()
@ -50,12 +83,6 @@ FS btrfs::get_filesystem_support()
if ( fs .read ) //needed to determine a minimum file system size. if ( fs .read ) //needed to determine a minimum file system size.
fs .shrink = FS::EXTERNAL ; fs .shrink = FS::EXTERNAL ;
} }
if ( ! Glib::find_program_in_path( "btrfs" ) .empty() )
{
//Test for labelling capability in btrfs command
if ( ! Utils::execute_command( "btrfs filesystem label --help", output, error, true ) )
fs .write_label = FS::EXTERNAL;
} }
if ( fs .check ) if ( fs .check )
@ -81,7 +108,12 @@ bool btrfs::check_repair( const Partition & partition, OperationDetail & operati
void btrfs::set_used_sectors( Partition & partition ) void btrfs::set_used_sectors( Partition & partition )
{ {
if ( ! Utils::execute_command( "btrfs-show " + partition .get_path(), output, error, true ) )
if ( btrfs_found )
exit_status = Utils::execute_command( "btrfs filesystem show " + partition .get_path(), output, error, true ) ;
else
exit_status = Utils::execute_command( "btrfs-show " + partition .get_path(), output, error, true ) ;
if ( ! exit_status )
{ {
Glib::ustring size_label; Glib::ustring size_label;
if ( ((index = output .find( "FS bytes" )) < output .length()) && if ( ((index = output .find( "FS bytes" )) < output .length()) &&
@ -148,6 +180,7 @@ bool btrfs::resize( const Partition & partition_new, OperationDetail & operation
operationdetail .add_child( OperationDetail( str_temp, STATUS_NONE, FONT_BOLD_ITALIC ) ) ; operationdetail .add_child( OperationDetail( str_temp, STATUS_NONE, FONT_BOLD_ITALIC ) ) ;
char dtemplate[] = "/tmp/gparted-XXXXXXXX" ; char dtemplate[] = "/tmp/gparted-XXXXXXXX" ;
Glib::ustring dname = mkdtemp( dtemplate ) ; Glib::ustring dname = mkdtemp( dtemplate ) ;
Glib::ustring str_size ;
if( dname .empty() ) if( dname .empty() )
{ {
//Failed to create temporary directory //Failed to create temporary directory
@ -167,20 +200,36 @@ bool btrfs::resize( const Partition & partition_new, OperationDetail & operation
if ( exit_status ) if ( exit_status )
{ {
//Build resize command //Build resize command
str_temp = "btrfsctl" ;
if ( ! fill_partition ) if ( ! fill_partition )
{ str_size = Utils::num_to_str( floor( Utils::sector_to_unit(
str_temp += " -r " + Utils::num_to_str( floor( Utils::sector_to_unit(
partition_new .get_sector_length(), partition_new .sector_size, UNIT_KIB ) ) ) + "K" ; partition_new .get_sector_length(), partition_new .sector_size, UNIT_KIB ) ) ) + "K" ;
}
else else
str_temp += " -r max" ; str_size = "max" ;
str_temp += " " + dname ;
if ( btrfs_found )
str_temp = "btrfs filesystem resize " + str_size + " " + dname ;
else
str_temp = "btrfsctl -r " + str_size + " " + dname ;
//Execute the command //Execute the command
exit_status = execute_command( str_temp, operationdetail ) ; exit_status = execute_command( str_temp, operationdetail ) ;
//Sometimes btrfsctl returns an exit status of 256 on successful resize. //Resizing a btrfs file system for a second time to the
exit_status = ( exit_status == 0 || exit_status == 256 ) ; // same size results in ioctl() returning -1 EINVAL
// (Invalid argument) from the kernel btrfs code.
// * Btrfs filesystem resize reports this as exit
// status 30:
// ERROR: Unable to resize '/MOUNTPOINT'
// * Btrfsctl -r reports this as exit status 1:
// ioctl:: Invalid argument
// WARNING:
// Ignoring these errors could mask real failures, but
// not ignoring them will cause partition shinks to
// fail on the second "grow file system to fill the
// partition" resize.
exit_status = ( exit_status == 0
|| ( btrfs_found && exit_status == 30<<8 )
|| ( ! btrfs_found && exit_status == 1<<8 )
) ;
//Always unmount the file system //Always unmount the file system
str_temp = "umount -v " + dname ; str_temp = "umount -v " + dname ;
@ -196,7 +245,22 @@ bool btrfs::resize( const Partition & partition_new, OperationDetail & operation
void btrfs::read_label( Partition & partition ) void btrfs::read_label( Partition & partition )
{ {
if ( ! Utils::execute_command( "btrfs-show " + partition .get_path(), output, error, true ) ) if ( btrfs_found )
{
exit_status = Utils::execute_command( "btrfs filesystem show " + partition .get_path(), output, error, true ) ;
if ( ! exit_status )
{
partition .label = Utils::regexp_label( output, "^Label: '(.*)' uuid:" );
//Btrfs filesystem show encloses the label in single
// quotes or reports "none" without single quotes, so
// the cases are disginguishable and this regexp won't
// match the no label case.
}
}
else
{
exit_status = Utils::execute_command( "btrfs-show " + partition .get_path(), output, error, true ) ;
if ( ! exit_status )
{ {
Glib::ustring label = Utils::regexp_label( output, "^Label: (.*) uuid:" ) ; Glib::ustring label = Utils::regexp_label( output, "^Label: (.*) uuid:" ) ;
//Btrfs-show reports "none" when there is no label, but //Btrfs-show reports "none" when there is no label, but
@ -205,7 +269,8 @@ void btrfs::read_label( Partition & partition )
if ( label != "none" ) if ( label != "none" )
partition .label = label ; partition .label = label ;
} }
else }
if ( exit_status )
{ {
if ( ! output .empty() ) if ( ! output .empty() )
partition .messages .push_back( output ) ; partition .messages .push_back( output ) ;