[gparted/ataraid: 13/17] Detect busy status of dmraid started ATARAID members (#75)



commit caec22871e2fa869db85831c625f30d70738906e
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Sun Nov 24 13:15:22 2019 +0000

    Detect busy status of dmraid started ATARAID members (#75)
    
    Again this is to stop GParted allowing overwrite operations being
    performed on an ATARAID member while the array is actively using the
    member.  This time for dmraid started arrays using the kernel DM (Device
    Mapper) driver.
    
    The DMRaid module already uses dmraid to report active array names:
    
        # dmraid -sa -c
        isw_ecccdhhiga_MyArray
    
    To find active members in this array, (1) use udev to lookup the kernel
    device name:
    
        # udevadm info --query=name /dev/mapper/isw_ecccdhhiga_MyArray
        dm-0
    
    (2) list the member names exposed by the kernel DM driver through the
    /sys file system.
    
        # ls /sys/block/dm-0/slaves
        sdc  sdd
        # ls -l /sys/block/dm-0/slaves
        lrwxrwxrwx 1 root root 0 Nov 24 09:52 sdc -> 
../../../../pci0000:00/0000:00:0d.0/ata3/host2/target2:0:0/2:0:0:0/block/sdc
        lrwxrwxrwx 1 root root 0 Nov 24 09:52 sdc -> 
../../../../pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdd
    
    Closes #75 - Errors with GPT on RAID 0 ATARAID array

 include/DMRaid.h    |  8 ++++++
 src/DMRaid.cc       | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/GParted_Core.cc |  5 +++-
 3 files changed, 91 insertions(+), 2 deletions(-)
---
diff --git a/include/DMRaid.h b/include/DMRaid.h
index 9d1a0945..a53e1c70 100644
--- a/include/DMRaid.h
+++ b/include/DMRaid.h
@@ -27,11 +27,14 @@
 #define GPARTED_DMRAID_H
 
 #include "Utils.h"
+#include "BlockSpecial.h"
 #include "Partition.h"
 #include "OperationDetail.h"
 
+#include <glibmm/ustring.h>
 #include <vector>
 
+
 namespace GParted
 {
 
@@ -56,17 +59,22 @@ public:
        bool delete_dev_map_entry( const Partition & partition, OperationDetail & operationdetail ) ;
        bool purge_dev_map_entries( const Glib::ustring & dev_path ) ;
        bool update_dev_map_entry( const Partition & partition, OperationDetail & operationdetail ) ;
+       bool is_member_active(const Glib::ustring& member_path);
+
 private:
        void load_dmraid_cache() ;
        void set_commands_found() ;
        void get_dmraid_dir_entries( const Glib::ustring & dev_path, std::vector<Glib::ustring> & dir_list ) ;
        void get_affected_dev_map_entries( const Partition & partition, std::vector<Glib::ustring> & 
affected_entries ) ;
        void get_partition_dev_map_entries( const Partition & partition, std::vector<Glib::ustring> & 
partition_entries ) ;
+       static std::vector<Glib::ustring> lookup_dmraid_members(const Glib::ustring& array);
+
        static bool dmraid_cache_initialized ;
        static bool dmraid_found ;
        static bool dmsetup_found ;
        static bool udevadm_found ;
        static std::vector<Glib::ustring> dmraid_devices ;
+       static std::vector<BlockSpecial>  dmraid_member_cache;
 };
 
 }//GParted
diff --git a/src/DMRaid.cc b/src/DMRaid.cc
index ef0a8967..c6c6bda4 100644
--- a/src/DMRaid.cc
+++ b/src/DMRaid.cc
@@ -15,7 +15,9 @@
  */
 
 #include "DMRaid.h"
+#include "BlockSpecial.h"
 #include "Partition.h"
+#include "Utils.h"
 
 #include <limits.h>
 #include <stdlib.h>            //atoi function
@@ -28,12 +30,26 @@
 namespace GParted
 {
 
+// Data model:
+// dmraid_cache_initialized - Has the cache been loaded?
+// dmraid_found             - Is the "dmraid" command available?
+// dmsetup_found            - Is the "dmsetup" command available?
+// udevadm_found            - Is the "udevadm" command available?
+// dmraid_devices           - Vector of active array names.
+//                            E.g.
+//                            ["isw_ecccdhhiga_MyArray"]
+// dmraid_member_cache      - Vector of members of active DMRaid arrays.
+//                            E.g.
+//                            [BlockSpecial("/dev/sdc"), BlockSpecial("/dev/sdd")]
+
 //Initialize static data elements
 bool DMRaid::dmraid_cache_initialized = false ;
 bool DMRaid::dmraid_found  = false ;
 bool DMRaid::dmsetup_found = false ;
 bool DMRaid::udevadm_found  = false ;
 std::vector<Glib::ustring> DMRaid::dmraid_devices ;
+std::vector<BlockSpecial>  DMRaid::dmraid_member_cache;
+
 
 DMRaid::DMRaid()
 {
@@ -67,10 +83,11 @@ DMRaid::~DMRaid()
 
 void DMRaid::load_dmraid_cache()
 {
-       //Load data into dmraid structures
        Glib::ustring output, error ;
        dmraid_devices .clear() ;
+       dmraid_member_cache.clear();
 
+       // Load active DMRaid array names.
        if ( dmraid_found )
        {
                if ( ! Utils::execute_command( "dmraid -sa -c", output, error, true ) )
@@ -79,8 +96,17 @@ void DMRaid::load_dmraid_cache()
                                Utils::tokenize( output, dmraid_devices, "\n" ) ;
                }
        }
+
+       // Load members of active DMRaid arrays.
+       for (unsigned int i = 0; i < dmraid_devices.size(); i++)
+       {
+               std::vector<Glib::ustring> members = lookup_dmraid_members(DEV_MAPPER_PATH + 
dmraid_devices[i]);
+               for (unsigned int j = 0; j < members.size(); j++)
+                       dmraid_member_cache.push_back(BlockSpecial(members[j]));
+       }
 }
 
+
 void DMRaid::set_commands_found()
 {
        //Set status of commands found 
@@ -492,4 +518,56 @@ bool DMRaid::update_dev_map_entry( const Partition & partition, OperationDetail
        return exit_status ;
 }
 
+
+// Return whether the named device (e.g. "/dev/sdc") is a member of an active DMRaid array
+// or not.
+bool DMRaid::is_member_active(const Glib::ustring& member_path)
+{
+       BlockSpecial bs = BlockSpecial(member_path);
+       for (unsigned int i = 0; i < dmraid_member_cache.size(); i++)
+       {
+               if (bs == dmraid_member_cache[i])
+                       return true;
+       }
+
+       return false;
+}
+
+
+// Return vector of member devices of an active DMRaid array.
+// E.g. lookup_dmraid_members("/dev/mapper/isw_ecccdhhiga_MyArray") -> ["/dev/sdc", "/dev/sdd"]
+std::vector<Glib::ustring> DMRaid::lookup_dmraid_members(const Glib::ustring& array)
+{
+       // Method:
+       // (1) Query udev for the kernel device name;
+       // (2) List member names from the directory /sys/block/${name}/slaves.
+
+       std::vector<Glib::ustring> members;
+       if (! udevadm_found)
+               return members;  // Empty vector
+
+       Glib::ustring output;
+       Glib::ustring error;
+       Utils::execute_command("udevadm info --query=name " + Glib::shell_quote(array),
+                              output, error, true);
+
+       // Strip terminating new line from output.
+       size_t len = output.length();
+       if (len > 0 && output[len-1] == '\n')
+               output.resize(len-1);
+
+       if (output.empty())
+               return members;  // Empty vector
+
+       Glib::ustring filename;
+       Glib::Dir dir("/sys/block/" + output + "/slaves");
+       while ((filename = dir.read_name()) != "")
+       {
+               members.push_back("/dev/" + filename);
+       }
+
+       return members;
+}
+
+
 }//GParted
diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc
index 50c6a354..40057d36 100644
--- a/src/GParted_Core.cc
+++ b/src/GParted_Core.cc
@@ -1525,13 +1525,16 @@ bool GParted_Core::is_busy( FSType fstype, const Glib::ustring & path )
        }
        else
        {
+               DMRaid dmraid;
+
                //Still search GParted internal mounted partitions map in case an
                //  unknown file system is mounted
                busy = Mount_Info::is_dev_mounted( path );
 
                // Custom checks for recognised but other not-supported file system types.
                busy |= (fstype == FS_LINUX_SWRAID && SWRaid_Info::is_member_active(path));
-               busy |= (fstype == FS_ATARAID      && SWRaid_Info::is_member_active(path));
+               busy |= (fstype == FS_ATARAID      && (SWRaid_Info::is_member_active(path) ||
+                                                      dmraid.is_member_active(path)         ));
        }
 
        return busy ;


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