[gvfs/wip/oholy/pending-mounts] daemon: Prevent spawning new daemons if mount operation pending
- From: Ondrej Holy <oholy src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gvfs/wip/oholy/pending-mounts] daemon: Prevent spawning new daemons if mount operation pending
- Date: Fri, 12 Oct 2018 07:33:15 +0000 (UTC)
commit 103910f934173e0ec84d608dc96caaccea47d8b4
Author: Ondrej Holy <oholy redhat com>
Date: Thu Oct 11 17:47:59 2018 +0200
daemon: Prevent spawning new daemons if mount operation pending
A new daemon is always spawned if MountLocation method (or LookupMount for
automounted) is called and the respective mount isn't registered yet. This
is not usually an issue, because the redundant daemons are consequently
removed. However, this is a problem if mount operations hang for some reason.
This may happen e.g. with trash backend due to stale NFS mounts. Consequently,
new and new daemons are spawned which may lead to system failures due to lack
of system resources. See the following downstream bug report:
https://bugzilla.redhat.com/show_bug.cgi?id=1632960
Let's fix that behavior simply by preventing spawning of new daemons if
respective mount operations are already pending.
daemon/mount.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
---
diff --git a/daemon/mount.c b/daemon/mount.c
index e242666d..df6bd357 100644
--- a/daemon/mount.c
+++ b/daemon/mount.c
@@ -73,6 +73,7 @@ typedef void (*MountCallback) (VfsMountable *mountable,
static GList *mountables = NULL;
static GList *mounts = NULL;
+static GList *pending = NULL;
static gboolean fuse_available;
@@ -268,10 +269,58 @@ mount_data_free (MountData *data)
g_free (data);
}
+static int
+pending_compare (MountData *a, MountData *b)
+{
+ return g_mount_spec_equal (a->mount_spec, b->mount_spec) ? 0 : 1;
+}
+
+static void
+pending_remove (MountData *data, GError *error)
+{
+ GList *l, *next;
+ MountData *pending_data;
+
+ pending = g_list_remove (pending, data);
+
+ l = pending;
+ while (l != NULL)
+ {
+ next = l->next;
+ pending_data = l->data;
+
+ if (g_mount_spec_equal (pending_data->mount_spec, data->mount_spec))
+ {
+ pending_data->callback (pending_data->mountable, error, pending_data->user_data);
+ mount_data_free (pending_data);
+
+ pending = g_list_delete_link (pending, l);
+ }
+
+ l = next;
+ }
+}
+
+static gboolean
+pending_append (MountData *data)
+{
+ gboolean is_pending = FALSE;
+
+ if (g_list_find_custom (pending, data, (GCompareFunc) pending_compare) != NULL)
+ is_pending = TRUE;
+
+ pending = g_list_append (pending, data);
+
+ return is_pending;
+}
+
static void
mount_finish (MountData *data, GError *error)
{
data->callback (data->mountable, error, data->user_data);
+
+ pending_remove (data, error);
+
mount_data_free (data);
}
@@ -502,6 +551,9 @@ mountable_mount (VfsMountable *mountable,
data->callback = callback;
data->user_data = user_data;
+ if (pending_append (data))
+ return;
+
if (mountable->dbus_name == NULL)
spawn_mount (data);
else
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]