Cache looked up major, minor numbers in BlockSpecial class (#767842)

Creation of every BlockSpecial object used to result in a stat() OS
call.  On one of my test VMs debugging with 4 disks and a few partitions
on each, GParted refresh generated 541 calls to stat() in the
BlockSpecial(name) constructor.  However there were only 45 unique
names.  So on average each name was stat()ed approximately 12 times.

Cache the major, minor number associated with each name after starting
with a cleared cache for each GParted refresh.  This reduces these
direct calls to stat() to just the 45 unique names.

Bug 767842 - File system usage missing when tools report alternate block
             device names
This commit is contained in:
Mike Fleetwood 2016-07-12 08:05:53 +01:00 committed by Curtis Gedak
parent ce8fb1dd91
commit 003d6eff94
3 changed files with 42 additions and 0 deletions

View File

@ -41,6 +41,8 @@ public:
Glib::ustring m_name; // E.g. Block special file {"/dev/sda1", 8, 1},
unsigned long m_major; // plain file {"FILENAME", 0, 0} and empty object
unsigned long m_minor; // {"", 0, 0}.
static void clear_cache();
};
// Operator overloading > The Decision between Member and Non-member

View File

@ -20,28 +20,65 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <map>
namespace GParted
{
struct MM_Number
{
unsigned long m_major;
unsigned long m_minor;
};
typedef std::map<Glib::ustring, MM_Number> MMNumberMapping;
// Associative array caching name to major, minor number pairs
// E.g.
// mm_number_cache["/dev/sda"] = {8, 0}
// mm_number_cache["/dev/sda1"] = {8, 1}
// mm_number_cache["proc"] = {0, 0}
// mm_number_cache["sysfs"] = {0, 0}
static MMNumberMapping mm_number_cache;
BlockSpecial::BlockSpecial() : m_name( "" ), m_major( 0UL ), m_minor( 0UL )
{
}
BlockSpecial::BlockSpecial( const Glib::ustring & name ) : m_name( name ), m_major( 0UL ), m_minor( 0UL )
{
MMNumberMapping::const_iterator mm_num_iter = mm_number_cache.find( name );
if ( mm_num_iter != mm_number_cache.end() )
{
// Use already cached major, minor pair
m_major = mm_num_iter->second.m_major;
m_minor = mm_num_iter->second.m_minor;
return;
}
MM_Number pair = {0UL, 0UL};
// Call stat(name, ...) to get the major, minor pair
struct stat sb;
if ( stat( name.c_str(), &sb ) == 0 && S_ISBLK( sb.st_mode ) )
{
m_major = major( sb.st_rdev );
m_minor = minor( sb.st_rdev );
pair.m_major = m_major;
pair.m_minor = m_minor;
}
// Add new cache entry for name to major, minor pair
mm_number_cache[name] = pair;
}
BlockSpecial::~BlockSpecial()
{
}
void BlockSpecial::clear_cache()
{
mm_number_cache.clear();
}
bool operator==( const BlockSpecial & lhs, const BlockSpecial & rhs )
{
if ( lhs.m_major > 0UL && lhs.m_minor > 0UL )

View File

@ -166,6 +166,9 @@ void GParted_Core::set_devices_thread( std::vector<Device> * pdevices )
std::vector<Device> &devices = *pdevices;
devices .clear() ;
Device temp_device ;
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
FS_Info fs_info( true ) ; //Refresh cache of file system information
DMRaid dmraid( true ) ; //Refresh cache of dmraid device information