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
This commit is contained in:
Mike Fleetwood 2015-10-21 13:54:58 +01:00 committed by Curtis Gedak
parent 5f02bcf463
commit 0ce9857380
5 changed files with 87 additions and 43 deletions

View File

@ -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

View File

@ -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 ) ;

View File

@ -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 ;

View File

@ -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] )
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

View File

@ -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 ;