Shared CD-Rom Support
PATCH 1/1 Shared CD-Rom Support
This patch adds a QEMU monitor command may switch the domain owning the physical 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 CD-Rom)
NOTE: This was also submitted to the Xen list, with a couple additional xen-specific changes, that are not necessarily applicable here (xenstore entries, etc)
Signed-off-by Ben Guthro <[email protected]>
Signed-off-by Joshua Nicholas <[email protected]>
block.c +83 -4
@@ -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[PATH_MAX ]; +int is_media_inserted;char backing_filename[PATH_MAX ]; 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, conreturn -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 _WIN32if (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 ; } }
@@ -749,6 +786,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) {
@@ -765,6 +824,16 @@ int bdrv_get_translation_hint(BlockDriveint 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)
@@ -849,6 +918,11 @@ const char *bdrv_get_device_name(BlockDrconst 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)
@@ -1226,6 +1300,11 @@ static int bdrv_write_em(BlockDriverStatreturn async_ret; } +static BlockDriver *get_bdrv_raw (void ) +{ +return &bdrv_raw ; +} +void bdrv_init (void ) {bdrv_register (&bdrv_raw);
block_int.h +2 -0
@@ -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;
hw/ide.c +212 -2
275 lines not on this page · raw message
monitor.c +36 -0
@@ -192,6 +192,40 @@ static void help_cmd(const char *name) } } } +} + +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_help (const char *name)
@@ -1250,6 +1284,8 @@ static term_cmd_t term_cmds[] = { "tag|id", "save a VM snapshot. If no tag or id are provided, a new snapshot is created" }, {"loadvm" ,"s" , do_loadvm, "tag|id", "restore a VM snapshot from its tag or id" }, + { "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" }, { "delvm", "s", do_delvm, "tag|id", "delete a VM snapshot from its tag or id" }, { "stop", "", do_stop,
vl.c +5 -0
@@ -7110,6 +7110,7 @@ enum { QEMU_OPTION_hdc, QEMU_OPTION_hdd, QEMU_OPTION_cdrom, + QEMU_OPTION_cdrom_shared_with_eject, QEMU_OPTION_mtdblock, QEMU_OPTION_sd, QEMU_OPTION_pflash,
@@ -7197,6 +7198,7 @@ const QEMUOption qemu_options[] = { { "hdc", HAS_ARG, QEMU_OPTION_hdc }, { "hdd", HAS_ARG, QEMU_OPTION_hdd }, { "cdrom", HAS_ARG, QEMU_OPTION_cdrom }, + { "cdrom-shared-with-eject", 0, QEMU_OPTION_cdrom_shared_with_eject }, { "mtdblock", HAS_ARG, QEMU_OPTION_mtdblock }, { "sd", HAS_ARG, QEMU_OPTION_sd }, { "pflash", HAS_ARG, QEMU_OPTION_pflash },
@@ -7778,6 +7780,9 @@ int main(int argc, char **argv) hd_filename[cdrom_index] = optarg; }break ; +case QEMU_OPTION_cdrom_shared_with_eject: +// XXX Temporarily ignore this option +break ;case QEMU_OPTION_boot: boot_device = optarg[0 ]; if (boot_device != 'a' &&
vl.h +5 -0
@@ -661,10 +661,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);
@@ -683,6 +687,7 @@ void bdrv_iterate_format(void (*it)(voidvoid 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);