Update parsing of btrfs filesystem show for multi-device membership (#733601)

This patch changes the reading of the btrfs multi-device membership to
resolve issue 1/2 by ignoring the exit status from the 'btrfs filesystem
show' command and relying on parsing the required information to
determine success or failure.

Bug #733601 - Btrfs: Warnings and missing label with btrfs-progs 3.12
              and 3.14
This commit is contained in:
Mike Fleetwood 2014-07-23 11:26:11 +01:00 committed by Curtis Gedak
parent 422829ebff
commit a4f761e290
1 changed files with 22 additions and 24 deletions

View File

@ -463,36 +463,35 @@ const BTRFS_Device & btrfs::get_cache_entry( const Glib::ustring & path )
if ( bd_iter != btrfs_device_cache .end() ) if ( bd_iter != btrfs_device_cache .end() )
return bd_iter ->second ; return bd_iter ->second ;
int exit_status ;
Glib::ustring output, error ; Glib::ustring output, error ;
std::vector<int> devid_list ; std::vector<int> devid_list ;
std::vector<Glib::ustring> path_list ; std::vector<Glib::ustring> path_list ;
if ( btrfs_found ) if ( btrfs_found )
exit_status = Utils::execute_command( "btrfs filesystem show " + path, output, error, true ) ; Utils::execute_command( "btrfs filesystem show " + path, output, error, true ) ;
else else
exit_status = Utils::execute_command( "btrfs-show " + path, output, error, true ) ; Utils::execute_command( "btrfs-show " + path, output, error, true ) ;
if ( ! exit_status ) //In many cases the exit status doesn't reflect valid output or an error condition
// so rely on parsing the output to determine success.
//Extract devid and path for each device from output like this:
// Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50
// Total devices 2 FS bytes used 156.00KB
// devid 2 size 2.00GB used 512.00MB path /dev/sdb2
// devid 1 size 2.00GB used 240.75MB path /dev/sdb1
Glib::ustring::size_type offset = 0 ;
Glib::ustring::size_type index ;
while ( ( index = output .find( "devid ", offset ) ) != Glib::ustring::npos )
{ {
//Extract devid and path for each device from output like this: int devid = -1 ;
// Label: none uuid: 36eb51a2-2927-4c92-820f-b2f0b5cdae50 sscanf( output .substr( index ) .c_str(), "devid %d", &devid ) ;
// Total devices 2 FS bytes used 156.00KB Glib::ustring devid_path = Utils::regexp_label( output .substr( index ),
// devid 2 size 2.00GB used 512.00MB path /dev/sdb2 "devid .* path (/dev/[[:graph:]]+)" ) ;
// devid 1 size 2.00GB used 240.75MB path /dev/sdb1 if ( devid > -1 && ! devid_path .empty() )
Glib::ustring::size_type offset = 0 ;
Glib::ustring::size_type index ;
while ( ( index = output .find( "devid ", offset ) ) != Glib::ustring::npos )
{ {
int devid = -1 ; devid_list .push_back( devid ) ;
sscanf( output .substr( index ) .c_str(), "devid %d", &devid ) ; path_list .push_back( devid_path ) ;
Glib::ustring devid_path = Utils::regexp_label( output .substr( index ),
"devid .* path (/dev/[[:graph:]]+)" ) ;
if ( devid > -1 && ! devid_path .empty() )
{
devid_list .push_back( devid ) ;
path_list .push_back( devid_path ) ;
}
offset = index + 5 ; //Next find starts immediately after current "devid"
} }
offset = index + 5 ; //Next find starts immediately after current "devid"
} }
//Add cache entries for all found devices //Add cache entries for all found devices
for ( unsigned int i = 0 ; i < devid_list .size() ; i ++ ) for ( unsigned int i = 0 ; i < devid_list .size() ; i ++ )
@ -507,8 +506,7 @@ const BTRFS_Device & btrfs::get_cache_entry( const Glib::ustring & path )
if ( bd_iter != btrfs_device_cache .end() ) if ( bd_iter != btrfs_device_cache .end() )
return bd_iter ->second ; return bd_iter ->second ;
//If "btrfs filesystem show" / "btrfs-show" commands not found, returned non-zero //If for any reason we fail to parse the information return an "unknown" record
// exit status or failed to parse information return an "unknown" record
static BTRFS_Device btrfs_dev = { -1, } ; static BTRFS_Device btrfs_dev = { -1, } ;
return btrfs_dev ; return btrfs_dev ;
} }