[gparted] Add BlockSpecial into mount_info and fstab_info (#767842)



commit a800ca8b68d60251101ee27e569dfa2a97b67886
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Sat Jun 25 08:29:17 2016 +0100

    Add BlockSpecial into mount_info and fstab_info (#767842)
    
    On some distributions having btrfs on top of LUKS encrypted partitions,
    adding a second device and removing the first device used to mount the
    file system causes GParted to no longer be able to report the file
    system as busy or the mount points themselves.
    
    For example, on CentOS 7, create a single btrfs file system and mount
    it.  The provided /dev/mapper/sdb1_crypt name is reported, via
    /proc/mounts, as the mounting device:
        # cryptsetup luksFormat --force-password /dev/sdb1
        # cryptsetup luksOpen /dev/sdb1 sdb1_crypt
        # mkfs.btrfs -L encrypted-btrfs /dev/mapper/sdb1_crypt
        # mount /dev/mapper/sdb1_crypt /mnt/1
    
        # ls -l /dev/mapper
        total 0
        lrwxrwxrwx. 1 root root       7 Jul  2 14:15 centos-root -> ../dm-1
        lrwxrwxrwx. 1 root root       7 Jul  2 14:15 centos-swap -> ../dm-0
        crw-------. 1 root root 10, 236 Jul  2 14:15 control
        lrwxrwxrwx. 1 root root       7 Jul  2 15:14 sdb1_crypt -> ../dm-2
        # fgrep btrfs /proc/mounts
        /dev/mapper/sdb1_crypt /mnt/1 btrfs rw,seclabel,relatime,space_cache 0 0
    
    Add a second device to the btrfs file system:
        # cryptsetup luksFormat --force-password /dev/sdb2
        # cryptsetup luksOpen /dev/sdb2 sdb2_crypt
        # btrfs device add /dev/mapper/sdb2_crypt /mnt/1
    
        # ls -l /dev/mapper
        ...
        lrwxrwxrwx. 1 root root       7 Jul  2 15:12 sdb2_crypt -> ../dm-3
        # btrfs filesystem show /dev/mapper/sdb1_crypt
        Label: 'encrypted-btrfs'  uuid: 45d7b1ef-820c-4ef8-8abd-c70d928afb49
                Total devices 2 FS bytes used 32.00KiB
                devid    1 size 1022.00MiB used 12.00MiB path /dev/mapper/sdb1_crypt
                devid    2 size 1022.00MiB used 0.00B path /dev/mapper/sdb2_crypt
    
    Remove the first mounting device from the btrfs file system.  Now the
    non-canonical name /dev/dm-3 is reported, via /proc/mounts, as the
    mounting device:
        # btrfs device delete /dev/mapper/sdb1_crypt /mnt/1
    
        # btrfs filesystem show /dev/mapper/sdb2_crypt
        Label: 'encrypted-btrfs'  uuid: 45d7b1ef-820c-4ef8-8abd-c70d928afb49
                Total devices 1 FS bytes used 96.00KiB
                devid    2 size 1022.00MiB used 144.00MiB path /dev/mapper/sdb2_crypt
        # fgrep btrfs /proc/mounts
        /dev/dm-3 /mnt/1 btrfs rw,seclabel,relatime,space_cache 0 0
        # ls -l /dev/dm-3
        brw-rw----. 1 root disk 253, 3 Jul  2 15:12 /dev/dm-3
    
    GParted loads the mount_info mapping from /proc/mounts and with it the
    /dev/dm-3 name.  When GParted is determining if the encrypted btrfs file
    system is mounted or getting the mount points it is using the
    /dev/mapper/sdb2_crypt name.  Therefore no information is found and the
    file system is incorrectly reported as unmounted.
    
    Fix by changing mount_info and fstab_info to use BlockSpecial objects
    instead of strings so that matching is performed by major, minor device
    numbers rather than by string compare.  Note that as BlockSpecial
    objects are used as the key of std::map [1] mappings operator<() [2]
    needs to be provided to order the key values.
    
    [1] std::map
        http://www.cplusplus.com/reference/map/map/
    [2] std::map::key_comp
        http://www.cplusplus.com/reference/map/map/key_comp/
    
    Bug 767842 - File system usage missing when tools report alternate block
                 device names

 include/BlockSpecial.h |    1 +
 include/GParted_Core.h |   14 +++++----
 src/BlockSpecial.cc    |   10 +++++++
 src/GParted_Core.cc    |   67 +++++++++++++++++++++++-------------------------
 4 files changed, 51 insertions(+), 41 deletions(-)
---
diff --git a/include/BlockSpecial.h b/include/BlockSpecial.h
index 376e3b0..3635a27 100644
--- a/include/BlockSpecial.h
+++ b/include/BlockSpecial.h
@@ -48,6 +48,7 @@ public:
 //     "2. If a binary operator treats both operands equally (it leaves them unchanged),
 //     implement this operator as a non-member function."
 bool operator==( const BlockSpecial & lhs, const BlockSpecial & rhs );
+bool operator<( const BlockSpecial & lhs, const BlockSpecial & rhs );
 
 }//GParted
 
diff --git a/include/GParted_Core.h b/include/GParted_Core.h
index fec90bd..61a65bd 100644
--- a/include/GParted_Core.h
+++ b/include/GParted_Core.h
@@ -18,6 +18,7 @@
 #ifndef GPARTED_GPARTED_CORE_H
 #define GPARTED_GPARTED_CORE_H
 
+#include "../include/BlockSpecial.h"
 #include "../include/FileSystem.h"
 #include "../include/Operation.h"
 #include "../include/Partition.h"
@@ -75,19 +76,20 @@ public:
                                        Byte_Value sector_size,
                                        bool inside_extended );
 
+       typedef std::map<BlockSpecial, std::vector<Glib::ustring> > MountMapping;
+
 private:
        //detectionstuff..
        static void init_maps() ;
        void set_thread_status_message( Glib::ustring msg ) ;
-       static void read_mountpoints_from_file( const Glib::ustring & filename,
-                                               std::map< Glib::ustring, std::vector<Glib::ustring> > & map ) 
;
-       static void add_node_and_mountpoint( std::map< Glib::ustring, std::vector<Glib::ustring> > & map,
+       static void read_mountpoints_from_file( const Glib::ustring & filename, MountMapping & map );
+       static void add_node_and_mountpoint( MountMapping & map,
                                             Glib::ustring & node,
                                             Glib::ustring & mountpoint ) ;
        static void read_mountpoints_from_file_swaps( const Glib::ustring & filename,
-                                                     std::map< Glib::ustring, std::vector<Glib::ustring> > & 
map ) ;
-       static bool have_rootfs_dev( std::map< Glib::ustring, std::vector<Glib::ustring> > & map ) ;
-       static void read_mountpoints_from_mount_command( std::map< Glib::ustring, std::vector<Glib::ustring> 
& map ) ;
+                                                     MountMapping & map );
+       static bool have_rootfs_dev( MountMapping & map );
+       static void read_mountpoints_from_mount_command( MountMapping & map );
        static Glib::ustring get_partition_path( PedPartition * lp_partition );
        void set_device_serial_number( Device & device );
        void set_device_partitions( Device & device, PedDevice* lp_device, PedDisk* lp_disk ) ;
diff --git a/src/BlockSpecial.cc b/src/BlockSpecial.cc
index 1941b3f..ebd29f0 100644
--- a/src/BlockSpecial.cc
+++ b/src/BlockSpecial.cc
@@ -52,4 +52,14 @@ bool operator==( const BlockSpecial & lhs, const BlockSpecial & rhs )
                return lhs.m_name == rhs.m_name;
 }
 
+bool operator<( const BlockSpecial & lhs, const BlockSpecial & rhs )
+{
+       if ( lhs.m_major == 0 && rhs.m_major == 0 && lhs.m_minor == 0 && rhs.m_minor == 0 )
+               // Two non-block special files are ordered by name.
+               return lhs.m_name < rhs.m_name;
+       else
+               // Block special files are ordered by major, minor device numbers.
+               return lhs.m_major < rhs.m_major || ( lhs.m_major == rhs.m_major && lhs.m_minor < rhs.m_minor 
);
+}
+
 } //GParted
diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc
index 8fbdf8c..ed035f2 100644
--- a/src/GParted_Core.cc
+++ b/src/GParted_Core.cc
@@ -17,6 +17,7 @@
  
 #include "../include/Win_GParted.h"
 #include "../include/GParted_Core.h"
+#include "../include/BlockSpecial.h"
 #include "../include/DMRaid.h"
 #include "../include/FS_Info.h"
 #include "../include/LVM2_PV_Info.h"
@@ -69,17 +70,18 @@ namespace GParted
 const std::time_t SETTLE_DEVICE_PROBE_MAX_WAIT_SECONDS = 1;
 const std::time_t SETTLE_DEVICE_APPLY_MAX_WAIT_SECONDS = 10;
 
-//mount_info - Associative array mapping currently mounted devices to
-//  one or more mount points.  E.g.
-//      mount_info["/dev/sda1"] -> ["/boot"]
-//      mount_info["/dev/sda2"] -> [""]  (swap)
-//      mount_info["/dev/sda3"] -> ["/"]
-//fstab_info - Associative array mapping configured devices to one or
-//  more mount points read from /etc/fstab.  E.g.
-//      fstab_info["/dev/sda1"] -> ["/boot"]
-//      fstab_info["/dev/sda3"] -> ["/"]
-static std::map< Glib::ustring, std::vector<Glib::ustring> > mount_info ;
-static std::map< Glib::ustring, std::vector<Glib::ustring> > fstab_info ;
+// Associative array mapping currently mounted devices to one or more mount points.
+// E.g.
+//     mount_info[BlockSpecial("/dev/sda1")] -> ["/boot"]
+//     mount_info[BlockSpecial("/dev/sda2")] -> [""]  (swap)
+//     mount_info[BlockSpecial("/dev/sda3")] -> ["/"]
+static GParted_Core::MountMapping mount_info;
+
+// Associative array mapping configured devices to one or more mount points read from
+// /etc/fstab.  E.g.
+//     fstab_info[BlockSpecial("/dev/sda1")] -> ["/boot"]
+//     fstab_info[BlockSpecial("/dev/sda3")] -> ["/"]
+static GParted_Core::MountMapping fstab_info;
 
 static bool udevadm_found = false;
 static bool udevsettle_found = false;
@@ -968,13 +970,13 @@ std::vector<Glib::ustring> GParted_Core::get_disklabeltypes()
 //Return whether the device path, such as /dev/sda3, is mounted or not
 bool GParted_Core::is_dev_mounted( const Glib::ustring & path )
 {
-       std::map< Glib::ustring, std::vector<Glib::ustring> >::iterator iter_mp = mount_info .find( path ) ;
+       MountMapping::iterator iter_mp = mount_info.find( BlockSpecial( path ) );
        return iter_mp != mount_info .end() ;
 }
 
 std::vector<Glib::ustring> GParted_Core::get_all_mountpoints() 
 {
-       std::map< Glib::ustring, std::vector<Glib::ustring> >::iterator iter_mp ;
+       MountMapping::iterator iter_mp;
        std::vector<Glib::ustring> mountpoints ;
 
        for ( iter_mp = mount_info .begin() ; iter_mp != mount_info .end() ; ++iter_mp )
@@ -1042,7 +1044,7 @@ void GParted_Core::init_maps()
        read_mountpoints_from_file( "/etc/fstab", fstab_info ) ;
        
        //sort the mount points and remove duplicates.. (no need to do this for fstab_info)
-       std::map< Glib::ustring, std::vector<Glib::ustring> >::iterator iter_mp ;
+       MountMapping::iterator iter_mp;
        for ( iter_mp = mount_info .begin() ; iter_mp != mount_info .end() ; ++iter_mp )
        {
                std::sort( iter_mp ->second .begin(), iter_mp ->second .end() ) ;
@@ -1053,9 +1055,7 @@ void GParted_Core::init_maps()
        }
 }
 
-void GParted_Core::read_mountpoints_from_file(
-       const Glib::ustring & filename,
-       std::map< Glib::ustring, std::vector<Glib::ustring> > & map )
+void GParted_Core::read_mountpoints_from_file( const Glib::ustring & filename, MountMapping & map )
 {
        FS_Info fs_info ;  //Use cache of file system information
 
@@ -1086,15 +1086,14 @@ void GParted_Core::read_mountpoints_from_file(
        endmntent( fp ) ;
 }
 
-void GParted_Core::add_node_and_mountpoint(
-       std::map< Glib::ustring, std::vector<Glib::ustring> > & map,
-       Glib::ustring & node,
-       Glib::ustring & mountpoint )
+void GParted_Core::add_node_and_mountpoint( MountMapping & map,
+                                            Glib::ustring & node,
+                                            Glib::ustring & mountpoint )
 {
        //Only add node path(s) if mount point exists
        if ( file_test( mountpoint, Glib::FILE_TEST_EXISTS ) )
        {
-               map[ node ] .push_back( mountpoint ) ;
+               map[BlockSpecial( node )].push_back( mountpoint );
 
                //If node is a symbolic link (e.g., /dev/root)
                //  then find real path and add entry too
@@ -1103,16 +1102,15 @@ void GParted_Core::add_node_and_mountpoint(
                        char * rpath = realpath( node.c_str(), NULL );
                        if ( rpath != NULL )
                        {
-                               map[rpath].push_back( mountpoint );
+                               map[BlockSpecial( rpath )].push_back( mountpoint );
                                free( rpath );
                        }
                }
        }
 }
 
-void GParted_Core::read_mountpoints_from_file_swaps(
-       const Glib::ustring & filename,
-       std::map< Glib::ustring, std::vector<Glib::ustring> > & map )
+void GParted_Core::read_mountpoints_from_file_swaps( const Glib::ustring & filename,
+                                                     MountMapping & map )
 {
        std::string line ;
        std::string node ;
@@ -1124,7 +1122,7 @@ void GParted_Core::read_mountpoints_from_file_swaps(
                {
                        node = Utils::regexp_label( line, "^(/[^ ]+)" ) ;
                        if ( node .size() > 0 )
-                               map[ node ] .push_back( "" /* no mountpoint for swap */ ) ;
+                               map[BlockSpecial( node )].push_back( "" /* no mountpoint for swap */ );
                }
                file .close() ;
        }
@@ -1132,22 +1130,21 @@ void GParted_Core::read_mountpoints_from_file_swaps(
 
 //Return true only if the map contains a device name for the / (root) file system other
 //  than 'rootfs' and '/dev/root'
-bool GParted_Core::have_rootfs_dev( std::map< Glib::ustring, std::vector<Glib::ustring> > & map )
+bool GParted_Core::have_rootfs_dev( MountMapping & map )
 {
-       std::map< Glib::ustring, std::vector<Glib::ustring> >::iterator iter_mp ;
+       MountMapping::iterator iter_mp;
        for ( iter_mp = mount_info .begin() ; iter_mp != mount_info .end() ; iter_mp ++ )
        {
                if ( ! iter_mp ->second .empty() && iter_mp ->second[ 0 ] == "/" )
                {
-                       if ( iter_mp ->first != "rootfs" && iter_mp ->first != "/dev/root" )
+                       if ( iter_mp->first.m_name != "rootfs" && iter_mp->first.m_name != "/dev/root" )
                                return true ;
                }
        }
        return false ;
 }
 
-void GParted_Core::read_mountpoints_from_mount_command(
-       std::map< Glib::ustring, std::vector<Glib::ustring> > & map )
+void GParted_Core::read_mountpoints_from_mount_command( MountMapping & map )
 {
        Glib::ustring output ;
        Glib::ustring error ;
@@ -1870,8 +1867,8 @@ void GParted_Core::set_mountpoints( Partition & partition )
                }
                else  // Not busy file system
                {
-                       std::map< Glib::ustring, std::vector<Glib::ustring> >::iterator iter_mp;
-                       iter_mp = fstab_info.find( partition.get_path() );
+                       MountMapping::iterator iter_mp;
+                       iter_mp = fstab_info.find( BlockSpecial( partition.get_path() ) );
                        if ( iter_mp != fstab_info.end() )
                                partition.add_mountpoints( iter_mp->second );
                }
@@ -1886,7 +1883,7 @@ bool GParted_Core::set_mountpoints_helper( Partition & partition, const Glib::us
        else
                search_path = path ;
 
-       std::map< Glib::ustring, std::vector<Glib::ustring> >::iterator iter_mp = mount_info .find( 
search_path ) ;
+       MountMapping::iterator iter_mp = mount_info.find( BlockSpecial( search_path ) );
        if ( iter_mp != mount_info .end() )
        {
                partition .add_mountpoints( iter_mp ->second ) ;


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