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

[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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.