From 571304d2c662f8c35e9529b71ae48ffe263c038f Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Tue, 12 Jul 2016 15:04:15 +0100 Subject: [PATCH] Pre-populate BlockSpecial cache while reading /proc/partitions (#767842) GParted is already reading /proc/partitions to get whole disk device names. The file also contains the major, minor device number of every partition. Use this information to pre-populate the cache in the BlockSpecial class. # cat /proc/partitions major minor #blocks name 8 0 20971520 sda 8 1 512000 sda1 8 2 20458496 sda2 ... 9 3 1047552 md3 259 2 262144 md3p1 259 3 262144 md3p2 ... 253 0 18317312 dm-0 253 1 2097152 dm-1 253 2 8383872 dm-2 253 3 1048576 dm-3 Note that for Device-Mapper names (dm-*) the kernel is not using the canonical user space names (mapper/*). There is no harm in pre-populating the cache with these names and will help if tools report them too. It is just that for DMRaid, LVM and LUKS, GParted uses the canonical /dev/mapper/* names so will still have to call stat() once for each such name. For plain disks (sd*) and Linux Software RAID arrays (md*) the kernel name is the common user space name too, therefore matches what GParted uses and pre-populating does avoid calling stat() at all for these names. Bug 767842 - File system usage missing when tools report alternate block device names --- include/BlockSpecial.h | 2 ++ src/BlockSpecial.cc | 10 ++++++++++ src/GParted_Core.cc | 3 ++- src/Proc_Partitions_Info.cc | 19 +++++++++++++++++-- 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/include/BlockSpecial.h b/include/BlockSpecial.h index 71f3357e..b05f4dac 100644 --- a/include/BlockSpecial.h +++ b/include/BlockSpecial.h @@ -43,6 +43,8 @@ public: unsigned long m_minor; // {"", 0, 0}. static void clear_cache(); + static void register_block_special( const Glib::ustring & name, + unsigned long major, unsigned long minor ); }; // Operator overloading > The Decision between Member and Non-member diff --git a/src/BlockSpecial.cc b/src/BlockSpecial.cc index ed6ff71b..2481e02f 100644 --- a/src/BlockSpecial.cc +++ b/src/BlockSpecial.cc @@ -79,6 +79,16 @@ void BlockSpecial::clear_cache() mm_number_cache.clear(); } +void BlockSpecial::register_block_special( const Glib::ustring & name, + unsigned long major, unsigned long minor ) +{ + MM_Number pair; + pair.m_major = major; + pair.m_minor = minor; + // Add new, or update existing, cache entry for name to major, minor pair + mm_number_cache[name] = pair; +} + bool operator==( const BlockSpecial & lhs, const BlockSpecial & rhs ) { if ( lhs.m_major > 0UL && lhs.m_minor > 0UL ) diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc index ade2ab4e..38d4d9c2 100644 --- a/src/GParted_Core.cc +++ b/src/GParted_Core.cc @@ -169,7 +169,8 @@ void GParted_Core::set_devices_thread( std::vector * pdevices ) BlockSpecial::clear_cache(); // MUST BE FIRST. Cache of name to major, minor // numbers incrementally loaded when BlockSpecial // objects are created in the following caches. - Proc_Partitions_Info pp_info( true ) ; //Refresh cache of proc partition information + Proc_Partitions_Info pp_info( true ) ; // SHOULD BE SECOND. Caches /proc/partitions and + // pre-populates BlockSpecial cache. FS_Info fs_info( true ) ; //Refresh cache of file system information DMRaid dmraid( true ) ; //Refresh cache of dmraid device information LVM2_PV_Info::clear_cache(); // Cache automatically loaded if and when needed diff --git a/src/Proc_Partitions_Info.cc b/src/Proc_Partitions_Info.cc index 153c0061..fd16fb61 100644 --- a/src/Proc_Partitions_Info.cc +++ b/src/Proc_Partitions_Info.cc @@ -15,11 +15,13 @@ */ #include "../include/Proc_Partitions_Info.h" +#include "../include/BlockSpecial.h" #include "../include/Utils.h" #include #include #include +#include namespace GParted { @@ -73,10 +75,23 @@ void Proc_Partitions_Info::load_proc_partitions_info_cache() std::string line ; Glib::ustring device; - // Read whole disk device names, excluding partitions, from - // /proc/partitions and save in this cache. while ( getline( proc_partitions, line ) ) { + // Pre-populate BlockSpecial cache with major, minor numbers of + // all names found from /proc/partitions. + Glib::ustring name = Utils::regexp_label( line, + "^[[:blank:]]*[[:digit:]]+[[:blank:]]+[[:digit:]]+[[:blank:]]+[[:digit:]]+[[:blank:]]+([[:graph:]]+)$" ); + if ( name == "" ) + continue; + unsigned long maj; + unsigned long min; + if ( sscanf( line.c_str(), "%lu %lu", &maj, &min ) != 2 ) + continue; + BlockSpecial::register_block_special( "/dev/" + name, maj, min ); + + // Recognise only whole disk device names, excluding partitions, + // from /proc/partitions and save in this cache. + //Whole disk devices are the ones we want. //Device names without a trailing digit refer to the whole disk. device = Utils::regexp_label(line, "^[\t ]+[0-9]+[\t ]+[0-9]+[\t ]+[0-9]+[\t ]+([^0-9]+)$") ;