Use UUID and label of SWRaid arrays too (#756829)

In cases where blkid wrongly reports a file system instead of an SWRaid
member (sometimes confused by metadata 0.90/1.0 mirror array or old
version not recognising SWRaid members), the UUID and label are
obviously wrong too.  Therefore have to use the UUID and label returned
by the mdadm query command and never anything reported by blkid or any
file system specific command.

Example of blkid reporting the wrong type, UUID and label for /dev/sda1
and the correct values for /dev/sdb1:

    # blkid | egrep 'sd[ab]1'
    /dev/sda1: UUID="10ab5f7d-7d8a-4171-8b6a-5e973b402501" TYPE="ext4" LABEL="chimney-boot"
    /dev/sdb1: UUID="15224a42-c25b-bcd9-15db-60004e5fe53a" UUID_SUB="0a095e45-9360-1b17-0ad1-1fe369e22b98" LABEL="chimney:1" TYPE="linux_raid_member"

    # mdadm -E -s -v
    ARRAY /dev/md/1  level=raid1 metadata=1.0 num-devices=2 UUID=15224a42:c25bbcd9:15db6000:4e5fe53a name=chimney:1
       devices=/dev/sda1,/dev/sdb1
    ...
    ARRAY /dev/md127 level=raid1 num-devices=2 UUID=8dc7483c:d74ee0a8:b6a8dc3c:a57e43f8
       devices=/dev/sdb6,/dev/sda6
    ...

NOTES:
* In mdadm terminology the label is called the array name, hence name=
  parameter for array md/1 in the above output.
* Metadata 0.90 arrays don't support naming, hence the missing name=
  parameter for array md127 in the above output.

Bug 756829 - SWRaid member detection enhancements
This commit is contained in:
Mike Fleetwood 2015-10-23 21:23:29 +01:00 committed by Curtis Gedak
parent 0ce9857380
commit 7255c8af40
3 changed files with 86 additions and 15 deletions

View file

@ -33,6 +33,8 @@ namespace GParted
struct SWRaid_Member
{
Glib::ustring member;
Glib::ustring uuid;
Glib::ustring label;
bool active;
};
@ -42,11 +44,14 @@ public:
static void load_cache();
static bool is_member( const Glib::ustring & member_path );
static bool is_member_active( const Glib::ustring & member_path );
static Glib::ustring get_uuid( const Glib::ustring & member_path );
static Glib::ustring get_label( 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 Glib::ustring mdadm_to_canonical_uuid( const Glib::ustring & mdadm_uuid );
static bool mdadm_found;
static std::vector<SWRaid_Member> swraid_info_cache;

View file

@ -1405,6 +1405,20 @@ void GParted_Core::set_device_one_partition( Device & device, PedDevice * lp_dev
void GParted_Core::set_partition_label_and_uuid( Partition & partition )
{
FS_Info fs_info; // Use cache of file system information
Glib::ustring partition_path = partition.get_path();
// For SWRaid members only get the label and UUID from SWRaid_Info. Never use
// values from FS_Info to avoid showing incorrect information in cases where blkid
// reports the wrong values.
if ( partition.filesystem == FS_LINUX_SWRAID )
{
Glib::ustring label = SWRaid_Info::get_label( partition_path );
if ( ! label.empty() )
partition.set_filesystem_label( label );
partition.uuid = SWRaid_Info::get_uuid( partition_path );
return;
}
// Retrieve file system label. Use file system specific method first in an effort
// to ensure multi-byte character sets are properly displayed.
@ -1412,14 +1426,14 @@ void GParted_Core::set_partition_label_and_uuid( Partition & partition )
if ( ! partition.filesystem_label_known() )
{
bool label_found = false;
Glib::ustring label = fs_info.get_label( partition.get_path(), label_found );
Glib::ustring label = fs_info.get_label( partition_path, label_found );
if ( label_found )
partition.set_filesystem_label( label );
}
// Retrieve file system UUID. Use cached method first in an effort to speed up
// device scanning.
partition.uuid = fs_info.get_uuid( partition.get_path() );
partition.uuid = fs_info.get_uuid( partition_path );
if ( partition.uuid.empty() )
{
read_uuid( partition );

View file

@ -28,11 +28,11 @@ namespace GParted
// mdadm_found - Is the "mdadm" command available?
// swraid_info_cache - Vector of member information in Linux Software RAID arrays.
// E.g.
// //member , active
// [{"/dev/sda1", true },
// {"/dev/sda2", true },
// {"/dev/sda6", false},
// {"/dev/sdb6", false}
// //member , uuid , label , active
// [{"/dev/sda1", "15224a42-c25b-bcd9-15db-60004e5fe53a", "chimney:1", true },
// {"/dev/sda2", "15224a42-c25b-bcd9-15db-60004e5fe53a", "chimney:1", true },
// {"/dev/sda6", "8dc7483c-d74e-e0a8-b6a8-dc3ca57e43f8", "" , false},
// {"/dev/sdb6", "8dc7483c-d74e-e0a8-b6a8-dc3ca57e43f8", "" , false}
// ]
// Initialise static data elements
@ -63,6 +63,24 @@ bool SWRaid_Info::is_member_active( const Glib::ustring & member_path )
return false; // No such member
}
// Return array UUID for the specified member, or "" when failed to parse the UUID or
// there is no such member.
Glib::ustring SWRaid_Info::get_uuid( const Glib::ustring & member_path )
{
const SWRaid_Member & memb = get_cache_entry_by_member( member_path );
return memb.uuid;
}
// Return array label (array name in mdadm terminology) for the specified member, or ""
// when the array has no label or there is no such member.
// (Metadata 0.90 arrays don't have names. Metata 1.x arrays are always named, getting a
// default of hostname ":" array number when not otherwise specified).
Glib::ustring SWRaid_Info::get_label( const Glib::ustring & member_path )
{
const SWRaid_Member & memb = get_cache_entry_by_member( member_path );
return memb.label;
}
// Private methods
void SWRaid_Info::set_command_found()
@ -79,19 +97,20 @@ void SWRaid_Info::load_swraid_info_cache()
if ( ! mdadm_found )
return;
// Load SWRaid members into the cache.
// Load SWRaid members into the cache. Load member device, array UUID and array
// label (array name in mdadm terminology).
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=...
// Extract information from Linux Software RAID arrays only, excluding
// IMSM and DDF arrays. Example output:
// ARRAY metadata=imsm UUID=9a5e3477:e1e668ea:12066a1b:d3708608
// devices=/dev/sdd,/dev/sdc,/dev/md/imsm0
// ARRAY /dev/md/MyRaid container=...
// ARRAY /dev/md/MyRaid container=9a5e3477:e1e668ea:12066a1b:d3708608 member=0 UUID=47518beb:cc6ef9e7:c80cd1c7:5f6ecb28
//
// ARRAY /dev/md/1 level=raid1 metadata=1.0 num-devices=2 UUID=...
// ARRAY /dev/md/1 level=raid1 metadata=1.0 num-devices=2 UUID=15224a42:c25bbcd9:15db6000:4e5fe53a name=chimney:1
// devices=/dev/sda1,/dev/sdb1
// ARRAY /dev/md5 level=raid1 num-devices=2 UUID=...
// ARRAY /dev/md5 level=raid1 num-devices=2 UUID=8dc7483c:d74ee0a8:b6a8dc3c:a57e43f8
// devices=/dev/sda6,/dev/sdb6
std::vector<Glib::ustring> lines;
Utils::split( output, lines, "\n" );
@ -102,6 +121,8 @@ void SWRaid_Info::load_swraid_info_cache()
LINE_TYPE_DEVICES = 2
};
LINE_TYPE line_type = LINE_TYPE_OTHER;
Glib::ustring uuid;
Glib::ustring label;
for ( unsigned int i = 0 ; i < lines.size() ; i ++ )
{
Glib::ustring metadata_type;
@ -116,8 +137,15 @@ void SWRaid_Info::load_swraid_info_cache()
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;
continue;
}
uuid = mdadm_to_canonical_uuid(
Utils::regexp_label( lines[i], "UUID=([[:graph:]]+)" ) );
label = Utils::regexp_label( lines[i], "name=(.*)$" );
}
else if ( line_type == LINE_TYPE_ARRAY &&
lines[i].find( "devices=" ) != Glib::ustring::npos )
@ -131,12 +159,18 @@ void SWRaid_Info::load_swraid_info_cache()
{
SWRaid_Member memb;
memb.member = devices[j];
memb.uuid = uuid;
memb.label = label;
memb.active = false;
swraid_info_cache.push_back( memb );
}
uuid.clear();
label.clear();
}
else
{
line_type = LINE_TYPE_OTHER;
}
}
}
@ -187,8 +221,26 @@ SWRaid_Member & SWRaid_Info::get_cache_entry_by_member( const Glib::ustring & me
if ( member_path == swraid_info_cache[i].member )
return swraid_info_cache[i];
}
static SWRaid_Member memb = {"", false};
static SWRaid_Member memb = {"", "", "", false};
return memb;
}
// Reformat mdadm printed UUID into canonical format. Returns "" if source not correctly
// formatted.
// E.g. "15224a42:c25bbcd9:15db6000:4e5fe53a" -> "15224a42-c25b-bcd9-15db-60004e5fe53a"
Glib::ustring SWRaid_Info::mdadm_to_canonical_uuid( const Glib::ustring & mdadm_uuid )
{
Glib::ustring verified_uuid = Utils::regexp_label( mdadm_uuid,
"^([[:xdigit:]]{8}:[[:xdigit:]]{8}:[[:xdigit:]]{8}:[[:xdigit:]]{8})$" );
if ( verified_uuid.empty() )
return verified_uuid;
Glib::ustring canonical_uuid = verified_uuid.substr( 0, 8) + "-" +
verified_uuid.substr( 9, 4) + "-" +
verified_uuid.substr(13, 4) + "-" +
verified_uuid.substr(18, 4) + "-" +
verified_uuid.substr(22, 4) + verified_uuid.substr(27, 8);
return canonical_uuid;
}
} //GParted