[gparted] Move busy detection of SWRaid members into the new module (#756829)



commit 0ce985738038b171c7a96594fa99f7b69a4bf6f6
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Wed Oct 21 13:54:58 2015 +0100

    Move busy detection of SWRaid members into the new module (#756829)
    
    Add active attribute to the cache of SWRaid members.  Move parsing of
    /proc/mdstat to discover busy SWRaid members into the cache loading
    code.  New parsing code is a little different because it is finding all
    members of active arrays rather than determining if a specific member is
    active.
    
    Bug 756829 - SWRaid member detection enhancements

 include/SWRaid_Info.h |   10 +++++-
 include/Utils.h       |    1 -
 src/GParted_Core.cc   |    2 +-
 src/SWRaid_Info.cc    |   84 ++++++++++++++++++++++++++++++++++++++++++++----
 src/Utils.cc          |   33 -------------------
 5 files changed, 87 insertions(+), 43 deletions(-)
---
diff --git a/include/SWRaid_Info.h b/include/SWRaid_Info.h
index e59275e..cdd8054 100644
--- a/include/SWRaid_Info.h
+++ b/include/SWRaid_Info.h
@@ -30,18 +30,26 @@
 namespace GParted
 {
 
+struct SWRaid_Member
+{
+       Glib::ustring member;
+       bool          active;
+};
+
 class SWRaid_Info
 {
 public:
        static void load_cache();
        static bool is_member( const Glib::ustring & member_path );
+       static bool is_member_active( const Glib::ustring & member_path );
 
 private:
        static void set_command_found();
        static void load_swraid_info_cache();
+       static SWRaid_Member & get_cache_entry_by_member( const Glib::ustring & member_path );
 
        static bool mdadm_found;
-       static std::vector<Glib::ustring> swraid_info_cache;
+       static std::vector<SWRaid_Member> swraid_info_cache;
 };
 
 }//GParted
diff --git a/include/Utils.h b/include/Utils.h
index 142e0b3..f4809a2 100644
--- a/include/Utils.h
+++ b/include/Utils.h
@@ -181,7 +181,6 @@ public:
        static Glib::ustring get_filesystem_software( FILESYSTEM filesystem ) ;
        static bool kernel_supports_fs( const Glib::ustring & fs ) ;
        static bool kernel_version_at_least( int major_ver, int minor_ver, int patch_ver ) ;
-       static bool swraid_member_is_active( const Glib::ustring & path ) ;
        static Glib::ustring format_size( Sector sectors, Byte_Value sector_size ) ;
        static Glib::ustring format_time( std::time_t seconds ) ;
        static double sector_to_unit( Sector sectors, Byte_Value sector_size, SIZE_UNIT size_unit ) ;
diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc
index 59c7c15..73746a9 100644
--- a/src/GParted_Core.cc
+++ b/src/GParted_Core.cc
@@ -1857,7 +1857,7 @@ bool GParted_Core::is_busy( FILESYSTEM fstype, const Glib::ustring & path )
                busy = is_dev_mounted( path ) ;
 
                //Custom checks for recognised but other not-supported file system types
-               busy |= ( fstype == FS_LINUX_SWRAID && Utils::swraid_member_is_active( path ) ) ;
+               busy |= ( fstype == FS_LINUX_SWRAID && SWRaid_Info::is_member_active( path ) );
        }
 
        return busy ;
diff --git a/src/SWRaid_Info.cc b/src/SWRaid_Info.cc
index 5a36791..4ccc0ea 100644
--- a/src/SWRaid_Info.cc
+++ b/src/SWRaid_Info.cc
@@ -19,19 +19,25 @@
 #include "../include/Utils.h"
 
 #include <glibmm/ustring.h>
+#include <fstream>
 
 namespace GParted
 {
 
 // Data model:
 // mdadm_found       - Is the "mdadm" command available?
-// swraid_info_cache - Vector of /dev entries of members in Linux Software RAID arrays.
+// swraid_info_cache - Vector of member information in Linux Software RAID arrays.
 //                     E.g.
-//                     ["/dev/sda1", "/dev/sda2", ...]
+//                     //member     , active
+//                     [{"/dev/sda1", true },
+//                      {"/dev/sda2", true },
+//                      {"/dev/sda6", false},
+//                      {"/dev/sdb6", false}
+//                     ]
 
 // Initialise static data elements
 bool SWRaid_Info::mdadm_found = false;
-std::vector<Glib::ustring> SWRaid_Info::swraid_info_cache;
+std::vector<SWRaid_Member> SWRaid_Info::swraid_info_cache;
 
 void SWRaid_Info::load_cache()
 {
@@ -41,13 +47,22 @@ void SWRaid_Info::load_cache()
 
 bool SWRaid_Info::is_member( const Glib::ustring & member_path )
 {
-       for ( unsigned int i = 0 ; i < swraid_info_cache.size() ; i ++ )
-               if ( member_path == swraid_info_cache[i] )
-                       return true;
+       const SWRaid_Member & memb = get_cache_entry_by_member( member_path );
+       if ( memb.member == member_path )
+               return true;
 
        return false;
 }
 
+bool SWRaid_Info::is_member_active( const Glib::ustring & member_path )
+{
+       const SWRaid_Member & memb = get_cache_entry_by_member( member_path );
+       if ( memb.member == member_path )
+               return memb.active;
+
+       return false;  // No such member
+}
+
 // Private methods
 
 void SWRaid_Info::set_command_found()
@@ -113,12 +128,67 @@ void SWRaid_Info::load_swraid_info_cache()
                                std::vector<Glib::ustring> devices;
                                Utils::split( devices_str, devices, "," );
                                for ( unsigned int j = 0 ; j < devices.size() ; j ++ )
-                                       swraid_info_cache.push_back( devices[j] );
+                               {
+                                       SWRaid_Member memb;
+                                       memb.member = devices[j];
+                                       memb.active = false;
+                                       swraid_info_cache.push_back( memb );
+                               }
                        }
                        else
                                line_type = LINE_TYPE_OTHER;
                }
        }
+
+       // Set which SWRaid members are active.
+       std::string line;
+       std::ifstream input( "/proc/mdstat" );
+       if ( input )
+       {
+               // Read /proc/mdstat extracting members for active arrays, marking them
+               // active in the cache.  Example fragment of /proc/mdstat:
+               //     md1 : active raid1 sdb1[0] sdb2[1]
+               //           1047552 blocks super 1.2 [2/2] [UU]
+               while ( getline( input, line ) )
+               {
+                       if ( line.find( " : active " ) != std::string::npos )
+                       {
+                               // Found a line for an active array.  Split into space
+                               // separated fields.
+                               std::vector<Glib::ustring> fields;
+                               Utils::tokenize( line, fields, " " );
+                               for ( unsigned int i = 0 ; i < fields.size() ; i ++ )
+                               {
+                                       Glib::ustring::size_type index = fields[i].find( "[" );
+                                       if ( index != Glib::ustring::npos )
+                                       {
+                                               // Field contains an "[" so got a short
+                                               // kernel device name of a member.  Mark
+                                               // as active.
+                                               Glib::ustring mpath = "/dev/" +
+                                                                     fields[i].substr( 0, index );
+                                               SWRaid_Member & memb = get_cache_entry_by_member( mpath );
+                                               if ( memb.member == mpath )
+                                                       memb.active = true;
+                                       }
+                               }
+                       }
+               }
+               input.close();
+       }
+}
+
+// Perform linear search of the cache to find the matching member.
+// Returns found cache entry or not found substitute.
+SWRaid_Member & SWRaid_Info::get_cache_entry_by_member( const Glib::ustring & member_path )
+{
+       for ( unsigned int i = 0 ; i < swraid_info_cache.size() ; i ++ )
+       {
+               if ( member_path == swraid_info_cache[i].member )
+                       return swraid_info_cache[i];
+       }
+       static SWRaid_Member memb = {"", false};
+       return memb;
 }
 
 } //GParted
diff --git a/src/Utils.cc b/src/Utils.cc
index b4f8f71..0d86293 100644
--- a/src/Utils.cc
+++ b/src/Utils.cc
@@ -401,39 +401,6 @@ bool Utils::kernel_version_at_least( int major_ver, int minor_ver, int patch_ver
        return result ;
 }
 
-//Report whether the device is an active member of a Linux Software RAID array
-bool Utils::swraid_member_is_active( const Glib::ustring & path )
-{
-       //Read /proc/mdstat and look for the device name on an active RAID array
-       //  line.   Example line: "md1 : active raid1 sda1[2] sdb1[3]"
-       //                                           ^^^^^^
-       //                                           needle
-       //  Strip "/dev/" prefix and search for device name with surrounding
-       //  " " and "[" to avoid substring matches.
-       if ( path .substr( 0, 5 ) != "/dev/" )
-               return false ;
-
-       bool member_active = false ;
-       Glib::ustring needle = " " + path .substr( 5 ) + "[" ;
-       std::string line ;
-       std::ifstream input( "/proc/mdstat" ) ;
-       if ( input )
-       {
-               while ( getline( input, line ) )
-               {
-                       if (    line .find( " : active " ) != std::string::npos
-                            && line .find( needle ) != std::string::npos       )
-                       {
-                               member_active = true ;
-                               break ;
-                       }
-               }
-               input .close() ;
-       }
-
-       return member_active ;
-}
-
 Glib::ustring Utils::format_size( Sector sectors, Byte_Value sector_size )
 {
        std::stringstream ss ;


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