1a0d93
From 396216f71abf6907efd1383ca0d1a597918cd83d Mon Sep 17 00:00:00 2001
1a0d93
From: Ondrej Holy <oholy@redhat.com>
1a0d93
Date: Thu, 11 Oct 2018 17:47:59 +0200
1a0d93
Subject: [PATCH] daemon: Prevent spawning new daemons if outgoing operation
1a0d93
 exists
1a0d93
1a0d93
A new daemon is always spawned if MountLocation method (or LookupMount for
1a0d93
automounted) is called and the respective mount isn't registered yet. This
1a0d93
is not usually an issue, because the redundant daemons are consequently
1a0d93
terminated. However, this is a problem if mount operations hang for some reason.
1a0d93
This may happen e.g. with trash backend due to stale NFS mounts. Consequently,
1a0d93
new and new daemons are spawned which may lead to system failures due to lack
1a0d93
of system resources. See the following downstream bug report:
1a0d93
https://bugzilla.redhat.com/show_bug.cgi?id=1632960
1a0d93
1a0d93
Let's fix that behavior simply by preventing spawning of new daemons if
1a0d93
respective outgoing mount operations exist.
1a0d93
1a0d93
https://gitlab.gnome.org/GNOME/gvfs/merge_requests/19
1a0d93
---
1a0d93
 daemon/mount.c | 26 ++++++++++++++++++++++++++
1a0d93
 1 file changed, 26 insertions(+)
1a0d93
1a0d93
diff --git a/daemon/mount.c b/daemon/mount.c
1a0d93
index e242666d..33cae597 100644
1a0d93
--- a/daemon/mount.c
1a0d93
+++ b/daemon/mount.c
1a0d93
@@ -73,6 +73,7 @@ typedef void (*MountCallback) (VfsMountable *mountable,
1a0d93
 
1a0d93
 static GList *mountables = NULL;
1a0d93
 static GList *mounts = NULL;
1a0d93
+static GList *ongoing = NULL;
1a0d93
 
1a0d93
 static gboolean fuse_available;
1a0d93
 
1a0d93
@@ -253,6 +254,7 @@ typedef struct {
1a0d93
   char *obj_path;
1a0d93
   gboolean spawned;
1a0d93
   GVfsDBusSpawner *spawner;
1a0d93
+  GList *pending; /* MountData */
1a0d93
 } MountData;
1a0d93
 
1a0d93
 static void spawn_mount (MountData *data);
1a0d93
@@ -264,6 +266,7 @@ mount_data_free (MountData *data)
1a0d93
   g_mount_spec_unref (data->mount_spec);
1a0d93
   g_free (data->obj_path);
1a0d93
   g_clear_object (&data->spawner);
1a0d93
+  g_list_free_full (data->pending, (GDestroyNotify) mount_data_free);
1a0d93
 
1a0d93
   g_free (data);
1a0d93
 }
1a0d93
@@ -271,7 +274,17 @@ mount_data_free (MountData *data)
1a0d93
 static void
1a0d93
 mount_finish (MountData *data, GError *error)
1a0d93
 {
1a0d93
+  GList *l;
1a0d93
+
1a0d93
+  ongoing = g_list_remove (ongoing, data);
1a0d93
+
1a0d93
   data->callback (data->mountable, error, data->user_data);
1a0d93
+  for (l = data->pending; l != NULL; l = l->next)
1a0d93
+    {
1a0d93
+      MountData *pending_data = l->data;
1a0d93
+      pending_data->callback (pending_data->mountable, error, pending_data->user_data);
1a0d93
+    }
1a0d93
+
1a0d93
   mount_data_free (data);
1a0d93
 }
1a0d93
 
1a0d93
@@ -493,6 +506,7 @@ mountable_mount (VfsMountable *mountable,
1a0d93
 		 gpointer user_data)
1a0d93
 {
1a0d93
   MountData *data;
1a0d93
+  GList *l;
1a0d93
 
1a0d93
   data = g_new0 (MountData, 1);
1a0d93
   data->automount = automount;
1a0d93
@@ -502,6 +516,18 @@ mountable_mount (VfsMountable *mountable,
1a0d93
   data->callback = callback;
1a0d93
   data->user_data = user_data;
1a0d93
 
1a0d93
+  for (l = ongoing; l != NULL; l = l->next)
1a0d93
+    {
1a0d93
+      MountData *ongoing_data = l->data;
1a0d93
+      if (g_mount_spec_equal (ongoing_data->mount_spec, mount_spec))
1a0d93
+        {
1a0d93
+          ongoing_data->pending = g_list_append (ongoing_data->pending, data);
1a0d93
+          return;
1a0d93
+        }
1a0d93
+    }
1a0d93
+
1a0d93
+  ongoing = g_list_append (ongoing, data);
1a0d93
+
1a0d93
   if (mountable->dbus_name == NULL)
1a0d93
     spawn_mount (data);
1a0d93
   else
1a0d93
-- 
1a0d93
2.20.1
1a0d93