[gparted] Pre-populate BlockSpecial cache while reading /proc/partitions (#767842)



commit 571304d2c662f8c35e9529b71ae48ffe263c038f
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Tue Jul 12 15:04:15 2016 +0100

    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 71f3357..b05f4da 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 ed6ff71..2481e02 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 ade2ab4..38d4d9c 100644
--- a/src/GParted_Core.cc
+++ b/src/GParted_Core.cc
@@ -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
                                                // 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 153c006..fd16fb6 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 <glibmm/ustring.h>
 #include <vector>
 #include <fstream>
+#include <stdio.h>
 
 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]+)$") ;


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