[gvfs/wip/oholy/pending-mounts: 3/3] daemon: Prevent spawning new daemons if outgoing operation exists



commit 396216f71abf6907efd1383ca0d1a597918cd83d
Author: Ondrej Holy <oholy redhat com>
Date:   Thu Oct 11 17:47:59 2018 +0200

    daemon: Prevent spawning new daemons if outgoing operation exists
    
    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
    terminated. 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 outgoing mount operations exist.
    
    https://gitlab.gnome.org/GNOME/gvfs/merge_requests/19

 daemon/mount.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
---
diff --git a/daemon/mount.c b/daemon/mount.c
index e242666d..33cae597 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 *ongoing = NULL;
 
 static gboolean fuse_available;
 
@@ -253,6 +254,7 @@ typedef struct {
   char *obj_path;
   gboolean spawned;
   GVfsDBusSpawner *spawner;
+  GList *pending; /* MountData */
 } MountData;
 
 static void spawn_mount (MountData *data);
@@ -264,6 +266,7 @@ mount_data_free (MountData *data)
   g_mount_spec_unref (data->mount_spec);
   g_free (data->obj_path);
   g_clear_object (&data->spawner);
+  g_list_free_full (data->pending, (GDestroyNotify) mount_data_free);
 
   g_free (data);
 }
@@ -271,7 +274,17 @@ mount_data_free (MountData *data)
 static void
 mount_finish (MountData *data, GError *error)
 {
+  GList *l;
+
+  ongoing = g_list_remove (ongoing, data);
+
   data->callback (data->mountable, error, data->user_data);
+  for (l = data->pending; l != NULL; l = l->next)
+    {
+      MountData *pending_data = l->data;
+      pending_data->callback (pending_data->mountable, error, pending_data->user_data);
+    }
+
   mount_data_free (data);
 }
 
@@ -493,6 +506,7 @@ mountable_mount (VfsMountable *mountable,
                 gpointer user_data)
 {
   MountData *data;
+  GList *l;
 
   data = g_new0 (MountData, 1);
   data->automount = automount;
@@ -502,6 +516,18 @@ mountable_mount (VfsMountable *mountable,
   data->callback = callback;
   data->user_data = user_data;
 
+  for (l = ongoing; l != NULL; l = l->next)
+    {
+      MountData *ongoing_data = l->data;
+      if (g_mount_spec_equal (ongoing_data->mount_spec, mount_spec))
+        {
+          ongoing_data->pending = g_list_append (ongoing_data->pending, data);
+          return;
+        }
+    }
+
+  ongoing = g_list_append (ongoing, data);
+
   if (mountable->dbus_name == NULL)
     spawn_mount (data);
   else


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