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
This commit is contained in:
Mike Fleetwood 2016-07-12 15:04:15 +01:00 committed by Curtis Gedak
parent 003d6eff94
commit 571304d2c6
4 changed files with 31 additions and 3 deletions

View File

@ -43,6 +43,8 @@ public:
unsigned long m_minor; // {"", 0, 0}. unsigned long m_minor; // {"", 0, 0}.
static void clear_cache(); 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 // Operator overloading > The Decision between Member and Non-member

View File

@ -79,6 +79,16 @@ void BlockSpecial::clear_cache()
mm_number_cache.clear(); 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 ) bool operator==( const BlockSpecial & lhs, const BlockSpecial & rhs )
{ {
if ( lhs.m_major > 0UL && lhs.m_minor > 0UL ) if ( lhs.m_major > 0UL && lhs.m_minor > 0UL )

View File

@ -169,7 +169,8 @@ void GParted_Core::set_devices_thread( std::vector<Device> * pdevices )
BlockSpecial::clear_cache(); // MUST BE FIRST. Cache of name to major, minor BlockSpecial::clear_cache(); // MUST BE FIRST. Cache of name to major, minor
// numbers incrementally loaded when BlockSpecial // numbers incrementally loaded when BlockSpecial
// objects are created in the following caches. // 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 FS_Info fs_info( true ) ; //Refresh cache of file system information
DMRaid dmraid( true ) ; //Refresh cache of dmraid device information DMRaid dmraid( true ) ; //Refresh cache of dmraid device information
LVM2_PV_Info::clear_cache(); // Cache automatically loaded if and when needed LVM2_PV_Info::clear_cache(); // Cache automatically loaded if and when needed

View File

@ -15,11 +15,13 @@
*/ */
#include "../include/Proc_Partitions_Info.h" #include "../include/Proc_Partitions_Info.h"
#include "../include/BlockSpecial.h"
#include "../include/Utils.h" #include "../include/Utils.h"
#include <glibmm/ustring.h> #include <glibmm/ustring.h>
#include <vector> #include <vector>
#include <fstream> #include <fstream>
#include <stdio.h>
namespace GParted namespace GParted
{ {
@ -73,10 +75,23 @@ void Proc_Partitions_Info::load_proc_partitions_info_cache()
std::string line ; std::string line ;
Glib::ustring device; Glib::ustring device;
// Read whole disk device names, excluding partitions, from
// /proc/partitions and save in this cache.
while ( getline( proc_partitions, line ) ) 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. //Whole disk devices are the ones we want.
//Device names without a trailing digit refer to the whole disk. //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]+)$") ; device = Utils::regexp_label(line, "^[\t ]+[0-9]+[\t ]+[0-9]+[\t ]+[0-9]+[\t ]+([^0-9]+)$") ;