[gvfs] GDaemonMount: invalidate mount cache whenever we unmount a mount



commit 2744d498095aeca09308819bca42d0fe287523d0
Author: Simon McVittie <simon mcvittie collabora co uk>
Date:   Thu Jul 24 20:24:42 2014 +0100

    GDaemonMount: invalidate mount cache whenever we unmount a mount
    
    Otherwise, the old mount info, and in particular the (D-Bus unique name,
    object path) pair representing it in its backend, will remain in
    the cache until the backend process exits, which could take time.
    Re-mounting and re-unmounting that mount would fail, because the
    second Unmount() call would go to the unique name and object path of
    the backend object that was destroyed by the first Unmount call,
    not the backend object that is now responsible.
    
    I'm using the Unmount reply rather than a signal, for thread-safety;
    the mount cache is global, so if it was listening for the Unmounted
    signal, that signal would be queued up for delivery to some
    specific main-context, call it A. If another thread did the
    umount/mount/unmount in main context B, before main context A was
    dispatched, then the invalidation would be too late to help it.
    
    This does not cover concurrent mount/unmount in two distinct main
    contexts without any synchronization. However, if two threads in
    main contexts B and C race to mount/unmount a share, then they're
    sometimes going to lose anyway, and there isn't a great deal that
    cache invalidation can do to help them.

 client/gdaemonmount.c   |    4 ++++
 client/gdaemonvfs.c     |   16 +++++++++++++---
 client/gdaemonvfs.h     |    3 ++-
 client/gvfsdaemondbus.c |    4 ++--
 4 files changed, 21 insertions(+), 6 deletions(-)
---
diff --git a/client/gdaemonmount.c b/client/gdaemonmount.c
index e4acef0..60dd8bf 100644
--- a/client/gdaemonmount.c
+++ b/client/gdaemonmount.c
@@ -210,9 +210,13 @@ unmount_reply (GVfsDBusMount *proxy,
                GAsyncResult *res,
                gpointer user_data)
 {
+  GDBusProxy *base_proxy = G_DBUS_PROXY (proxy);
   AsyncProxyCreate *data = user_data;
   GError *error = NULL;
 
+  _g_daemon_vfs_invalidate (g_dbus_proxy_get_name (base_proxy),
+                            g_dbus_proxy_get_object_path (base_proxy));
+
   if (! gvfs_dbus_mount_call_unmount_finish (proxy, res, &error))
     {
       _g_simple_async_result_take_error_stripped (data->result, error);
diff --git a/client/gdaemonvfs.c b/client/gdaemonvfs.c
index 7a6dc0a..9ab806b 100644
--- a/client/gdaemonvfs.c
+++ b/client/gdaemonvfs.c
@@ -740,9 +740,18 @@ lookup_mount_info_by_fuse_path_in_cache (const char *fuse_path,
   return info;
 }
 
-
+/*
+ * _g_daemon_vfs_invalidate:
+ * @dbus_id: the D-Bus unique name of the backend process
+ * @object_path: the object path of the mount, or %NULL to invalidate
+ *    all mounts in that process
+ *
+ * Invalidate cache entries because we get out-of-band information that
+ * something has been mounted or unmounted.
+ */
 void
-_g_daemon_vfs_invalidate_dbus_id (const char *dbus_id)
+_g_daemon_vfs_invalidate (const char *dbus_id,
+                          const char *object_path)
 {
   GList *l, *next;
 
@@ -752,7 +761,8 @@ _g_daemon_vfs_invalidate_dbus_id (const char *dbus_id)
       GMountInfo *mount_info = l->data;
       next = l->next;
 
-      if (strcmp (mount_info->dbus_id, dbus_id) == 0)
+      if (strcmp (mount_info->dbus_id, dbus_id) == 0 &&
+          (object_path == NULL || strcmp (mount_info->object_path, object_path) == 0))
        {
          the_vfs->mount_cache = g_list_delete_link (the_vfs->mount_cache, l);
          g_mount_info_unref (mount_info);
diff --git a/client/gdaemonvfs.h b/client/gdaemonvfs.h
index c5ecefc..5d5195d 100644
--- a/client/gdaemonvfs.h
+++ b/client/gdaemonvfs.h
@@ -67,7 +67,8 @@ GMountInfo *    _g_daemon_vfs_get_mount_info_by_fuse_sync (const char *fuse_path
 GMountSpec *    _g_daemon_vfs_get_mount_spec_for_path  (GMountSpec               *spec,
                                                        const char               *path,
                                                        const char               *new_path);
-void            _g_daemon_vfs_invalidate_dbus_id       (const char               *dbus_id);
+void            _g_daemon_vfs_invalidate               (const char               *dbus_id,
+                                                        const char               *object_path);
 GDBusConnection *_g_daemon_vfs_get_async_bus           (void);
 int             _g_daemon_vfs_append_metadata_for_set  (GVariantBuilder *builder,
                                                        MetaTree *tree,
diff --git a/client/gvfsdaemondbus.c b/client/gvfsdaemondbus.c
index b74370c..dc5f50f 100644
--- a/client/gvfsdaemondbus.c
+++ b/client/gvfsdaemondbus.c
@@ -81,7 +81,7 @@ vfs_connection_closed (GDBusConnection *connection,
 
   if (connection_data->async_dbus_id)
     {
-      _g_daemon_vfs_invalidate_dbus_id (connection_data->async_dbus_id);
+      _g_daemon_vfs_invalidate (connection_data->async_dbus_id, NULL);
       G_LOCK (async_map);
       g_hash_table_remove (async_map, connection_data->async_dbus_id);
       G_UNLOCK (async_map);
@@ -472,7 +472,7 @@ invalidate_local_connection (const char *dbus_id,
 {
   ThreadLocalConnections *local;
   
-  _g_daemon_vfs_invalidate_dbus_id (dbus_id);
+  _g_daemon_vfs_invalidate (dbus_id, NULL);
 
   local = g_private_get (&local_connections);
   if (local)


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