From d2e1130ad22eb3f52db4dc7f645ed4d5bf119d24 Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Mon, 7 Oct 2013 23:37:31 +0100 Subject: [PATCH] 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: 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 --- include/Utils.h | 1 + src/GParted_Core.cc | 5 +++-- src/Utils.cc | 33 +++++++++++++++++++++++++++++++++ src/Win_GParted.cc | 3 ++- 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/include/Utils.h b/include/Utils.h index a7682831..86335f76 100644 --- a/include/Utils.h +++ b/include/Utils.h @@ -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 ) ; diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc index 1959efa2..dc19f5bf 100644 --- a/src/GParted_Core.cc +++ b/src/GParted_Core.cc @@ -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, diff --git a/src/Utils.cc b/src/Utils.cc index 2b305155..2b3ad4a5 100644 --- a/src/Utils.cc +++ b/src/Utils.cc @@ -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 ; diff --git a/src/Win_GParted.cc b/src/Win_GParted.cc index f34fe4fa..87307767 100644 --- a/src/Win_GParted.cc +++ b/src/Win_GParted.cc @@ -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