summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Kellner <gicmo@gnome.org>2011-05-25 15:38:52 +0200
committerChristian Kellner <gicmo@gnome.org>2011-06-06 14:40:45 +0200
commit100ea69c8dbdc99e37edc52b6de1011fa130d9a3 (patch)
treec862b4d5d8335ce8b9aef0309bc8db1be91637d5
parente078f0e75203969ef4c7bcbc61bd935d65316cc9 (diff)
downloadgvfs-100ea69c8dbdc99e37edc52b6de1011fa130d9a3.tar.gz
daemon: Implement auto-busy on unmount
Add generic logic to GVfsJobUnmount to automatically return G_IO_ERROR_BUSY when there are active connections _and_ the user decided to not force and unmount. Fixes bug 509606.
-rw-r--r--daemon/gvfsjobunmount.c106
1 files changed, 90 insertions, 16 deletions
diff --git a/daemon/gvfsjobunmount.c b/daemon/gvfsjobunmount.c
index 17e364f1..c4fadbca 100644
--- a/daemon/gvfsjobunmount.c
+++ b/daemon/gvfsjobunmount.c
@@ -137,27 +137,92 @@ run (GVfsJob *job)
}
static gboolean
+job_finish_immediately_if_possible (GVfsJobUnmount *op_job)
+{
+ GVfsBackend *backend = op_job->backend;
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+ gboolean is_busy;
+ gboolean force_unmount;
+
+ if (class->try_unmount != NULL || class->unmount != NULL)
+ return FALSE;
+
+ is_busy = g_vfs_backend_has_blocking_processes (backend);
+ force_unmount = op_job->flags & G_MOUNT_UNMOUNT_FORCE;
+
+ if (is_busy && ! force_unmount)
+ g_vfs_job_failed_literal (G_VFS_JOB (op_job),
+ G_IO_ERROR, G_IO_ERROR_BUSY,
+ _("Filesystem is busy"));
+ else
+ g_vfs_job_succeeded (G_VFS_JOB (op_job));
+
+ return TRUE;
+}
+
+static void
+unmount_cb (GVfsBackend *backend,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GVfsJobUnmount *op_job = G_VFS_JOB_UNMOUNT (user_data);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+ gboolean should_unmount;
+ gboolean finished;
+
+ should_unmount = g_vfs_backend_unmount_with_operation_finish (backend,
+ res);
+
+ if (should_unmount)
+ op_job->flags |= G_MOUNT_UNMOUNT_FORCE;
+
+ finished = job_finish_immediately_if_possible (op_job);
+
+ if (! finished)
+ {
+ gboolean run_in_thread = TRUE;
+
+ if (class->try_unmount != NULL)
+ run_in_thread = ! class->try_unmount (op_job->backend,
+ op_job,
+ op_job->flags,
+ op_job->mount_source);
+
+ if (run_in_thread)
+ g_vfs_daemon_run_job_in_thread (g_vfs_backend_get_daemon (backend),
+ G_VFS_JOB (op_job));
+ }
+}
+
+static gboolean
try (GVfsJob *job)
{
GVfsJobUnmount *op_job = G_VFS_JOB_UNMOUNT (job);
+ GVfsBackend *backend = op_job->backend;
GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+ gboolean is_busy;
+ gboolean force_unmount;
- if (class->try_unmount == NULL)
- {
- if (class->unmount == NULL)
- {
- /* If unmount is not implemented we always succeed */
- g_vfs_job_succeeded (G_VFS_JOB (job));
- return TRUE;
- }
+ is_busy = g_vfs_backend_has_blocking_processes (backend);
+ force_unmount = op_job->flags & G_MOUNT_UNMOUNT_FORCE;
- return FALSE;
+ if (is_busy && ! force_unmount
+ && ! g_mount_source_is_dummy (op_job->mount_source))
+ {
+ g_vfs_backend_unmount_with_operation (backend,
+ op_job->mount_source,
+ (GAsyncReadyCallback) unmount_cb,
+ op_job);
+ return TRUE;
}
- return class->try_unmount (op_job->backend,
- op_job,
- op_job->flags,
- op_job->mount_source);
+ if (job_finish_immediately_if_possible (op_job))
+ return TRUE;
+ else
+ return class->try_unmount (op_job->backend,
+ op_job,
+ op_job->flags,
+ op_job->mount_source);
}
static void
@@ -175,6 +240,8 @@ unregister_mount_callback (DBusMessage *unmount_reply,
/* Unlink job source from daemon */
g_vfs_job_source_closed (G_VFS_JOB_SOURCE (backend));
+
+ g_vfs_daemon_close_active_channels (g_vfs_backend_get_daemon ((backend)));
}
/* Might be called on an i/o thread */
@@ -188,9 +255,16 @@ send_reply (GVfsJob *job)
if (job->failed)
(*G_VFS_JOB_CLASS (g_vfs_job_unmount_parent_class)->send_reply) (G_VFS_JOB (op_job));
else
- g_vfs_backend_unregister_mount (op_job->backend,
- unregister_mount_callback,
- job);
+ {
+ GVfsBackend *backend = op_job->backend;
+
+ /* Setting the backend to block requests will also
+ set active GVfsChannels to block requets */
+ g_vfs_backend_set_block_requests (backend);
+ g_vfs_backend_unregister_mount (backend,
+ unregister_mount_callback,
+ job);
+ }
}
/* Might be called on an i/o thread */