[gparted] Add devid to the cache of btrfs device information (#723842)



commit 287526681d37e88a83c96c06513eda2db852c163
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Thu Apr 10 22:28:40 2014 +0100

    Add devid to the cache of btrfs device information (#723842)
    
    Bug #723842 - GParted resizes the wrong filesystem (does not pass the
                  devid to btrfs filesystem resize)

 include/btrfs.h |    9 +++++++-
 src/btrfs.cc    |   59 +++++++++++++++++++++++++++++++++++-------------------
 2 files changed, 46 insertions(+), 22 deletions(-)
---
diff --git a/include/btrfs.h b/include/btrfs.h
index 693c686..f732096 100644
--- a/include/btrfs.h
+++ b/include/btrfs.h
@@ -23,6 +23,13 @@
 
 namespace GParted
 {
+
+struct BTRFS_Device
+{
+       int                             devid ;
+       std::vector<Glib::ustring>      members ;
+} ;
+
 class btrfs : public FileSystem
 {
 public:
@@ -40,7 +47,7 @@ public:
        static Glib::ustring get_mount_device( const Glib::ustring & path ) ;
 
 private:
-       static const std::vector<Glib::ustring> get_cache_entry( const Glib::ustring & path ) ;
+       static const BTRFS_Device & get_cache_entry( const Glib::ustring & path ) ;
        static Byte_Value btrfs_size_to_num( Glib::ustring str, Byte_Value ptn_bytes, bool scale_up ) ;
        static gdouble btrfs_size_max_delta( Glib::ustring str ) ;
        static gdouble btrfs_size_to_gdouble( Glib::ustring str ) ;
diff --git a/src/btrfs.cc b/src/btrfs.cc
index 30b668f..52e4480 100644
--- a/src/btrfs.cc
+++ b/src/btrfs.cc
@@ -27,14 +27,14 @@ namespace GParted
 bool btrfs_found = false ;
 bool resize_to_same_size_fails = true ;
 
-//Cache of all devices in each btrfs file system by device
+//Cache of required btrfs file system device information by device
 //  E.g. For a single device btrfs on /dev/sda2 and a three device btrfs
 //       on /dev/sd[bcd]1 the cache would be:
-//  btrfs_device_cache["/dev/sda2"] = ["/dev/sda2"]
-//  btrfs_device_cache["/dev/sdb1"] = ["/dev/sdd1", "/dev/sdc1", "/dev/sdb1"]
-//  btrfs_device_cache["/dev/sdc1"] = ["/dev/sdd1", "/dev/sdc1", "/dev/sdb1"]
-//  btrfs_device_cache["/dev/sdd1"] = ["/dev/sdd1", "/dev/sdc1", "/dev/sdb1"]
-std::map< Glib::ustring, std::vector<Glib::ustring> > btrfs_device_cache ;
+//  btrfs_device_cache["/dev/sda2"] = {devid=1, members=["/dev/sda2"]}
+//  btrfs_device_cache["/dev/sdb1"] = {devid=1, members=["/dev/sdd1", "/dev/sdc1", "/dev/sdb1"]}
+//  btrfs_device_cache["/dev/sdc1"] = {devid=2, members=["/dev/sdd1", "/dev/sdc1", "/dev/sdb1"]}
+//  btrfs_device_cache["/dev/sdd1"] = {devid=3, members=["/dev/sdd1", "/dev/sdc1", "/dev/sdb1"]}
+std::map<Glib::ustring, BTRFS_Device> btrfs_device_cache ;
 
 FS btrfs::get_filesystem_support()
 {
@@ -430,32 +430,33 @@ void btrfs::clear_cache()
 //  Return empty string if not found (not mounted).
 Glib::ustring btrfs::get_mount_device( const Glib::ustring & path )
 {
-       std::vector<Glib::ustring> entry = get_cache_entry( path ) ;
-       for ( unsigned int i = 0 ; i < entry .size() ; i ++ )
-               if ( GParted_Core::is_dev_mounted( entry[ i ] ) )
-                       return entry[ i ] ;
+       BTRFS_Device btrfs_dev = get_cache_entry( path ) ;
+       for ( unsigned int i = 0 ; i < btrfs_dev .members .size() ; i ++ )
+               if ( GParted_Core::is_dev_mounted( btrfs_dev .members[ i ] ) )
+                       return btrfs_dev .members[ i ] ;
        return "" ;
 }
 
 //Private methods
 
 //Return btrfs device cache entry, incrementally loading cache as required
-const std::vector<Glib::ustring> btrfs::get_cache_entry( const Glib::ustring & path )
+const BTRFS_Device & btrfs::get_cache_entry( const Glib::ustring & path )
 {
-       std::vector<Glib::ustring> entry = btrfs_device_cache[ path ] ;
-
-       if ( ! entry .empty() )
-               return entry ;
+       std::map<Glib::ustring, BTRFS_Device>::const_iterator bd_iter = btrfs_device_cache .find( path ) ;
+       if ( bd_iter != btrfs_device_cache .end() )
+               return bd_iter ->second ;
 
        int exit_status ;
        Glib::ustring output, error ;
+       std::vector<int> devid_list ;
+       std::vector<Glib::ustring> path_list ;
        if ( btrfs_found )
                exit_status = 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 )
        {
-               //Extract path for each devid from output like this:
+               //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
@@ -464,19 +465,35 @@ const std::vector<Glib::ustring> btrfs::get_cache_entry( const Glib::ustring & p
                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_path .empty() )
+                       if ( devid > -1 && ! devid_path .empty() )
                        {
-                               entry .push_back( devid_path ) ;
+                               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 < entry .size() ; i ++ )
-               btrfs_device_cache[ entry[ i ] ] = entry ;
-       return entry ;
+       for ( unsigned int i = 0 ; i < devid_list .size() ; i ++ )
+       {
+               BTRFS_Device btrfs_dev ;
+               btrfs_dev .devid = devid_list[ i ] ;
+               btrfs_dev .members = path_list ;
+               btrfs_device_cache[ path_list[ i ] ] = btrfs_dev ;
+       }
+
+       bd_iter = btrfs_device_cache .find( 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
+       static BTRFS_Device btrfs_dev = { -1, } ;
+       return btrfs_dev ;
 }
 
 //Return the value of a btrfs tool formatted size, including reversing


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