qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 5/5] raw-posix: unmount CD-ROM filesystem via udisks


From: Paolo Bonzini
Subject: [Qemu-devel] [PATCH 5/5] raw-posix: unmount CD-ROM filesystem via udisks
Date: Wed, 8 Feb 2012 18:37:36 +0100

We need to use O_EXCL in order to suppress event generation in the
kernel.  However, O_EXCL by definition fails when the CD-ROM drive
is mounted.  Automatically unmount it when it is passed through to
the guest.

Signed-off-by: Paolo Bonzini <address@hidden>
---
 Makefile.objs            |    3 +
 block.c                  |    7 +++
 block/raw-posix-udisks.c |  105 ++++++++++++++++++++++++++++++++++++++++++++++
 block/raw-posix-udisks.h |   39 +++++++++++++++++
 block/raw-posix.c        |   17 ++++++-
 5 files changed, 168 insertions(+), 3 deletions(-)
 create mode 100644 block/raw-posix-udisks.c
 create mode 100644 block/raw-posix-udisks.h

diff --git a/Makefile.objs b/Makefile.objs
index ec35320..a30a80d 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -41,6 +41,9 @@ block-nested-$(CONFIG_POSIX) += raw-posix.o
 block-nested-$(CONFIG_LIBISCSI) += iscsi.o
 block-nested-$(CONFIG_CURL) += curl.o
 block-nested-$(CONFIG_RBD) += rbd.o
+ifeq ($(CONFIG_DBUS),y)
+block-nested-$(CONFIG_LINUX) += raw-posix-udisks.o
+endif
 
 block-obj-y +=  $(addprefix block/, $(block-nested-y))
 
diff --git a/block.c b/block.c
index 3621d11..6dad6b5 100644
--- a/block.c
+++ b/block.c
@@ -42,6 +42,10 @@
 #endif
 #endif
 
+#ifdef CONFIG_DBUS
+#include <glib-object.h>
+#endif
+
 #ifdef _WIN32
 #include <windows.h>
 #endif
@@ -3278,6 +3282,9 @@ BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs,
 void bdrv_init(void)
 {
     module_call_init(MODULE_INIT_BLOCK);
+#ifdef CONFIG_DBUS
+    g_type_init();
+#endif
 }
 
 void bdrv_init_with_whitelist(void)
diff --git a/block/raw-posix-udisks.c b/block/raw-posix-udisks.c
new file mode 100644
index 0000000..3ab3cbe
--- /dev/null
+++ b/block/raw-posix-udisks.c
@@ -0,0 +1,105 @@
+/*
+ * Udisks interaction for CD-ROM unmounting
+ *
+ * Copyright (c) 2012 Red Hat, Inc.
+ *
+ * Author: Paolo Bonzini  <address@hidden>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include "block/raw-posix-udisks.h"
+
+static void udisks_find_device_by_device_file(DBusGConnection *bus,
+                                              const char *path,
+                                              char **object_path,
+                                              GError **error)
+{
+    DBusGProxy *proxy;
+    proxy = dbus_g_proxy_new_for_name (bus, "org.freedesktop.UDisks",
+                                       "/org/freedesktop/UDisks",
+                                       "org.freedesktop.UDisks");
+    dbus_g_proxy_call (proxy, "FindDeviceByDeviceFile", error,
+                       G_TYPE_STRING, path, G_TYPE_INVALID,
+                       DBUS_TYPE_G_OBJECT_PATH, object_path, G_TYPE_INVALID);
+    g_object_unref (proxy);
+}
+
+static void udisks_device_filesystem_unmount(DBusGConnection *bus,
+                                             const char *object_path,
+                                             GError **error)
+{
+    DBusGProxy *proxy;
+    proxy = dbus_g_proxy_new_for_name (bus, "org.freedesktop.UDisks",
+                                       object_path,
+                                       "org.freedesktop.UDisks.Device");
+    dbus_g_proxy_call (proxy, "FilesystemUnmount", error,
+                       G_TYPE_STRV, NULL, G_TYPE_INVALID,
+                       G_TYPE_INVALID);
+    g_object_unref (proxy);
+}
+
+int
+udisks_unmount (const char *path)
+{
+    DBusGConnection *bus;
+    char *object_path;
+    GError *error;
+    int ret;
+
+    error = NULL;
+    bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+    if (bus == NULL) {
+        g_warning ("Couldn't connect to system bus: %s", error->message);
+        ret = -EACCES;
+        goto out;
+    }
+
+    udisks_find_device_by_device_file(bus, path, &object_path, &error);
+    if (error || !object_path) {
+        ret = -ENODEV;
+        goto out;
+    }
+
+    udisks_device_filesystem_unmount(bus, object_path, &error);
+    if (error) {
+        g_print ("Unmount failed: %s\n", error->message);
+        ret = -EBUSY;
+        goto out;
+      }
+
+    ret = 0; /* success */
+out:
+    g_free (object_path);
+    if (error != NULL) {
+        g_error_free (error);
+    }
+    if (bus != NULL) {
+        dbus_g_connection_unref (bus);
+    }
+    return ret;
+}
diff --git a/block/raw-posix-udisks.h b/block/raw-posix-udisks.h
new file mode 100644
index 0000000..47dd638
--- /dev/null
+++ b/block/raw-posix-udisks.h
@@ -0,0 +1,39 @@
+/*
+ * Udisks interaction for CD-ROM unmounting
+ *
+ * Copyright (c) 2012 Red Hat, Inc.
+ *
+ * Author: Paolo Bonzini  <address@hidden>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef QEMU_UDISKS_H
+#define QEMU_UDISKS_H 1
+
+#include "config-host.h"
+#include <errno.h>
+
+#ifdef CONFIG_DBUS
+int udisks_unmount (const char *path);
+#else
+static int udisks_unmount (const char *path) { return -ENOSYS; }
+#endif
+
+#endif
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 1b51bd4..c61d07a 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -28,6 +28,7 @@
 #include "block_int.h"
 #include "module.h"
 #include "block/raw-posix-aio.h"
+#include "block/raw-posix-udisks.h"
 
 #ifdef CONFIG_COCOA
 #include <paths.h>
@@ -1069,15 +1070,25 @@ static int cdrom_open(BlockDriverState *bs, const char 
*filename, int flags)
 {
     BDRVRawState *s = bs->opaque;
     int rc;
+    int i;
 
     s->type = FTYPE_CD;
 
     /* open will not fail even if no CD is inserted, so add O_NONBLOCK.  First
      * try with O_EXCL to see whether the CD is mounted.
      */
-    rc = raw_open_common(bs, filename, flags, O_NONBLOCK | O_EXCL);
-    if (rc < 0 && rc != -EBUSY) {
-        return rc;
+    for (i = 0; i < 20; i++) {
+        rc = raw_open_common(bs, filename, flags, O_NONBLOCK | O_EXCL);
+        if (rc == 0) {
+            break;
+        }
+        if (rc != -EBUSY) {
+            return rc;
+        }
+        if (i == 0 && udisks_unmount(filename) < 0) {
+            break;
+        }
+        usleep(100 * 1000);
     }
 
     s->cd.manage_door = false;
-- 
1.7.7.6




reply via email to

[Prev in Thread] Current Thread [Next in Thread]