diff --git a/include/Makefile.am b/include/Makefile.am index 4b00f1cc..4c308d9d 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -38,6 +38,7 @@ EXTRA_DIST = \ Partition.h \ PipeCapture.h \ Proc_Partitions_Info.h \ + SWRaid_Info.h \ TreeView_Detail.h \ Utils.h \ Win_GParted.h \ diff --git a/include/SWRaid_Info.h b/include/SWRaid_Info.h new file mode 100644 index 00000000..e59275eb --- /dev/null +++ b/include/SWRaid_Info.h @@ -0,0 +1,49 @@ +/* Copyright (C) 2015 Mike Fleetwood + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + + +/* SWRaid_Info + * + * Cache of information about Linux Software RAID arrays so that the + * mdadm command only needs to be executed once per refresh. + */ + +#ifndef GPARTED_SWRAID_INFO_H +#define GPARTED_SWRAID_INFO_H + +#include +#include + +namespace GParted +{ + +class SWRaid_Info +{ +public: + static void load_cache(); + static bool is_member( const Glib::ustring & member_path ); + +private: + static void set_command_found(); + static void load_swraid_info_cache(); + + static bool mdadm_found; + static std::vector swraid_info_cache; +}; + +}//GParted + +#endif /* GPARTED_SWRAID_INFO_H */ diff --git a/po/POTFILES.in b/po/POTFILES.in index 38bf0f68..29741cf1 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -31,6 +31,7 @@ src/OperationLabelFileSystem.cc src/OperationNamePartition.cc src/OperationResizeMove.cc src/Partition.cc +src/SWRaid_Info.cc src/TreeView_Detail.cc src/Utils.cc src/Win_GParted.cc diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc index ee97efab..59c7c157 100644 --- a/src/GParted_Core.cc +++ b/src/GParted_Core.cc @@ -29,6 +29,7 @@ #include "../include/OperationLabelFileSystem.h" #include "../include/OperationNamePartition.h" #include "../include/Proc_Partitions_Info.h" +#include "../include/SWRaid_Info.h" #include "../include/btrfs.h" #include "../include/exfat.h" @@ -165,6 +166,7 @@ void GParted_Core::set_devices_thread( std::vector * pdevices ) DMRaid dmraid( true ) ; //Refresh cache of dmraid device information LVM2_PV_Info::clear_cache(); // Cache automatically loaded if and when needed btrfs::clear_cache(); // Cache incrementally loaded if and when needed + SWRaid_Info::load_cache(); init_maps() ; @@ -1516,10 +1518,21 @@ FILESYSTEM GParted_Core::detect_filesystem( PedDevice * lp_device, PedPartition static Glib::ustring luks_unsupported = _("Linux Unified Key Setup encryption is not yet supported."); if ( lp_partition ) - { + // Will query partition using methods: (Q1) SWRaid, (Q2) libparted, + // (Q3) blkid, (Q4) internal path = get_partition_path( lp_partition ); + else + // Will query whole disk device using methods: (Q1) SWRaid, (Q3) blkid, + // (Q4) internal + path = lp_device->path; - // Standard libparted file system detection + // (Q1) Linux Software RAID member detection + if ( SWRaid_Info::is_member( path ) ) + return FS_LINUX_SWRAID; + + if ( lp_partition ) + { + // (Q2) Standard libparted file system detection if ( lp_partition->fs_type ) { fsname = lp_partition->fs_type->name; @@ -1531,14 +1544,10 @@ FILESYSTEM GParted_Core::detect_filesystem( PedDevice * lp_device, PedPartition fsname = temp; } } - else - { - // Querying whole disk device instead of libparted PedPartition - path = lp_device->path; - } - //FS_Info (blkid) file system detection because current libparted (v2.2) does not - // appear to detect file systems for sector sizes other than 512 bytes. + // (Q3) FS_Info (blkid) file system detection + // Originally just because libparted v2.2 didn't appear to detect file system for + // sector sizes other than 512 bytes. Now to also detect what libparted doesn't. if ( fsname.empty() ) { //TODO: blkid does not return anything for an "extended" partition. Need to handle this somehow @@ -1609,7 +1618,7 @@ FILESYSTEM GParted_Core::detect_filesystem( PedDevice * lp_device, PedPartition return FS_ZFS; } - // Fallback to GParted simple internal file system detection + // (Q4) Fallback to GParted simple internal file system detection FILESYSTEM fstype = detect_filesystem_internal( lp_device, lp_partition ); if ( fstype == FS_LUKS ) messages.push_back( luks_unsupported ); diff --git a/src/Makefile.am b/src/Makefile.am index cd11213d..0d9cd362 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -49,6 +49,7 @@ gpartedbin_SOURCES = \ Partition.cc \ PipeCapture.cc \ Proc_Partitions_Info.cc \ + SWRaid_Info.cc \ TreeView_Detail.cc \ Utils.cc \ Win_GParted.cc \ diff --git a/src/SWRaid_Info.cc b/src/SWRaid_Info.cc new file mode 100644 index 00000000..5a367918 --- /dev/null +++ b/src/SWRaid_Info.cc @@ -0,0 +1,124 @@ +/* Copyright (C) 2015 Mike Fleetwood + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "../include/SWRaid_Info.h" + +#include "../include/Utils.h" + +#include + +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. +// E.g. +// ["/dev/sda1", "/dev/sda2", ...] + +// Initialise static data elements +bool SWRaid_Info::mdadm_found = false; +std::vector SWRaid_Info::swraid_info_cache; + +void SWRaid_Info::load_cache() +{ + set_command_found(); + load_swraid_info_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; + + return false; +} + +// Private methods + +void SWRaid_Info::set_command_found() +{ + mdadm_found = ! Glib::find_program_in_path( "mdadm" ).empty(); +} + +void SWRaid_Info::load_swraid_info_cache() +{ + Glib::ustring output, error; + + swraid_info_cache.clear(); + + if ( ! mdadm_found ) + return; + + // Load SWRaid members into the cache. + Glib::ustring cmd = "mdadm --examine --scan --verbose"; + if ( ! Utils::execute_command( cmd, output, error, true ) ) + { + // Extract member /dev entries from Linux Software RAID arrays only, + // excluding IMSM and DDF arrays. Example output: + // ARRAY metadata=imsm UUID=... + // devices=/dev/sdd,/dev/sdc,/dev/md/imsm0 + // ARRAY /dev/md/MyRaid container=... + // + // ARRAY /dev/md/1 level=raid1 metadata=1.0 num-devices=2 UUID=... + // devices=/dev/sda1,/dev/sdb1 + // ARRAY /dev/md5 level=raid1 num-devices=2 UUID=... + // devices=/dev/sda6,/dev/sdb6 + std::vector lines; + Utils::split( output, lines, "\n" ); + enum LINE_TYPE + { + LINE_TYPE_OTHER = 0, + LINE_TYPE_ARRAY = 1, + LINE_TYPE_DEVICES = 2 + }; + LINE_TYPE line_type = LINE_TYPE_OTHER; + for ( unsigned int i = 0 ; i < lines.size() ; i ++ ) + { + Glib::ustring metadata_type; + if ( lines[i].substr( 0, 6 ) == "ARRAY " ) + { + line_type = LINE_TYPE_ARRAY; + Glib::ustring metadata_type = Utils::regexp_label( lines[i], + "metadata=([[:graph:]]+)" ); + // Mdadm with these flags doesn't seem to print the + // metadata tag for 0.90 version arrays. Accept no tag + // (or empty version) as well as "0.90". + if ( metadata_type != "" && metadata_type != "0.90" && + metadata_type != "1.0" && metadata_type != "1.1" && + metadata_type != "1.2" ) + // Skip mdadm reported non-Linux Software RAID arrays + line_type = LINE_TYPE_OTHER; + } + else if ( line_type == LINE_TYPE_ARRAY && + lines[i].find( "devices=" ) != Glib::ustring::npos ) + { + line_type = LINE_TYPE_DEVICES; + Glib::ustring devices_str = Utils::regexp_label( lines[i], + "devices=([[:graph:]]+)" ); + std::vector devices; + Utils::split( devices_str, devices, "," ); + for ( unsigned int j = 0 ; j < devices.size() ; j ++ ) + swraid_info_cache.push_back( devices[j] ); + } + else + line_type = LINE_TYPE_OTHER; + } + } +} + +} //GParted