Detect busy status of Linux Software RAID members (#709640)

Read the contents of /proc/mdstat file to determine if a device is a
member of of an active RAID array.

    $ cat /proc/mdstat
    Personalities : [raid1]
    md1 : active raid1 sda1[2] sdb1[3]
          524224 blocks super 1.0 [2/2] [UU]

    md2 : active raid1 sdb2[2] sda2[3](F)
          5238720 blocks super 1.1 [2/1] [U_]

    md3 : active raid1 sdb3[1]
          10477440 blocks super 1.1 [2/1] [_U]
          bitmap: 1/1 pages [4KB], 65536KB chunk

    md4 : inactive sda4[0](S)
          1048564 blocks super 1.2

    unused devices: <none>

There are 5 example Linux Software RAID arrays, md1 to md5.  All are
RAID1 mirrors with 2 members, in various states.

    Array  Members     Status
    md1    sda1, sdb2  Fully operational.
    md2    sda2, sdb2  Member sda2 marked as faulty.  (Device sda2 is
                       still in use).
    md3    sda3, sdb3  Member sda3 has been removed.  (Device sda3 is
                       not in use).
    md4    sda4, sdb4  Incremental start of member sda4 only.  (Neither
                       member devices is in use).
    md5    sda5, sdb5  Array stopped.  (Neither member device is in
                       use).

Also disable "Unmount" in the partition menu for active RAID array
members.

Bug #709640 - Linux Swap Suspend and Software RAID partitions not
              recognised
This commit is contained in:
Mike Fleetwood 2013-10-07 23:37:31 +01:00 committed by Curtis Gedak
parent fac3f5b865
commit d2e1130ad2
4 changed files with 39 additions and 3 deletions

View File

@ -168,6 +168,7 @@ 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

@ -1051,8 +1051,9 @@ void GParted_Core::set_device_partitions( Device & device, PedDevice* lp_device,
}
else
#endif
partition_is_busy = ped_partition_is_busy( lp_partition ) ||
( filesystem == GParted::FS_LVM2_PV && lvm2_pv_info .has_active_lvs( partition_path ) ) ;
partition_is_busy = ped_partition_is_busy( lp_partition )
|| ( filesystem == FS_LVM2_PV && lvm2_pv_info .has_active_lvs( partition_path ) )
|| ( filesystem == FS_LINUX_SWRAID && Utils::swraid_member_is_active( partition_path ) ) ;
partition_temp .Set( device .get_path(),
partition_path,

View File

@ -324,6 +324,39 @@ 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 ;

View File

@ -967,10 +967,11 @@ void Win_GParted::set_valid_operations()
: CTEXT_ACTIVATE_FILESYSTEM )
) ;
//Only permit mount/unmount, swapon/swapoff, ... if action is available
//Only permit mount/unmount, swapon/swapoff, activate/deactivate if action is available
if ( selected_partition .status == GParted::STAT_REAL
&& selected_partition .type != GParted::TYPE_EXTENDED
&& selected_partition .filesystem != GParted::FS_LVM2_PV
&& selected_partition .filesystem != FS_LINUX_SWRAID
&& ( selected_partition .busy
|| selected_partition .get_mountpoints() .size() /* Have mount point(s) */
|| selected_partition .filesystem == GParted::FS_LINUX_SWAP