[gparted] Pass device and partition names to blkid (#131)



commit 8b35892ea59958aa1eec596a48a36b0fa7950dca
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Sun Jan 24 14:33:04 2021 +0000

    Pass device and partition names to blkid (#131)
    
    A user reported that GParted would hang at "scanning all devices...",
    when a fully working disk was named on the command line, but another
    device on the machine was hung.
    
    This can be replicated like this:
    (on Ubuntu 20.04 LTS for it's NBD support)
    
    1. Export and import NBD:
        # truncate -s 1G /tmp/disk-1G.img
        # nbd-server -C /dev/null 9000 /tmp/disk-1G.img
        # nbd-client localhost 9000 /dev/nbd0
    
    2. Hang the NBD server and therefore /dev/nbd0:
        # killall -STOP nbd-server
    
    3. Run GParted:
        $ gparted /dev/sda
    
    Tracing GParted shows that execution of blkid never returns.
    
        # strace -f -tt -q -bexecve -eexecve ./gpartedbin 2>&1 1> /dev/null | fgrep -v ENOENT
        ...
        [pid 37823] 13:56:24.814139 execve("/usr/sbin/mkudffs", ["mkudffs", "--help"], 0x55e2a3f2d230 /* 20 
vars */ <detached ...>
        [pid 37814] 13:56:24.829246 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=37823, 
si_uid=0, si_status=1, si_utime=0, si_stime=0} ---
        [pid 37825] 13:56:25.376796 execve("/usr/sbin/blkid", ["blkid", "-v"], 0x55e2a3f2d230 /* 20 vars */ 
<detached ...>
        [pid 37824] 13:56:25.380824 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=37825, 
si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
        [pid 37826] 13:56:25.402512 execve("/usr/sbin/blkid", ["blkid"], 0x55e2a3f2d230 /* 20 vars */ 
<detached ...>
    
    Tracking of blkid shows that it hangs on either the open of or first
    read from /dev/nbd0.
    
        # strace blkid
        ...
        lstat("/dev", {st_mode=S_IFDIR|0755, st_size=4560, ...}) = 0
        lstat("/dev/nbd0", {st_mode=S_IFBLK|0660, st_rdev=makedev(0x2b, 0), ...}) = 0
        stat("/dev/nbd0", {st_mode=S_IFBLK|0660, st_rdev=makedev(0x2b, 0), ...}) = 0
        lstat("/dev", {st_mode=S_IFDIR|0755, st_size=4560, ...}) = 0
        lstat("/dev/nbd0", {st_mode=S_IFBLK|0660, st_rdev=makedev(0x2b, 0), ...}) = 0
        access("/dev/nbd0", F_OK)               = 0
        stat("/dev/nbd0", {st_mode=S_IFBLK|0660, st_rdev=makedev(0x2b, 0), ...}) = 0
        openat(AT_FDCWD, "/sys/dev/block/43:0", O_RDONLY|O_CLOEXEC) = 4
        openat(4, "dm/uuid", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
        close(4)                                = 0
        openat(AT_FDCWD, "/dev/nbd0", O_RDONLY|O_CLOEXEC
    
    Clean up:
    
    1. Resume NBD server:
        # killall -CONT nbd-server
    
    2. Delete NBD setup:
        # nbd-client -d /dev/nbd0
        # killall nbd-server
        # rm /tmp/disk-1G.img
    
    Fix this by making GParted specify the whole disk device and partition
    names that it is interested in to blkid, rather than letting blkid scan
    and report all block devices.  Do this both when GParted determines the
    devices for itself and when they are named on the command line.
    
    Also update example blkid command output being parsed and cache value
    with this change to how blkid is executed.
    
    Closes #131 - GParted hangs when non-named device is hung

 include/FS_Info.h   |  6 +++---
 src/FS_Info.cc      | 53 +++++++++++++++++++++++++++++------------------------
 src/GParted_Core.cc | 14 ++------------
 3 files changed, 34 insertions(+), 39 deletions(-)
---
diff --git a/include/FS_Info.h b/include/FS_Info.h
index 000f5af1..1bc56144 100644
--- a/include/FS_Info.h
+++ b/include/FS_Info.h
@@ -38,7 +38,7 @@ struct FS_Entry
 class FS_Info
 {
 public:
-       static void load_cache_for_paths( const std::vector<Glib::ustring> &device_paths );
+       static void load_cache_for_paths(const std::vector<Glib::ustring>& paths);
        static Glib::ustring get_fs_type( const Glib::ustring & path );
        static Glib::ustring get_label( const Glib::ustring & path, bool & found );
        static Glib::ustring get_uuid( const Glib::ustring & path );
@@ -49,9 +49,9 @@ private:
        static void initialize_if_required();
        static void set_commands_found();
        static const FS_Entry & get_cache_entry_by_path( const Glib::ustring & path );
-       static void load_fs_info_cache();
+       static void load_fs_info_cache(const std::vector<Glib::ustring>& paths);
        static void load_fs_info_cache_extra_for_path( const Glib::ustring & path );
-       static bool run_blkid_load_cache( const Glib::ustring & path = "" );
+       static bool run_blkid_load_cache(const std::vector<Glib::ustring>& paths);
        static void update_fs_info_cache_all_labels();
        static bool run_blkid_update_cache_one_label( FS_Entry & fs_entry );
 
diff --git a/src/FS_Info.cc b/src/FS_Info.cc
index 66200773..ecc56696 100644
--- a/src/FS_Info.cc
+++ b/src/FS_Info.cc
@@ -37,33 +37,32 @@ bool FS_Info::need_blkid_vfat_cache_update_workaround = true;
 // Vector of file system information.
 // E.g.
 // (Note BS(path) is a short hand for constructor BlockSpecial(path)).
-//     //path                         , type         , sec_type, uuid                                    , 
have_label, label
-//     [{BS("/dev/sda1")              , "xfs"        , ""      , "f828ee8c-1e16-4ca9-b234-e4949dcd4bd1"  , 
false     , ""          },
-//      {BS("/dev/sda2")              , "LVM2_member", ""      , "p31pR5-qPLm-YICz-O09i-sB4u-mAH2-GVSNWG", 
false     , ""          },
-//      {BS("/dev/block/8:2")         , "LVM2_member", ""      , "p31pR5-qPLm-YICz-O09i-sB4u-mAH2-GVSNWG", 
false     , ""          },
-//      {BS("/dev/mapper/centos-root"), "xfs"        , ""      , "a195605d-22c1-422d-9213-1ed67f1eee46"  , 
false     , ""          },
-//      {BS("/dev/mapper/centos-swap"), "swap"       , ""      , "8d419cb6-c663-4db7-b91c-6bcef8418a4d"  , 
false     , ""          },
-//      {BS("/dev/sdb1")              , "ext3"       , "ext2"  , "f218c3b8-237e-4fbe-92c5-76623bba4062"  , 
true      , "test-ext3" },
-//      {BS("/dev/sdb2")              , "vfat"       , "msdos" , "9F87-1061"                             , 
true      , "TEST-FAT16"},
-//      {BS("/dev/sdb3")              , ""           , ""      , ""                                      , 
false     , ""          }
+//     //path           , type         , sec_type, uuid                                    , have_label, 
label
+//     [{BS("/dev/sda") , ""           , ""      , ""                                      , false     , ""  
        },
+//      {BS("/dev/sda1"), "xfs"        , ""      , "f828ee8c-1e16-4ca9-b234-e4949dcd4bd1"  , false     , ""  
        },
+//      {BS("/dev/sda2"), "LVM2_member", ""      , "p31pR5-qPLm-YICz-O09i-sB4u-mAH2-GVSNWG", false     , ""  
        },
+//      {BS("/dev/sdb") , ""           , ""      , ""                                      , false     , ""  
        },
+//      {BS("/dev/sdb1"), "ext3"       , "ext2"  , "f218c3b8-237e-4fbe-92c5-76623bba4062"  , true      , 
"test-ext3" },
+//      {BS("/dev/sdb2"), "vfat"       , "msdos" , "9F87-1061"                             , true      , 
"TEST-FAT16"},
+//      {BS("/dev/sdb3"), ""           , ""      , ""                                      , false     , ""  
        }
 //     ]
 std::vector<FS_Entry> FS_Info::fs_info_cache;
 
 
-void FS_Info::load_cache_for_paths( const std::vector<Glib::ustring> &device_paths )
+void FS_Info::load_cache_for_paths(const std::vector<Glib::ustring>& paths)
 {
        set_commands_found();
-       load_fs_info_cache();
+       load_fs_info_cache(paths);
        fs_info_cache_initialized = true;
 
        const BlockSpecial empty_bs = BlockSpecial();
-       for ( unsigned int i = 0 ; i < device_paths.size() ; i ++ )
+       for (unsigned int i = 0; i < paths.size(); i++)
        {
-               const FS_Entry & fs_entry = get_cache_entry_by_path( device_paths[i] );
+               const FS_Entry& fs_entry = get_cache_entry_by_path(paths[i]);
                if ( fs_entry.path == empty_bs )
                {
                        // Run "blkid PATH" and load entry into cache for missing entries.
-                       load_fs_info_cache_extra_for_path( device_paths[i] );
+                       load_fs_info_cache_extra_for_path(paths[i]);
                }
        }
 }
@@ -165,7 +164,8 @@ void FS_Info::initialize_if_required()
        if ( ! fs_info_cache_initialized )
        {
                set_commands_found();
-               load_fs_info_cache();
+               std::vector<Glib::ustring> empty;
+               load_fs_info_cache(empty);
                fs_info_cache_initialized = true;
        }
 }
@@ -204,11 +204,12 @@ const FS_Entry & FS_Info::get_cache_entry_by_path( const Glib::ustring & path )
        return not_found;
 }
 
-void FS_Info::load_fs_info_cache()
+
+void FS_Info::load_fs_info_cache(const std::vector<Glib::ustring>& paths)
 {
        fs_info_cache.clear();
        // Run "blkid" and load entries into the cache.
-       run_blkid_load_cache();
+       run_blkid_load_cache(paths);
 
        // (#771244) Ensure the cache has entries for all whole disk devices, even if
        // those entries are blank.  Needed so that an ISO9660 image stored on a whole
@@ -228,7 +229,9 @@ void FS_Info::load_fs_info_cache()
 
 void FS_Info::load_fs_info_cache_extra_for_path( const Glib::ustring & path )
 {
-       bool entry_added = run_blkid_load_cache( path );
+       std::vector<Glib::ustring> one_path;
+       one_path.push_back(path);
+       bool entry_added = run_blkid_load_cache(one_path);
        if ( ! entry_added )
        {
                // Ran "blkid PATH" but didn't find details suitable for loading as a
@@ -238,17 +241,19 @@ void FS_Info::load_fs_info_cache_extra_for_path( const Glib::ustring & path )
        }
 }
 
-bool FS_Info::run_blkid_load_cache( const Glib::ustring & path )
+
+bool FS_Info::run_blkid_load_cache(const std::vector<Glib::ustring>& paths)
 {
        // Parse blkid output line by line extracting mandatory field: path and optional
        // fields: type, sec_type, uuid.  Label is not extracted here because of blkid's
        // default non-reversible encoding of non printable ASCII bytes.
+       // Example command:
+       //     blkid /dev/sda /dev/sda1 /dev/sda2 /dev/sdb /dev/sdb1 /dev/sdb2 /dev/sdb3
        // Example output:
+       //     /dev/sda: PTUUID="5012fb1f" PTTYPE="dos"
        //     /dev/sda1: UUID="f828ee8c-1e16-4ca9-b234-e4949dcd4bd1" TYPE="xfs"
        //     /dev/sda2: UUID="p31pR5-qPLm-YICz-O09i-sB4u-mAH2-GVSNWG" TYPE="LVM2_member"
-       //     /dev/block/8:2: UUID="p31pR5-qPLm-YICz-O09i-sB4u-mAH2-GVSNWG" TYPE="LVM2_member"
-       //     /dev/mapper/centos-root: UUID="a195605d-22c1-422d-9213-1ed67f1eee46" TYPE="xfs"
-       //     /dev/mapper/centos-swap: UUID="8d419cb6-c663-4db7-b91c-6bcef8418a4d" TYPE="swap"
+       //     /dev/sdb: PTUUID="f57595e1-c0ae-40ee-be64-00851b2a9977" PTTYPE="gpt"
        //     /dev/sdb1: LABEL="test-ext3" UUID="f218c3b8-237e-4fbe-92c5-76623bba4062" SEC_TYPE="ext2" 
TYPE="ext3" PARTUUID="71b3e059-30c5-492e-a526-9251dff7bbeb"
        //     /dev/sdb2: SEC_TYPE="msdos" LABEL="TEST-FAT16" UUID="9F87-1061" TYPE="vfat" 
PARTUUID="9d07ad9a-d468-428f-9bfd-724f5efae4fb"
        //     /dev/sdb3: PARTUUID="bb8438e1-d9f1-45d3-9888-e990b598900d"
@@ -257,8 +262,8 @@ bool FS_Info::run_blkid_load_cache( const Glib::ustring & path )
                return false;
 
        Glib::ustring cmd = "blkid";
-       if ( path.size() )
-               cmd = cmd + " " + Glib::shell_quote( path );
+       for (unsigned int i = 0; i < paths.size(); i++)
+               cmd.append(" " + Glib::shell_quote(paths[i]));
 
        Glib::ustring output;
        Glib::ustring error;
diff --git a/src/GParted_Core.cc b/src/GParted_Core.cc
index 9e1533e4..23187332 100644
--- a/src/GParted_Core.cc
+++ b/src/GParted_Core.cc
@@ -247,20 +247,10 @@ void GParted_Core::set_devices_thread( std::vector<Device> * pdevices )
                }
        }
 
-       std::cout << "DEBUG: device_paths=[";
-       for (unsigned int i = 0; i < device_paths.size(); i++)
-               std::cout << (i>0?",":"") << "\"" << device_paths[i] << "\"";
-       std::cout << "]" << std::endl;
-
+       // Initialise and load caches needed for content discovery.
        const std::vector<Glib::ustring>& device_and_partition_paths =
                        Proc_Partitions_Info::get_device_and_partition_paths_for(device_paths);
-       std::cout << "DEBUG: device_and_partition_paths=[";
-       for (unsigned int i = 0; i < device_and_partition_paths.size(); i++)
-               std::cout << (i>0?",":"") << "\"" << device_and_partition_paths[i] << "\"";
-       std::cout << "]" << std::endl;
-
-       // Initialise and load caches needed for content discovery.
-       FS_Info::load_cache_for_paths(device_paths);
+       FS_Info::load_cache_for_paths(device_and_partition_paths);
        Mount_Info::load_cache();
        LVM2_PV_Info::clear_cache();
        btrfs::clear_cache();


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