summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2014-07-24 20:24:42 +0100
committerRoss Lagerwall <rosslagerwall@gmail.com>2014-07-25 07:45:45 +0100
commit2744d498095aeca09308819bca42d0fe287523d0 (patch)
tree3f222d604f0e76c7339982d5a725741f86948879 /client
parent64e51eb07cd6628991842c6be8eb276802b71154 (diff)
downloadgvfs-2744d498095aeca09308819bca42d0fe287523d0.tar.gz
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.
Diffstat (limited to 'client')
-rw-r--r--client/gdaemonmount.c4
-rw-r--r--client/gdaemonvfs.c16
-rw-r--r--client/gdaemonvfs.h3
-rw-r--r--client/gvfsdaemondbus.c4
4 files changed, 21 insertions, 6 deletions
diff --git a/client/gdaemonmount.c b/client/gdaemonmount.c
index e4acef0a..60dd8bf3 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 7a6dc0aa..9ab806b3 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 c5ecefc5..5d5195d4 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 b74370c1..dc5f50ff 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)