Patchwork [4/4] blockdev: Process -drive fd and opaque options

login
register
mail settings
Submitter Corey Bryant
Date Oct. 5, 2012, 6:07 p.m.
Message ID <1349460425-30601-5-git-send-email-coreyb@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/189560/
State New
Headers show

Comments

Corey Bryant - Oct. 5, 2012, 6:07 p.m.
When an fd, and optionally opaque, are passed with -drive, they
are added to an automatically generated fd set.  The file name
is also generated in the form of "/dev/fdset/nnn", where nnn is
the fd set ID.  qemu_open() already knows how to handle a
filename of this format.  qemu_open() searches the corresponding
fd set for an fd and when it finds a match, QEMU goes on to use a
dup of that fd just like it would have used an fd that it opened
itself.

Signed-off-by: Corey Bryant <coreyb@linux.vnet.ibm.com>
---
 blockdev.c | 40 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 38 insertions(+), 2 deletions(-)

Patch

diff --git a/blockdev.c b/blockdev.c
index 5f18dfa..cf348c6 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -281,6 +281,7 @@  DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
     const char *file = NULL;
     const char *serial;
     const char *mediastr = "";
+    const char *opaque = NULL;
     BlockInterfaceType type;
     enum { MEDIA_DISK, MEDIA_CDROM } media;
     int bus_id, unit_id;
@@ -297,6 +298,10 @@  DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
     int snapshot = 0;
     bool copy_on_read;
     int ret;
+    int fd;
+    char filename[32];
+    AddfdInfo *fdinfo = NULL;
+    Error *errp = NULL;
 
     translation = BIOS_ATA_TRANSLATION_AUTO;
     media = MEDIA_DISK;
@@ -315,6 +320,8 @@  DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
     copy_on_read = qemu_opt_get_bool(opts, "copy-on-read", false);
 
     file = qemu_opt_get(opts, "file");
+    fd = qemu_opt_get_number(opts, "fd", -1);
+    opaque = qemu_opt_get(opts, "opaque");
     serial = qemu_opt_get(opts, "serial");
 
     if ((buf = qemu_opt_get(opts, "if")) != NULL) {
@@ -575,9 +582,35 @@  DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
     default:
         abort();
     }
-    if (!file || !*file) {
-        return dinfo;
+
+    if (file && fd != -1) {
+        error_report("file cannot be used with fd");
+        goto err;
+    }
+
+    if (opaque && fd == -1) {
+        error_report("opaque cannot be specified without fd");
+        goto err;
+    }
+
+    if ((!file || !*file)) {
+        if (fd != -1) {
+            /* add the fd, and optionally opaque, to an fd set */
+            fdinfo = monitor_fdset_add_fd(fd, false, -1, opaque ? true : false,
+                                          opaque, &errp);
+            if (fdinfo == NULL) {
+                goto err;
+            }
+
+            /* set file name to /dev/fdset/nnn */
+            snprintf(filename, sizeof(filename), "/dev/fdset/%" PRId64,
+                     fdinfo->fdset_id);
+            file = filename;
+        } else {
+            return dinfo;
+        }
     }
+
     if (snapshot) {
         /* always use cache=unsafe with snapshot */
         bdrv_flags &= ~BDRV_O_CACHE_MASK;
@@ -625,6 +658,9 @@  err:
     g_free(dinfo->id);
     QTAILQ_REMOVE(&drives, dinfo, next);
     g_free(dinfo);
+    if (fdinfo) {
+        qmp_remove_fd(fdinfo->fdset_id, true, fdinfo->fd, &errp);
+    }
     return NULL;
 }