[gvfs] udisks2: Lock unlocked volumes on eject/stop
- From: Ondrej Holy <oholy src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gvfs] udisks2: Lock unlocked volumes on eject/stop
- Date: Wed, 6 Apr 2016 14:17:41 +0000 (UTC)
commit dd98c02ecde5cc081a2d0e3990780efe3d66edfa
Author: Ondrej Holy <oholy redhat com>
Date: Thu Mar 24 10:04:15 2016 +0100
udisks2: Lock unlocked volumes on eject/stop
The eject/stop operation fails currently with "Cannot eject drive in
use: Encrypted device /dev/sdb1 is unlocked" if any volume is unlocked
and isn't mounted. The volume monitor is able to mount already unlocked
volumes, so it should be able to eject unlocked volumes also. Lock the
unlocked volumes if there are any before eject/stop operation.
https://bugzilla.gnome.org/show_bug.cgi?id=763890
monitor/udisks2/gvfsudisks2drive.c | 216 ++++++++++++++++++++++++++---------
1 files changed, 160 insertions(+), 56 deletions(-)
---
diff --git a/monitor/udisks2/gvfsudisks2drive.c b/monitor/udisks2/gvfsudisks2drive.c
index 5cc0006..3bd3060 100644
--- a/monitor/udisks2/gvfsudisks2drive.c
+++ b/monitor/udisks2/gvfsudisks2drive.c
@@ -524,7 +524,7 @@ gvfs_udisks2_drive_enumerate_identifiers (GDrive *_drive)
/* ---------------------------------------------------------------------------------------------------- */
-typedef void (*UnmountsMountsFunc) (GDrive *drive,
+typedef void (*UnmountAndLockFunc) (GDrive *drive,
GMountOperation *mount_operation,
GCancellable *cancellable,
GAsyncReadyCallback callback,
@@ -540,13 +540,14 @@ typedef struct {
GMountUnmountFlags flags;
GList *pending_mounts;
+ GList *pending_encrypted;
- UnmountsMountsFunc on_all_unmounted;
+ UnmountAndLockFunc on_all_unmounted;
gpointer on_all_unmounted_data;
-} UnmountMountsOp;
+} UnmountAndLockOp;
static void
-free_unmount_mounts_op (UnmountMountsOp *data)
+free_unmount_and_lock_op (UnmountAndLockOp *data)
{
g_list_free_full (data->pending_mounts, g_object_unref);
@@ -555,25 +556,19 @@ free_unmount_mounts_op (UnmountMountsOp *data)
}
static void
-unmount_mounts_cb (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data);
+unmount_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data);
static void
-unmount_mounts_do (UnmountMountsOp *data)
-{
- if (data->pending_mounts == NULL)
- {
- data->on_all_unmounted (data->drive,
- data->mount_operation,
- data->cancellable,
- data->callback,
- data->user_data,
- data->on_all_unmounted_data);
+lock_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data);
- free_unmount_mounts_op (data);
- }
- else
+static void
+unmount_and_lock_do (UnmountAndLockOp *data)
+{
+ if (data->pending_mounts != NULL)
{
GMount *mount;
mount = data->pending_mounts->data;
@@ -583,17 +578,41 @@ unmount_mounts_do (UnmountMountsOp *data)
data->flags,
data->mount_operation,
data->cancellable,
- unmount_mounts_cb,
+ unmount_cb,
data);
}
+ else if (data->pending_encrypted != NULL)
+ {
+ UDisksEncrypted *encrypted;
+
+ encrypted = data->pending_encrypted->data;
+ data->pending_encrypted = g_list_remove (data->pending_encrypted, encrypted);
+
+ udisks_encrypted_call_lock (encrypted,
+ g_variant_new ("a{sv}", NULL), /* options */
+ data->cancellable,
+ lock_cb,
+ data);
+ }
+ else
+ {
+ data->on_all_unmounted (data->drive,
+ data->mount_operation,
+ data->cancellable,
+ data->callback,
+ data->user_data,
+ data->on_all_unmounted_data);
+
+ free_unmount_and_lock_op (data);
+ }
}
static void
-unmount_mounts_cb (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
+unmount_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
{
- UnmountMountsOp *data = user_data;
+ UnmountAndLockOp *data = user_data;
GMount *mount = G_MOUNT (source_object);
GSimpleAsyncResult *simple;
GError *error = NULL;
@@ -621,31 +640,65 @@ unmount_mounts_cb (GObject *source_object,
g_simple_async_result_complete (simple);
g_object_unref (simple);
- free_unmount_mounts_op (data);
+ free_unmount_and_lock_op (data);
}
else
{
/* move on to the next mount.. */
- unmount_mounts_do (data);
+ unmount_and_lock_do (data);
}
g_object_unref (mount);
}
static void
-unmount_mounts (GVfsUDisks2Drive *drive,
- GMountUnmountFlags flags,
- GMountOperation *mount_operation,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data,
- UnmountsMountsFunc on_all_unmounted,
- gpointer on_all_unmounted_data)
+lock_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ UDisksEncrypted *encrypted = UDISKS_ENCRYPTED (source_object);
+ UnmountAndLockOp *data = user_data;
+ GSimpleAsyncResult *simple;
+ GError *error = NULL;
+
+ if (!udisks_encrypted_call_lock_finish (encrypted,
+ res,
+ &error))
+ {
+ /* lock failed; need to fail the whole eject operation */
+ simple = g_simple_async_result_new_from_error (G_OBJECT (data->drive),
+ data->callback,
+ data->user_data,
+ error);
+ g_error_free (error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ free_unmount_and_lock_op (data);
+ }
+ else
+ {
+ /* move on to the next encrypted.. */
+ unmount_and_lock_do (data);
+ }
+ g_object_unref (encrypted);
+}
+
+static void
+unmount_and_lock (GVfsUDisks2Drive *drive,
+ GMountUnmountFlags flags,
+ GMountOperation *mount_operation,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ UnmountAndLockFunc on_all_unmounted,
+ gpointer on_all_unmounted_data)
{
GMount *mount;
- UnmountMountsOp *data;
+ UnmountAndLockOp *data;
GList *l;
+ GSimpleAsyncResult *simple;
- data = g_new0 (UnmountMountsOp, 1);
+ data = g_new0 (UnmountAndLockOp, 1);
data->drive = g_object_ref (drive);
data->mount_operation = mount_operation;
data->cancellable = cancellable;
@@ -659,11 +712,62 @@ unmount_mounts (GVfsUDisks2Drive *drive,
{
GVfsUDisks2Volume *volume = GVFS_UDISKS2_VOLUME (l->data);
mount = g_volume_get_mount (G_VOLUME (volume));
- if (mount != NULL && g_mount_can_unmount (mount))
- data->pending_mounts = g_list_prepend (data->pending_mounts, g_object_ref (mount));
+ if (mount != NULL)
+ {
+ if (g_mount_can_unmount (mount))
+ data->pending_mounts = g_list_prepend (data->pending_mounts, g_object_ref (mount));
+ }
+ else
+ {
+ UDisksBlock *block;
+
+ block = gvfs_udisks2_volume_get_block (G_VOLUME (volume));
+ if (block != NULL)
+ {
+ UDisksEncrypted *encrypted;
+ GDBusObject *object;
+
+ object = g_dbus_interface_get_object (G_DBUS_INTERFACE (block));
+ if (object == NULL)
+ {
+ simple = g_simple_async_result_new_error (G_OBJECT (data->drive),
+ data->callback,
+ data->user_data,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "No object for D-Bus interface");
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+
+ free_unmount_and_lock_op (data);
+ goto out;
+ }
+
+ encrypted = udisks_object_get_encrypted (UDISKS_OBJECT (object));
+ if (encrypted != NULL)
+ {
+ UDisksBlock *cleartext_block;
+ UDisksClient *client;
+
+ client = gvfs_udisks2_volume_monitor_get_udisks_client (drive->monitor);
+ cleartext_block = udisks_client_get_cleartext_block (client, block);
+ if (cleartext_block != NULL)
+ {
+ data->pending_encrypted = g_list_prepend (data->pending_encrypted,
+ g_object_ref (encrypted));
+ g_object_unref (cleartext_block);
+ }
+
+ g_object_unref (encrypted);
+ }
+ }
+ }
}
- unmount_mounts_do (data);
+ unmount_and_lock_do (data);
+
+ out:
+ ;
}
/* ---------------------------------------------------------------------------------------------------- */
@@ -770,14 +874,14 @@ gvfs_udisks2_drive_eject_with_operation (GDrive *_drive,
}
/* first we need to go through all the volumes and unmount their assoicated mounts (if any) */
- unmount_mounts (drive,
- flags,
- mount_operation,
- cancellable,
- callback,
- user_data,
- gvfs_udisks2_drive_eject_on_all_unmounted,
- NULL);
+ unmount_and_lock (drive,
+ flags,
+ mount_operation,
+ cancellable,
+ callback,
+ user_data,
+ gvfs_udisks2_drive_eject_on_all_unmounted,
+ NULL);
}
static gboolean
@@ -912,14 +1016,14 @@ gvfs_udisks2_drive_stop (GDrive *_drive,
}
/* first we need to go through all the volumes and unmount their assoicated mounts (if any) */
- unmount_mounts (drive,
- flags,
- mount_operation,
- cancellable,
- callback,
- user_data,
- gvfs_udisks2_drive_stop_on_all_unmounted,
- NULL);
+ unmount_and_lock (drive,
+ flags,
+ mount_operation,
+ cancellable,
+ callback,
+ user_data,
+ gvfs_udisks2_drive_stop_on_all_unmounted,
+ NULL);
}
static gboolean
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]