[gparted] Use newer btrfs multi-tool control command first



commit a580abbc30e88cb1895af342d43dcbb98183a9d5
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Fri Nov 11 20:50:53 2011 +0000

    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.

 src/btrfs.cc |  135 +++++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 100 insertions(+), 35 deletions(-)
---
diff --git a/src/btrfs.cc b/src/btrfs.cc
index 41d38bf..7af0b5e 100644
--- a/src/btrfs.cc
+++ b/src/btrfs.cc
@@ -22,41 +22,68 @@
 namespace GParted
 {
 
+bool btrfs_found = false ;
+
 FS btrfs::get_filesystem_support()
 {
 	FS fs ;
 	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() )
 		fs .create = GParted::FS::EXTERNAL ;
 
 	if ( ! Glib::find_program_in_path( "btrfsck" ) .empty() )
 		fs .check = GParted::FS::EXTERNAL ;
 
-	//resizing of btrfs requires btrfsctl, mount, and umount
-	if (    ! Glib::find_program_in_path( "btrfsctl" ) .empty()
-	     && ! Glib::find_program_in_path( "mount" ) .empty()
-	     && ! Glib::find_program_in_path( "umount" ) .empty()
-	     && fs .check
-	   )
+	btrfs_found = ( ! Glib::find_program_in_path( "btrfs" ) .empty() ) ;
+	if ( btrfs_found )
 	{
-		fs .grow = FS::EXTERNAL ;
-		if ( fs .read ) //needed to determine a minimum file system size.
-			fs .shrink = FS::EXTERNAL ;
-	}
+		//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 ;
+		}
 
-	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;
 	}
+	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()
+		     && ! 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 ;
+		}
+	}
 
 	if ( fs .check )
 	{
@@ -81,7 +108,12 @@ bool btrfs::check_repair( const Partition & partition, OperationDetail & operati
 
 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;
 		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 ) ) ;
 	char dtemplate[] = "/tmp/gparted-XXXXXXXX" ;
 	Glib::ustring dname =  mkdtemp( dtemplate ) ;
+	Glib::ustring str_size ;
 	if( dname .empty() )
 	{
 		//Failed to create temporary directory
@@ -167,20 +200,36 @@ bool btrfs::resize( const Partition & partition_new, OperationDetail & operation
 	if ( exit_status )
 	{
 		//Build resize command
-		str_temp = "btrfsctl" ;
 		if ( ! fill_partition )
-		{
-			str_temp += " -r " + Utils::num_to_str( floor( Utils::sector_to_unit(
-						partition_new .get_sector_length(), partition_new .sector_size, UNIT_KIB ) ) ) + "K" ;
-		}
+			str_size = Utils::num_to_str( floor( Utils::sector_to_unit(
+					partition_new .get_sector_length(), partition_new .sector_size, UNIT_KIB ) ) ) + "K" ;
 		else
-			str_temp += " -r max" ;
-		str_temp += " " + dname ;
+			str_size = "max" ;
+
+		if ( btrfs_found )
+			str_temp = "btrfs filesystem resize " + str_size + " " + dname ;
+		else
+			str_temp = "btrfsctl -r " + str_size + " " + dname ;
 
 		//Execute the command
 		exit_status = execute_command( str_temp, operationdetail ) ;
-		//Sometimes btrfsctl returns an exit status of 256 on successful resize.
-		exit_status = ( exit_status == 0 || exit_status == 256 ) ;
+		//Resizing a btrfs file system for a second time to the
+		//  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
 		str_temp = "umount -v " + dname ;
@@ -196,17 +245,33 @@ bool btrfs::resize( const Partition & partition_new, OperationDetail & operation
 
 void btrfs::read_label( Partition & partition )
 {
-	if ( ! Utils::execute_command( "btrfs-show " + partition .get_path(), output, error, true ) )
+	if ( btrfs_found )
 	{
-		Glib::ustring label = Utils::regexp_label( output, "^Label: (.*)  uuid:" ) ;
-		//Btrfs-show reports "none" when there is no label, but
-		//  this is indistinguishable from the label actually
-		//  being "none".  Assume no label case.
-		if ( label != "none" )
-			partition .label = label ;
+		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:" ) ;
+			//Btrfs-show reports "none" when there is no label, but
+			//  this is indistinguishable from the label actually
+			//  being "none".  Assume no label case.
+			if ( label != "none" )
+				partition .label = label ;
+		}
+	}
+	if ( exit_status )
+	{
 		if ( ! output .empty() )
 			partition .messages .push_back( output ) ;
 



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