From a4f761e290a32b7dcb43bd4cf3b9da232b9157e5 Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Wed, 23 Jul 2014 11:26:11 +0100 Subject: [PATCH] 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 --- src/btrfs.cc | 46 ++++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/src/btrfs.cc b/src/btrfs.cc index 7df2a2a8..ba27f9ce 100644 --- a/src/btrfs.cc +++ b/src/btrfs.cc @@ -463,36 +463,35 @@ const BTRFS_Device & btrfs::get_cache_entry( const Glib::ustring & path ) if ( bd_iter != btrfs_device_cache .end() ) return bd_iter ->second ; - int exit_status ; Glib::ustring output, error ; std::vector devid_list ; std::vector path_list ; 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 - exit_status = Utils::execute_command( "btrfs-show " + path, output, error, true ) ; - if ( ! exit_status ) + Utils::execute_command( "btrfs-show " + path, output, error, true ) ; + //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: - // 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 ) + int devid = -1 ; + sscanf( output .substr( index ) .c_str(), "devid %d", &devid ) ; + Glib::ustring devid_path = Utils::regexp_label( output .substr( index ), + "devid .* path (/dev/[[:graph:]]+)" ) ; + if ( devid > -1 && ! devid_path .empty() ) { - int devid = -1 ; - sscanf( output .substr( index ) .c_str(), "devid %d", &devid ) ; - 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" + devid_list .push_back( devid ) ; + path_list .push_back( devid_path ) ; } + offset = index + 5 ; //Next find starts immediately after current "devid" } //Add cache entries for all found devices 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() ) return bd_iter ->second ; - //If "btrfs filesystem show" / "btrfs-show" commands not found, returned non-zero - // exit status or failed to parse information return an "unknown" record + //If for any reason we fail to parse the information return an "unknown" record static BTRFS_Device btrfs_dev = { -1, } ; return btrfs_dev ; }