udisks2: Use hash table for quicker lookups in the monitor

Resolves: RHEL-143934
This commit is contained in:
Milan Crha 2026-01-22 10:58:59 +01:00
parent 6eb3742e27
commit a33223d1b7
5 changed files with 1989 additions and 1 deletions

View File

@ -22,7 +22,7 @@
Name: gvfs
Version: 1.48.1
Release: 6%{?dist}
Release: 7%{?dist}
Summary: Backends for the gio framework in GLib
License: GPLv3 and LGPLv2+ and BSD and MPLv2.0
@ -45,6 +45,12 @@ Patch7: smb-Disable-seek-support-when-appening.patch
Patch8: smb-Fix-offset-after-truncate-when-appending.patch
Patch9: smb-Implement-support-for-edit-mode.patch
# https://issues.redhat.com/browse/RHEL-143934
Patch10: udisks2-monitor-performance-202.patch
Patch11: udisks2-monitor-performance-230.patch
Patch12: udisks2-monitor-performance-273.patch
Patch13: udisks2-monitor-performance-290.patch
BuildRequires: meson
BuildRequires: gcc
BuildRequires: pkgconfig
@ -441,6 +447,9 @@ killall -USR1 gvfsd >&/dev/null || :
%{_datadir}/installed-tests
%changelog
* Mon Jan 26 2026 Milan Crha <mcrha@redhat.com> - 1.48.1-7
- udisks2: Use hash table for quicker lookups in the monitor (RHEL-143934)
* Thu Feb 13 2025 Ondrej Holy <oholy@redhat.com> - 1.48.1-6
- Add edit mode support for smb backend (RHEL-71088)

View File

@ -0,0 +1,109 @@
From 14dc69defb82a789999ba43e5350438d9c7086a6 Mon Sep 17 00:00:00 2001
Date: Mon, 11 Mar 2024 10:20:51 +0100
Subject: [PATCH] udisks2: Do not schedule update if pending already
Currently, the udisks2 volume monitor updates everything for each
`/proc/mounts`, `/etc/fstab`, and udisks2 change. The update takes some
time. If too many changes happen in a short timeframe, the udisks2
volume monitor is not able to handle those events in a real-time. The
pending events can be processed for a long time. Many of those updates
are redundant though as the real changes were already reflected during
the previous updates. This causes a high CPU load among others. Let's
add small timeout that will allow to skip accumullated events.
Fixes: https://gitlab.gnome.org/GNOME/gvfs/-/issues/713
---
monitor/udisks2/gvfsudisks2volumemonitor.c | 35 +++++++++++++++++++---
1 file changed, 31 insertions(+), 4 deletions(-)
diff --git a/monitor/udisks2/gvfsudisks2volumemonitor.c b/monitor/udisks2/gvfsudisks2volumemonitor.c
index c8864aea8..540683b22 100644
--- a/monitor/udisks2/gvfsudisks2volumemonitor.c
+++ b/monitor/udisks2/gvfsudisks2volumemonitor.c
@@ -68,8 +68,12 @@ struct _GVfsUDisks2VolumeMonitor
GSettings *lockdown_settings;
gboolean readonly_lockdown;
+
+ gint update_id;
};
+#define UPDATE_TIMEOUT 100 /* ms */
+
static UDisksClient *get_udisks_client_sync (GError **error);
static void update_all (GVfsUDisks2VolumeMonitor *monitor,
@@ -148,6 +152,8 @@ gvfs_udisks2_volume_monitor_finalize (GObject *object)
g_clear_object (&monitor->lockdown_settings);
+ g_clear_handle_id (&monitor->update_id, g_source_remove);
+
G_OBJECT_CLASS (gvfs_udisks2_volume_monitor_parent_class)->finalize (object);
}
@@ -425,12 +431,33 @@ gvfs_udisks2_volume_monitor_get_readonly_lockdown (GVfsUDisks2VolumeMonitor *mon
/* ---------------------------------------------------------------------------------------------------- */
+static gboolean
+update_func (gpointer user_data)
+{
+ GVfsUDisks2VolumeMonitor *monitor = GVFS_UDISKS2_VOLUME_MONITOR (user_data);
+
+ monitor->update_id = 0;
+
+ update_all (monitor, TRUE, FALSE);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+schedule_update (GVfsUDisks2VolumeMonitor *monitor)
+{
+ if (monitor->update_id != 0)
+ return;
+
+ monitor->update_id = g_timeout_add (UPDATE_TIMEOUT, update_func, monitor);
+}
+
void
gvfs_udisks2_volume_monitor_update (GVfsUDisks2VolumeMonitor *monitor)
{
g_return_if_fail (GVFS_IS_UDISKS2_VOLUME_MONITOR (monitor));
udisks_client_settle (monitor->client);
- update_all (monitor, TRUE, FALSE);
+ schedule_update (monitor);
}
/* ---------------------------------------------------------------------------------------------------- */
@@ -532,7 +559,7 @@ on_client_changed (UDisksClient *client,
gpointer user_data)
{
GVfsUDisks2VolumeMonitor *monitor = GVFS_UDISKS2_VOLUME_MONITOR (user_data);
- update_all (monitor, TRUE, FALSE);
+ schedule_update (monitor);
}
static void
@@ -540,7 +567,7 @@ mountpoints_changed (GUnixMountMonitor *mount_monitor,
gpointer user_data)
{
GVfsUDisks2VolumeMonitor *monitor = GVFS_UDISKS2_VOLUME_MONITOR (user_data);
- update_all (monitor, TRUE, FALSE);
+ schedule_update (monitor);
}
static void
@@ -548,7 +575,7 @@ mounts_changed (GUnixMountMonitor *mount_monitor,
gpointer user_data)
{
GVfsUDisks2VolumeMonitor *monitor = GVFS_UDISKS2_VOLUME_MONITOR (user_data);
- update_all (monitor, TRUE, FALSE);
+ schedule_update (monitor);
}
/* ---------------------------------------------------------------------------------------------------- */
--
GitLab

View File

@ -0,0 +1,39 @@
From 45a5612574a54bf4648cedafa5b977efb48293c9 Mon Sep 17 00:00:00 2001
Date: Thu, 12 Sep 2024 13:27:04 +0200
Subject: [PATCH] udisks2: Run update synchronously for internal changes
The commit 14dc69de introduced performance improvement by skipping
accumulated mount, mount point and udisks2 client changes. That was
achieved by running the update with a small delay. But this logic was
mistakenly used for the `gvfs_udisks2_volume_monitor_update` function
also. This function expects the update to happen synchronously. This
leads to various issues e.g. `g_volume_get_mount` fails when called
immediately after `g_volume_mount`. Let's run the update synchronously
from the `gvfs_udisks2_volume_monitor_update` function to fix the
mentioned issues.
Fixes: https://gitlab.gnome.org/GNOME/gvfs/-/issues/762
---
monitor/udisks2/gvfsudisks2volumemonitor.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/monitor/udisks2/gvfsudisks2volumemonitor.c b/monitor/udisks2/gvfsudisks2volumemonitor.c
index 3a2015b29..f78f28d40 100644
--- a/monitor/udisks2/gvfsudisks2volumemonitor.c
+++ b/monitor/udisks2/gvfsudisks2volumemonitor.c
@@ -457,7 +457,11 @@ gvfs_udisks2_volume_monitor_update (GVfsUDisks2VolumeMonitor *monitor)
{
g_return_if_fail (GVFS_IS_UDISKS2_VOLUME_MONITOR (monitor));
udisks_client_settle (monitor->client);
- schedule_update (monitor);
+
+ if (monitor->update_id != 0)
+ g_source_remove (monitor->update_id);
+
+ update_func (monitor);
}
/* ---------------------------------------------------------------------------------------------------- */
--
GitLab

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,90 @@
Adapted https://gitlab.gnome.org/GNOME/gvfs/-/merge_requests/290
diff --git a/monitor/udisks2/gvfsudisks2volumemonitor.c b/monitor/udisks2/gvfsudisks2volumemonitor.c
index 51068f9..48120d9 100644
--- a/monitor/udisks2/gvfsudisks2volumemonitor.c
+++ b/monitor/udisks2/gvfsudisks2volumemonitor.c
@@ -92,6 +92,7 @@ static void update_volumes (GVfsUDisks2VolumeMonitor *monitor,
GList **removed_volumes,
gboolean coldplug);
static void update_fstab_volumes (GVfsUDisks2VolumeMonitor *monitor,
+ GHashTable *mount_points_by_path, /* gchar *path ~> GUnixMountPoint * */
GList **added_volumes,
GList **removed_volumes,
gboolean coldplug);
@@ -749,7 +750,7 @@ update_all (GVfsUDisks2VolumeMonitor *monitor,
update_drives (monitor, &added_drives, &removed_drives, coldplug);
update_volumes (monitor, mount_entries, mount_points_by_path, &added_volumes, &removed_volumes, coldplug);
- update_fstab_volumes (monitor, &added_volumes, &removed_volumes, coldplug);
+ update_fstab_volumes (monitor, mount_points_by_path, &added_volumes, &removed_volumes, coldplug);
update_mounts (monitor, mount_entries, mount_points_by_path, &added_mounts, &removed_mounts, coldplug);
update_discs (monitor,
&added_volumes, &removed_volumes,
@@ -1637,16 +1638,9 @@ mount_point_has_device (GVfsUDisks2VolumeMonitor *monitor,
return ret;
}
-static void
-free_nonnull_unix_mount_point (gpointer ptr)
-{
- GUnixMountPoint *mount_point = ptr;
- if (mount_point != NULL)
- g_unix_mount_point_free (mount_point);
-}
-
static void
update_fstab_volumes (GVfsUDisks2VolumeMonitor *monitor,
+ GHashTable *mount_points_by_path, /* gchar *path ~> GUnixMountPoint * */
GList **added_volumes,
GList **removed_volumes,
gboolean coldplug)
@@ -1654,7 +1648,6 @@ update_fstab_volumes (GVfsUDisks2VolumeMonitor *monitor,
GHashTable *cur_mount_points; /* GUnixMountPoint * ~> GVfsUDisks2Volume * */
GHashTableIter iter;
gpointer key = NULL, value = NULL;
- GList *new_mount_points, *l;
GVfsUDisks2Volume *volume;
cur_mount_points = g_hash_table_new_full (gvfs_mount_point_hash, gvfs_mount_point_equal, NULL, g_object_unref);
@@ -1669,11 +1662,10 @@ update_fstab_volumes (GVfsUDisks2VolumeMonitor *monitor,
g_hash_table_insert (cur_mount_points, mount_point, g_object_ref (volume));
}
- new_mount_points = g_unix_mount_points_get (NULL);
- /* filter the mount points that we don't want to include */
- for (l = new_mount_points; l != NULL; l = g_list_next (l))
+ g_hash_table_iter_init (&iter, mount_points_by_path);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
{
- GUnixMountPoint *mount_point = l->data;
+ GUnixMountPoint *mount_point = value;
/* use the mount points that we want to include */
if (should_include_mount_point (monitor, mount_point) &&
@@ -1685,7 +1677,7 @@ update_fstab_volumes (GVfsUDisks2VolumeMonitor *monitor,
{
volume = gvfs_udisks2_volume_new (monitor,
NULL, /* block */
- mount_point,
+ g_unix_mount_point_copy (mount_point), /* adopts the mount_point */
NULL, /* drive */
NULL, /* activation_root */
coldplug);
@@ -1702,7 +1694,6 @@ update_fstab_volumes (GVfsUDisks2VolumeMonitor *monitor,
g_hash_table_add (monitor->fstab_volumes, g_object_ref (volume));
*added_volumes = g_list_prepend (*added_volumes, g_steal_pointer (&volume));
- l->data = NULL;
}
}
}
@@ -1718,8 +1709,6 @@ update_fstab_volumes (GVfsUDisks2VolumeMonitor *monitor,
g_hash_table_remove (monitor->fstab_volumes, volume);
}
- g_list_free_full (new_mount_points, free_nonnull_unix_mount_point);
-
g_hash_table_unref (cur_mount_points);
}