WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH][QEMU] Shared CD-Rom Support

In response to the cdrom discussion going on today:

Attached is a port of a patch we have against 3.1

This patch plumbs the cdrom info through QEMU such that a QEMU monitor command may switch the domain owning the physiical cdrom, such that an eject command on the guest command line will physically eject the drive door.

Monitor command example:
set_cdrom_owner 1 hdd
(for the time being the "hdd" parameter is a constant, as we only support a singular CDRom)

Signed-off-by: Ben Guthro <bguthro@xxxxxxxxxxxxxxx>
Signed-off-by: Joshua Nicholas <jnicholas@xxxxxxxxxxxxxxx>


diff -r 7953164cebb6 tools/ioemu/block.c
--- a/tools/ioemu/block.c       Tue Aug 07 09:07:29 2007 +0100
+++ b/tools/ioemu/block.c       Thu Aug 16 15:49:49 2007 -0400
@@ -56,6 +56,8 @@ static BlockDriverState *bdrv_first;
 static BlockDriverState *bdrv_first;
 static BlockDriver *first_drv;
 
+static BlockDriver *get_bdrv_raw(void);
+
 int path_is_absolute(const char *path)
 {
     const char *p;
@@ -323,6 +325,7 @@ int bdrv_open2(BlockDriverState *bs, con
 {
     int ret, open_flags;
     char tmp_filename[1024];
+    int is_media_inserted;
     char backing_filename[1024];
     
     bs->read_only = 0;
@@ -359,6 +362,10 @@ int bdrv_open2(BlockDriverState *bs, con
     }
 
     pstrcpy(bs->filename, sizeof(bs->filename), filename);
+    if (bs->type == BDRV_TYPE_CDROM && !drv && bs->is_shared) {
+        drv = get_bdrv_raw();
+    }else{
+
     if (flags & BDRV_O_FILE) {
         drv = find_protocol(filename);
         if (!drv)
@@ -370,16 +377,27 @@ int bdrv_open2(BlockDriverState *bs, con
                 return -1;
         }
     }
+
+    }
     bs->drv = drv;
     bs->opaque = qemu_mallocz(drv->instance_size);
     if (bs->opaque == NULL && drv->instance_size > 0)
         return -1;
+    is_media_inserted = 1;
     /* Note: for compatibility, we open disk image files as RDWR, and
        RDONLY as fallback */
     if (!(flags & BDRV_O_FILE))
         open_flags = BDRV_O_RDWR;
     else
         open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
+
+    if (bs->type == BDRV_TYPE_CDROM && bs->is_shared) {
+        if (!bs->is_owner) {
+            bs->total_sectors = 0;
+            return ENOMEDIUM;
+        }
+    }
+
     ret = drv->bdrv_open(bs, filename, open_flags);
     if (ret == -EACCES && !(flags & BDRV_O_FILE)) {
         ret = drv->bdrv_open(bs, filename, BDRV_O_RDONLY);
@@ -391,6 +409,20 @@ int bdrv_open2(BlockDriverState *bs, con
         bs->drv = NULL;
         return ret;
     }
+
+    if (bs->type == BDRV_TYPE_CDROM && ret < 1) {
+        if (!bs->is_owner) {
+            bs->total_sectors = 0;
+            if (errno == ENOMEDIUM )
+                return ENOMEDIUM;
+            else
+                return -1;
+        }
+    }
+
+    if (bs->type == BDRV_TYPE_CDROM && ret == ENOMEDIUM)
+        is_media_inserted = 0;
+
     if (drv->bdrv_getlength) {
         bs->total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
     }
@@ -413,8 +445,12 @@ int bdrv_open2(BlockDriverState *bs, con
             goto fail;
     }
 
+    if (is_media_inserted)
+        bs->media_changed = 1;
+    else
+        bs->media_changed = 0;
+
     /* call the change callback */
-    bs->media_changed = 1;
     if (bs->change_cb)
         bs->change_cb(bs->change_opaque);
 
@@ -427,19 +463,20 @@ void bdrv_close(BlockDriverState *bs)
         if (bs->backing_hd)
             bdrv_delete(bs->backing_hd);
         bs->drv->bdrv_close(bs);
-        qemu_free(bs->opaque);
+        bs->drv = NULL;
 #ifdef _WIN32
         if (bs->is_temporary) {
             unlink(bs->filename);
         }
 #endif
-        bs->opaque = NULL;
-        bs->drv = NULL;
 
         /* call the change callback */
         bs->media_changed = 1;
         if (bs->change_cb)
             bs->change_cb(bs->change_opaque);
+ 
+        qemu_free(bs->opaque);
+        bs->opaque = NULL;
     }
 }
 
@@ -754,6 +791,28 @@ void bdrv_set_translation_hint(BlockDriv
     bs->translation = translation;
 }
 
+void bdrv_set_shared_owner_hint(BlockDriverState *bs, int is_owner)
+{
+    bs->is_shared = 1;
+    bs->is_owner = is_owner;
+}
+
+void bdrv_change_shared_owner(BlockDriverState *bs, int new_owner_state)
+{
+    if (!bs->is_shared)
+        return;
+
+    if (bs->is_owner == new_owner_state)
+        return;
+
+    bs->is_owner = new_owner_state;
+
+    if (!new_owner_state) {
+        bdrv_close(bs);
+        return;
+    }
+}
+
 void bdrv_get_geometry_hint(BlockDriverState *bs, 
                             int *pcyls, int *pheads, int *psecs)
 {
@@ -770,6 +829,16 @@ int bdrv_get_translation_hint(BlockDrive
 int bdrv_get_translation_hint(BlockDriverState *bs)
 {
     return bs->translation;
+}
+
+int bdrv_is_shared(BlockDriverState *bs)
+{
+    return bs->is_shared;
+}
+
+int bdrv_is_owner(BlockDriverState *bs)
+{
+    return bs->is_owner;
 }
 
 int bdrv_is_removable(BlockDriverState *bs)
@@ -854,6 +923,11 @@ const char *bdrv_get_device_name(BlockDr
 const char *bdrv_get_device_name(BlockDriverState *bs)
 {
     return bs->device_name;
+}
+
+const char *bdrv_get_filename(BlockDriverState *bs)
+{
+    return bs->filename;
 }
 
 void bdrv_flush(BlockDriverState *bs)
@@ -1231,6 +1305,11 @@ static int bdrv_write_em(BlockDriverStat
     return async_ret;
 }
 
+static BlockDriver *get_bdrv_raw(void)
+{
+    return &bdrv_raw ;
+}
+
 void bdrv_init(void)
 {
     bdrv_register(&bdrv_raw);
diff -r 7953164cebb6 tools/ioemu/block_int.h
--- a/tools/ioemu/block_int.h   Tue Aug 07 09:07:29 2007 +0100
+++ b/tools/ioemu/block_int.h   Thu Aug 16 15:49:49 2007 -0400
@@ -87,6 +87,8 @@ struct BlockDriverState {
     int removable; /* if true, the media can be removed */
     int locked;    /* if true, the media cannot temporarily be ejected */
     int encrypted; /* if true, the media is encrypted */
+    int is_shared; /* if true, the media is shared across multiple QEMU 
instances */
+    int is_owner;  /* if true, the media is sharable and currently owned by 
this QEMU instance */
     /* event callback when inserting/removing */
     void (*change_cb)(void *opaque);
     void *change_opaque;
diff -r 7953164cebb6 tools/ioemu/hw/ide.c
--- a/tools/ioemu/hw/ide.c      Tue Aug 07 09:07:29 2007 +0100
+++ b/tools/ioemu/hw/ide.c      Thu Aug 16 15:49:49 2007 -0400
@@ -23,11 +23,25 @@
  */
 #include "vl.h"
 
+#include <linux/cdrom.h>
+#include <linux/fs.h>
+#include <scsi/sg.h>
+#include <scsi/scsi.h>
+#include <sys/ioctl.h>
+
 /* debug IDE devices */
 //#define DEBUG_IDE
 //#define DEBUG_IDE_ATAPI
 //#define DEBUG_AIO
 #define USE_DMA_CDROM
+
+#define DEBUG_CDROM
+#ifdef  DEBUG_CDROM
+#include "exec-all.h"   // for FILE* logfile
+#define DEBUG_CDROM_PRINT( formatCstr, args... ) fprintf( logfile, formatCstr, 
##args ); fflush( logfile )
+#else
+#define DEBUG_CDROM_PRINT( formatCstr, args... )
+#endif
 
 /* Bits of HD_STATUS */
 #define ERR_STAT               0x01
@@ -295,6 +309,7 @@ typedef struct IDEState {
 typedef struct IDEState {
     /* ide config */
     int is_cdrom;
+    int is_physical_media_present;
     int cylinders, heads, sectors;
     int64_t nb_sectors;
     int mult_sectors;
@@ -1081,7 +1096,11 @@ static int cd_read_sector(BlockDriverSta
                            int sector_size)
 {
     int ret;
-
+    if (bdrv_is_shared(bs) && !bdrv_is_owner(bs)) {
+        DEBUG_CDROM_PRINT("CDrom : own : cd_read_sector(%d %ld %d) not owner = 
ignored | fn: %s devN: %s\n", lba, (long)((int64_t)lba << 2), sector_size, 
bdrv_get_filename(bs), bdrv_get_device_name(bs));
+        memset(buf, -1, sector_size); // Make sure the data looks bad
+        return;
+    }
     switch(sector_size) {
     case 2048:
         ret = bdrv_read(bs, (int64_t)lba << 2, buf, 4);
@@ -1322,6 +1341,12 @@ static void ide_atapi_cmd_read(IDEState 
     printf("read %s: LBA=%d nb_sectors=%d\n", s->atapi_dma ? "dma" : "pio",
        lba, nb_sectors);
 #endif
+    if (s->is_cdrom && bdrv_is_shared(s->bs) && !bdrv_is_owner(s->bs)) {
+        DEBUG_CDROM_PRINT("CDrom : own : ide_atapi_cmd_read() not owner = 
request denied | fn: %s devN: %s\n", bdrv_get_filename(s->bs), 
bdrv_get_device_name(s->bs));
+        ide_atapi_cmd_error(s, SENSE_NOT_READY, 
+                            ASC_MEDIUM_NOT_PRESENT);
+        return;
+    }
     if (s->atapi_dma) {
         ide_atapi_cmd_read_dma(s, lba, nb_sectors, sector_size);
     } else {
@@ -1329,11 +1354,160 @@ static void ide_atapi_cmd_read(IDEState 
     }
 }
 
+static void unlock_physical_cdrom_door(const char* filename)
+{
+    int status;
+    int cdrom_fd;
+
+       cdrom_fd = open(filename, O_RDONLY | O_NONBLOCK);
+       if (cdrom_fd >= 0) {
+               status = ioctl(cdrom_fd, CDROM_LOCKDOOR, 0); // Always unlock 
the door regardless of ownership
+               if (status < 0)
+                       DEBUG_CDROM_PRINT( "CDrom : %s : ERROR? : could NOT 
unlock CD door : %s : %d %s\n", __FUNCTION__, filename, errno, strerror(errno));
+               close(cdrom_fd);
+       } else {
+               DEBUG_CDROM_PRINT("CDrom : %s : open(%s) failed : door NOT 
unlocked : %d %s\n", __FUNCTION__, filename, errno, strerror(errno));
+       }
+}
+
+/* Eject using SCSI SG_IO commands. Return 1 if successful, 0 otherwise. From 
/usr/bin/eject sources */
+static int perform_physical_cdrom_eject_via_scsi(int fd)
+{
+    int status, k;
+    sg_io_hdr_t io_hdr;
+    unsigned char allowRmBlk[6] = {ALLOW_MEDIUM_REMOVAL, 0, 0, 0, 0, 0};
+    unsigned char startStop1Blk[6] = {START_STOP, 0, 0, 0, 1, 0};
+    unsigned char startStop2Blk[6] = {START_STOP, 0, 0, 0, 2, 0};
+    unsigned char inqBuff[2];
+    unsigned char sense_buffer[32];
+
+    if ((ioctl(fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) {
+        return ENODEV;    // not an sg device, or old sg driver
+    }
+
+    memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
+    io_hdr.interface_id = 'S';
+    io_hdr.cmd_len = 6;
+    io_hdr.mx_sb_len = sizeof(sense_buffer);
+    io_hdr.dxfer_direction = SG_DXFER_NONE;
+    io_hdr.dxfer_len = 0;
+    io_hdr.dxferp = inqBuff;
+    io_hdr.sbp = sense_buffer;
+    io_hdr.timeout = 2000;
+
+    io_hdr.cmdp = allowRmBlk;
+    status = ioctl(fd, SG_IO, (void *)&io_hdr);
+    if (status < 0)
+        return ((errno)?errno:status);
+
+    io_hdr.cmdp = startStop1Blk;
+    status = ioctl(fd, SG_IO, (void *)&io_hdr);
+    if (status < 0)
+        return ((errno)?errno:status);
+
+    io_hdr.cmdp = startStop2Blk;
+    status = ioctl(fd, SG_IO, (void *)&io_hdr);
+    if (status < 0)
+        return ((errno)?errno:status);
+
+    /* force kernel to reread partition table when new disc inserted */
+    status = ioctl(fd, BLKRRPART);
+    return 0;
+}
+
+static int perform_physical_cdrom_eject(const char* filename)
+{
+    int status;
+    int cdrom_fd;
+
+    status = 1;
+    cdrom_fd = open(filename, O_RDONLY | O_NONBLOCK);
+    if ( cdrom_fd >= 0 ) {
+        status = ioctl(cdrom_fd, CDROMEJECT, CDSL_CURRENT); // bdrv MUST be 
closed
+        if (status < 0) { // NOTE: ioctl fails when door is open
+            DEBUG_CDROM_PRINT("CDrom : ej : ioctl(%s, CDROMEJECT,CDSL_CURRENT) 
failed %d, trying eject_cdrom_via_scsi()\n", filename, errno);
+            status = perform_physical_cdrom_eject_via_scsi(cdrom_fd); // last 
resort
+        }
+        close(cdrom_fd);
+    }
+
+    return status;
+}
+
+static int is_cdrom_physical_media_present(const char* filename)
+{
+    int status;
+    int cdrom_fd;
+
+    cdrom_fd = open(filename, O_RDONLY | O_NONBLOCK); // O_NONBLOCK ignores 
ENOMEDIUM
+    if (cdrom_fd >= 0) {
+        status = ioctl(cdrom_fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
+        if (status >= 0) {
+            if (status == CDS_DISC_OK) {
+                if (  ioctl(cdrom_fd, CDROM_MEDIA_CHANGED, CDSL_CURRENT) == 0 
// trick to
+                   || ioctl(cdrom_fd, CDROM_MEDIA_CHANGED, CDSL_CURRENT) == 0 
// verify media
+                   ) {
+                    close(cdrom_fd);
+                    return 1;
+                }
+            }
+        } else {
+            DEBUG_CDROM_PRINT("CDrom : %s : ioctl(%s, CDROM_MEDIA_CHANGED) 
failed %d %s\n", __FUNCTION__, filename, errno, strerror(errno));
+        }
+    } else {
+        DEBUG_CDROM_PRINT("CDrom : %s : open(%s, O_RDONLY|O_NONBLOCK) failed 
%d %s\n", __FUNCTION__, filename, errno, strerror(errno));
+    }
+
+    close(cdrom_fd);
+    return 0;
+}
+
+static int ascertain_is_media_present(IDEState *s)
+{
+    int is_physical_media_present_now;
+
+    if (!s->is_cdrom || !bdrv_is_shared(s->bs)) {
+        if (bdrv_is_inserted(s->bs))
+            return 1;
+        return 0;
+    }
+    if (!bdrv_is_owner(s->bs))
+        return 0;
+
+    is_physical_media_present_now = 
is_cdrom_physical_media_present(bdrv_get_filename(s->bs));
+    if (is_physical_media_present_now) {
+        if (s->is_physical_media_present) {
+//          DEBUG_CDROM_PRINT("CDrom : present : media still inserted | fn: %s 
devN: %s\n", bdrv_get_filename(s->bs), bdrv_get_device_name(s->bs));
+            return 1;
+        }
+        s->is_physical_media_present = 1;
+
+        if (!bdrv_is_inserted(s->bs))
+            bdrv_open(s->bs, bdrv_get_filename(s->bs), 0);
+        unlock_physical_cdrom_door(bdrv_get_filename(s->bs));
+
+        DEBUG_CDROM_PRINT("CDrom : present : media inserted | fn: %s devN: 
%s\n", bdrv_get_filename(s->bs), bdrv_get_device_name(s->bs));
+        return -1;
+    }
+
+    if (!s->is_physical_media_present) {
+//      DEBUG_CDROM_PRINT("CDrom : present : media is still NOT inserted | fn: 
%s devN: %s\n", bdrv_get_filename(s->bs), bdrv_get_device_name(s->bs));
+        return 0;
+    }
+    s->is_physical_media_present = 0;
+
+    bdrv_close(s->bs);
+
+    DEBUG_CDROM_PRINT("CDrom : present : media is NOT inserted | fn: %s devN: 
%s\n", bdrv_get_filename(s->bs), bdrv_get_device_name(s->bs));
+    return 0;
+}
+
 static void ide_atapi_cmd(IDEState *s)
 {
     const uint8_t *packet;
     uint8_t *buf;
     int max_len;
+    int is_media_present;
 
     packet = s->io_buffer;
     buf = s->io_buffer;
@@ -1349,12 +1523,19 @@ static void ide_atapi_cmd(IDEState *s)
 #endif
     switch(s->io_buffer[0]) {
     case GPCMD_TEST_UNIT_READY:
-        if (bdrv_is_inserted(s->bs)) {
-            ide_atapi_cmd_ok(s);
+        is_media_present = ascertain_is_media_present(s);
+        if (is_media_present) {
+            if (is_media_present > 0)
+                ide_atapi_cmd_ok(s);
+            else {
+                DEBUG_CDROM_PRINT("CDrom : present : GPCMD_TEST_UNIT_READY : 
was_inserted %s : SENSE_UNIT_ATTENTION !\n", bdrv_get_device_name(s->bs));
+                ide_atapi_cmd_error(s, SENSE_UNIT_ATTENTION, 0);
+            }
         } else {
             ide_atapi_cmd_error(s, SENSE_NOT_READY, 
                                 ASC_MEDIUM_NOT_PRESENT);
-            xenstore_check_new_media_present(1000);
+            if (!s->is_cdrom || !bdrv_is_shared(s->bs)) // Prevent timer 
initiated open() as it closes physical cdrom drive door
+                xenstore_check_new_media_present(1000);
         }
         break;
     case GPCMD_MODE_SENSE_10:
@@ -1527,7 +1708,16 @@ static void ide_atapi_cmd(IDEState *s)
             
             if (eject && !start) {
                 /* eject the disk */
-                bdrv_eject(s->bs, 1);
+                bdrv_close(s->bs); // close the device ( allows for eject AND 
flushes system cache )
+                if (bdrv_is_shared(s->bs) && bdrv_is_owner(s->bs)) {
+                    if (perform_physical_cdrom_eject(bdrv_get_filename(s->bs)) 
== 0) {
+                        s->is_physical_media_present = 0;
+                        DEBUG_CDROM_PRINT("CDrom : ej : sucesss | fn: %s devN: 
%s\n", bdrv_get_filename(s->bs), bdrv_get_device_name(s->bs));
+                    } else {
+                        DEBUG_CDROM_PRINT("CDrom : ej : FAILED | fn: %s devN: 
%s\n", bdrv_get_filename(s->bs), bdrv_get_device_name(s->bs));
+                    }
+                }
+
             } else if (eject && start) {
                 /* close the tray */
                 bdrv_eject(s->bs, 0);
@@ -1637,9 +1827,31 @@ static void cdrom_change_cb(void *opaque
 {
     IDEState *s = opaque;
     int64_t nb_sectors;
+    int cylinders;
+
+    if (bdrv_is_shared(s->bs) && !bdrv_is_owner(s->bs)) {
+        s->is_physical_media_present = 0;
+        return;
+    }
+    if (!bdrv_is_inserted(s->bs))
+        return;
 
     /* XXX: send interrupt too */
     bdrv_get_geometry(s->bs, &nb_sectors);
+
+    /* if no geometry, use a standard physical disk geometry */
+    cylinders = nb_sectors / (16 * 63);
+    if (cylinders > 16383)
+        cylinders = 16383;
+    else if (cylinders < 2)
+        cylinders = 2;
+    s->cylinders = cylinders;
+    s->heads = 16;
+    s->sectors = 63;
+    bdrv_set_geometry_hint(s->bs, s->cylinders, s->heads, s->sectors); // 
Reset the geometry in case the media changed
+
+    DEBUG_CDROM_PRINT("CDrom : geometry change %ld [ %ld ] %d %d %d | fn: %s 
devN: %s\n", (long)nb_sectors, (long)s->nb_sectors, s->cylinders, s->heads, 
s->sectors, bdrv_get_filename(s->bs), bdrv_get_device_name(s->bs));
+
     s->nb_sectors = nb_sectors;
 }
 
@@ -2298,6 +2510,11 @@ static void ide_init2(IDEState *ide_stat
             if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
                 s->is_cdrom = 1;
                bdrv_set_change_cb(s->bs, cdrom_change_cb, s);
+                if (bdrv_is_shared(s->bs)) {
+                    unlock_physical_cdrom_door(bdrv_get_filename(s->bs));
+                    DEBUG_CDROM_PRINT("CDrom : init : geometry [ %ld ] %d %d 
%d | fn: %s devN: %s\n", (long)s->nb_sectors, s->cylinders, s->heads, 
s->sectors, bdrv_get_filename(s->bs), bdrv_get_device_name(s->bs));
+                }
+
             }
         }
         s->drive_serial = drive_serial++;
diff -r 7953164cebb6 tools/ioemu/monitor.c
--- a/tools/ioemu/monitor.c     Tue Aug 07 09:07:29 2007 +0100
+++ b/tools/ioemu/monitor.c     Thu Aug 16 15:49:49 2007 -0400
@@ -397,6 +397,40 @@ void do_change(const char *device, const
             term_printf("invalid password\n");
         }
     }
+}
+
+static void do_set_cdrom_owner(const char* new_owner_state_cstr, const char 
*device)
+{
+    BlockDriverState *bs;
+    int new_owner_state;
+
+    if (!new_owner_state_cstr || !device) {
+        term_printf("[set_cdrom_owner] ERROR : insufficient args (NULL) 
!?!\n");
+        return;
+    }
+
+    if (sscanf(new_owner_state_cstr, "%d", &new_owner_state) != 1) {
+        term_printf("[set_cdrom_owner] ERROR : bad arg '%s'\n", 
new_owner_state_cstr);
+        return;
+    }
+
+    if (new_owner_state)    // normalize given input
+        new_owner_state = 1;
+
+    bs = bdrv_find(device);
+    if (!bs) {
+        term_printf("[set_cdrom_owner] ERROR : cdrom device '%s' not found 
%d\n", device, new_owner_state);
+        return;
+    }
+
+    if (bdrv_is_owner(bs) == new_owner_state) {
+        term_printf("[set_cdrom_owner] IGNORED : no change to ownership %d\n", 
new_owner_state);
+        return;
+    }
+
+    bdrv_change_shared_owner(bs, new_owner_state);
+
+    term_printf("[set_cdrom_owner] done : (%d)\n", new_owner_state);
 }
 
 static void do_screen_dump(const char *filename)
@@ -1217,7 +1251,10 @@ static term_cmd_t term_cmds[] = {
       "filename", "save screen into PPM image 'filename'" },
     { "log", "s", do_log,
       "item1[,...]", "activate logging of the specified items to 
'/tmp/qemu.log'" }, 
-#ifndef CONFIG_DM
+#ifdef CONFIG_DM
+    { "set_cdrom_owner", "sB", do_set_cdrom_owner,
+      "<1|0> device", "1 to become the owner and acquire the physical drive or 
0 to release it and no longer be the owner" },
+#else
     { "savevm", "s?", do_savevm,
       "tag|id", "save a VM snapshot. If no tag or id are provided, a new 
snapshot is created" }, 
     { "loadvm", "s", do_loadvm,
diff -r 7953164cebb6 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c  Tue Aug 07 09:07:29 2007 +0100
+++ b/tools/ioemu/vl.c  Thu Aug 16 15:49:49 2007 -0400
@@ -6436,6 +6436,7 @@ enum {
     QEMU_OPTION_hdd,
     QEMU_OPTION_cdrom,
 #endif /* !CONFIG_DM */
+    QEMU_OPTION_cdrom_shared_with_eject,
     QEMU_OPTION_boot,
     QEMU_OPTION_snapshot,
 #ifdef TARGET_I386
@@ -6519,6 +6520,7 @@ const QEMUOption qemu_options[] = {
     { "hdd", HAS_ARG, QEMU_OPTION_hdd },
     { "cdrom", HAS_ARG, QEMU_OPTION_cdrom },
 #endif /* !CONFIG_DM */
+    { "cdrom-shared-with-eject", 0, QEMU_OPTION_cdrom_shared_with_eject },
     { "boot", HAS_ARG, QEMU_OPTION_boot },
     { "snapshot", 0, QEMU_OPTION_snapshot },
 #ifdef TARGET_I386
@@ -7279,6 +7281,9 @@ int main(int argc, char **argv)
                 }
                 break;
 #endif /* !CONFIG_DM */
+            case QEMU_OPTION_cdrom_shared_with_eject:
+               // XXX Temporarily ignore this option
+               break;
             case QEMU_OPTION_boot:
                 boot_device = strdup(optarg);
                 if (strspn(boot_device, "a"
diff -r 7953164cebb6 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h  Tue Aug 07 09:07:29 2007 +0100
+++ b/tools/ioemu/vl.h  Thu Aug 16 15:49:49 2007 -0400
@@ -678,10 +678,14 @@ void bdrv_set_geometry_hint(BlockDriverS
                             int cyls, int heads, int secs);
 void bdrv_set_type_hint(BlockDriverState *bs, int type);
 void bdrv_set_translation_hint(BlockDriverState *bs, int translation);
+void bdrv_set_shared_owner_hint(BlockDriverState *bs, int is_owner);
+void bdrv_change_shared_owner(BlockDriverState *bs, int new_owner_state);
 void bdrv_get_geometry_hint(BlockDriverState *bs, 
                             int *pcyls, int *pheads, int *psecs);
 int bdrv_get_type_hint(BlockDriverState *bs);
 int bdrv_get_translation_hint(BlockDriverState *bs);
+int bdrv_is_shared(BlockDriverState *bs);
+int bdrv_is_owner(BlockDriverState *bs);
 int bdrv_is_removable(BlockDriverState *bs);
 int bdrv_is_read_only(BlockDriverState *bs);
 int bdrv_is_inserted(BlockDriverState *bs);
@@ -700,6 +704,7 @@ void bdrv_iterate_format(void (*it)(void
 void bdrv_iterate_format(void (*it)(void *opaque, const char *name), 
                          void *opaque);
 const char *bdrv_get_device_name(BlockDriverState *bs);
+const char *bdrv_get_filename(BlockDriverState *bs);
 int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num, 
                           const uint8_t *buf, int nb_sectors);
 int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
diff -r 7953164cebb6 tools/ioemu/xenstore.c
--- a/tools/ioemu/xenstore.c    Tue Aug 07 09:07:29 2007 +0100
+++ b/tools/ioemu/xenstore.c    Thu Aug 16 15:56:02 2007 -0400
@@ -85,6 +85,7 @@ void xenstore_parse_domain_config(int do
         *dev = NULL, *params = NULL, *type = NULL;
     int i, is_scsi;
     unsigned int len, num, hd_index;
+    int is_cdrom_shared_with_eject, is_cdrom_owner;
 
     for(i = 0; i < MAX_DISKS + MAX_SCSI_DISKS; i++)
         media_filename[i] = NULL;
@@ -166,10 +167,29 @@ void xenstore_parse_domain_config(int do
 
         bs_table[hd_index + (is_scsi ? MAX_DISKS : 0)] = bdrv_new(dev);
         /* check if it is a cdrom */
-        if (type && !strcmp(type, "cdrom")) {
+       if (type && !strcmp(type, "cdrom")) {
+             is_cdrom_shared_with_eject = is_cdrom_owner = 0;
+             /* read the cdrom param is_cdrom_shared_with_eject (if any) */
+             if (pasprintf(&buf, "%s/device/vbd/%s/cdrom-shared-witheject", 
path, e[i]) == -1)
+                 continue;
+             free(type);
+             type = xs_read(xsh, XBT_NULL, buf, &len);
+             if (type != NULL)
+                 is_cdrom_shared_with_eject = (atoi(type))?1:0;
+             /* read the cdrom param is_cdrom_shared_with_eject (if any) */
+             if (pasprintf(&buf, "%s/device/vbd/%s/cdrom-owner", path, e[i]) 
== -1)
+                 continue;
+             free(type);
+             type = xs_read(xsh, XBT_NULL, buf, &len);
+             if (type != NULL)
+                 is_cdrom_owner = (atoi(type))?1:0;
+             /* indicate that this device is a cdrom */
             bdrv_set_type_hint(bs_table[hd_index], BDRV_TYPE_CDROM);
-            if (pasprintf(&buf, "%s/params", bpath) != -1)
-                xs_watch(xsh, buf, dev);
+             if (is_cdrom_shared_with_eject)
+                 bdrv_set_shared_owner_hint(bs_table[hd_index], 
is_cdrom_owner);
+
+             if (pasprintf(&buf, "%s/params", bpath) != -1)
+                  xs_watch(xsh, buf, dev);
         }
         /* open device now if media present */
         if (params[0]) {
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel