[gparted] Replace /proc/mounts grep with Mount_Info cache reload and query (!89)



commit ba1bafc5acd5569df4ba21f7e940998f9877b0bf
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Sun Sep 5 10:10:59 2021 +0100

    Replace /proc/mounts grep with Mount_Info cache reload and query (!89)
    
    Creating a grep process to check if a particular mount is still mounted
    is an unnecessary overhead.  All that is needed is for the Mount_Info
    module to refresh it's copy of /proc/mounts and query that.
    
    To keep the code as simple as possible just reload the whole of the
    Mount_Info module and query the mount cache to determine if the
    particular block device is still mounted at this particular mount point.
    This therefore re-reads /proc/mounts (necessary) and /proc/swaps and
    /etc/fstab (unnecessary).  This is still much less overhead than
    creating a separate grep process.
    
    Closes !89 - Fix unmount error when unmounting below a bind mount point

 include/Mount_Info.h |  1 +
 src/Mount_Info.cc    | 12 ++++++++++++
 src/Win_GParted.cc   | 16 +++++++++-------
 3 files changed, 22 insertions(+), 7 deletions(-)
---
diff --git a/include/Mount_Info.h b/include/Mount_Info.h
index e9310ddc..ae4a6513 100644
--- a/include/Mount_Info.h
+++ b/include/Mount_Info.h
@@ -49,6 +49,7 @@ public:
        static void load_cache();
        static bool is_dev_mounted( const Glib::ustring & path );
        static bool is_dev_mounted( const BlockSpecial & bs );
+       static bool is_dev_mounted_at(const Glib::ustring& path, const Glib::ustring& mountpoint);
        static bool is_dev_mounted_readonly( const Glib::ustring & path );
        static bool is_dev_mounted_readonly( const BlockSpecial & bs );
        static std::vector<Glib::ustring> get_all_mountpoints();
diff --git a/src/Mount_Info.cc b/src/Mount_Info.cc
index 3794bce4..81dd5e44 100644
--- a/src/Mount_Info.cc
+++ b/src/Mount_Info.cc
@@ -136,6 +136,18 @@ const std::vector<Glib::ustring> & Mount_Info::get_fstab_mountpoints( const Glib
        return find( fstab_info, path ).mountpoints;
 }
 
+
+// Return whether the device path, such as /dev/sda3, is mounted at mount point or not
+bool Mount_Info::is_dev_mounted_at(const Glib::ustring& path, const Glib::ustring& mountpoint)
+{
+       const std::vector<Glib::ustring>& mountpoints = get_mounted_mountpoints(path);
+       for (unsigned i = 0; i < mountpoints.size(); i++)
+               if (mountpoint == mountpoints[i])
+                       return true;
+       return false;
+}
+
+
 // Private methods
 
 void Mount_Info::read_mountpoints_from_file( const Glib::ustring & filename, MountMapping & map )
diff --git a/src/Win_GParted.cc b/src/Win_GParted.cc
index fcb086eb..ae7998f2 100644
--- a/src/Win_GParted.cc
+++ b/src/Win_GParted.cc
@@ -2847,14 +2847,16 @@ bool Win_GParted::unmount_partition( const Partition & partition, Glib::ustring
                }
                else
                {
-                       Glib::ustring checkmount = "grep -w " + Glib::shell_quote(fs_mountpoints[i]) + " 
/proc/mounts";
-                       Glib::ustring cmd = "umount -v " + Glib::shell_quote( fs_mountpoints[i] );
-                       Glib::ustring dummy;
-                       Glib::ustring umount_error;
-
-                       // Check mount point is still mounted
-                       if (! Utils::execute_command(checkmount, dummy, umount_error))
+                       // Unmounting below a duplicating bind mount, unmounts all copies
+                       // in one go so check if the file system is still mounted at this
+                       // mount point before trying to unmount it.
+                       Mount_Info::load_cache();
+                       if (Mount_Info::is_dev_mounted_at(partition.get_path(), fs_mountpoints[i]))
                        {
+                               Glib::ustring cmd = "umount -v " + Glib::shell_quote(fs_mountpoints[i]);
+                               Glib::ustring dummy;
+                               Glib::ustring umount_error;
+
                                if (Utils::execute_command(cmd, dummy, umount_error))
                                        umount_errors.push_back("# " + cmd + "\n" + umount_error);
                        }


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