block: Allow error return in BlockDevOps.change_media_cb()
Some devices allow a media change between read-only and read-write media. They need to adapt the permissions in their .change_media_cb() implementation, which can fail. So add an Error parameter to the function. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Acked-by: Fam Zheng <famz@redhat.com>
This commit is contained in:
parent
c62d32f503
commit
39829a01ae
@ -677,19 +677,29 @@ void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops,
|
||||
|
||||
/*
|
||||
* Notify @blk's attached device model of media change.
|
||||
* If @load is true, notify of media load.
|
||||
* Else, notify of media eject.
|
||||
*
|
||||
* If @load is true, notify of media load. This action can fail, meaning that
|
||||
* the medium cannot be loaded. @errp is set then.
|
||||
*
|
||||
* If @load is false, notify of media eject. This can never fail.
|
||||
*
|
||||
* Also send DEVICE_TRAY_MOVED events as appropriate.
|
||||
*/
|
||||
void blk_dev_change_media_cb(BlockBackend *blk, bool load)
|
||||
void blk_dev_change_media_cb(BlockBackend *blk, bool load, Error **errp)
|
||||
{
|
||||
if (blk->dev_ops && blk->dev_ops->change_media_cb) {
|
||||
bool tray_was_open, tray_is_open;
|
||||
Error *local_err = NULL;
|
||||
|
||||
assert(!blk->legacy_dev);
|
||||
|
||||
tray_was_open = blk_dev_is_tray_open(blk);
|
||||
blk->dev_ops->change_media_cb(blk->dev_opaque, load);
|
||||
blk->dev_ops->change_media_cb(blk->dev_opaque, load, &local_err);
|
||||
if (local_err) {
|
||||
assert(load == true);
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
tray_is_open = blk_dev_is_tray_open(blk);
|
||||
|
||||
if (tray_was_open != tray_is_open) {
|
||||
@ -703,7 +713,7 @@ void blk_dev_change_media_cb(BlockBackend *blk, bool load)
|
||||
|
||||
static void blk_root_change_media(BdrvChild *child, bool load)
|
||||
{
|
||||
blk_dev_change_media_cb(child->opaque, load);
|
||||
blk_dev_change_media_cb(child->opaque, load, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
19
blockdev.c
19
blockdev.c
@ -2311,7 +2311,7 @@ static int do_open_tray(const char *blk_name, const char *qdev_id,
|
||||
}
|
||||
|
||||
if (!locked || force) {
|
||||
blk_dev_change_media_cb(blk, false);
|
||||
blk_dev_change_media_cb(blk, false, &error_abort);
|
||||
}
|
||||
|
||||
if (locked && !force) {
|
||||
@ -2349,6 +2349,7 @@ void qmp_blockdev_close_tray(bool has_device, const char *device,
|
||||
Error **errp)
|
||||
{
|
||||
BlockBackend *blk;
|
||||
Error *local_err = NULL;
|
||||
|
||||
device = has_device ? device : NULL;
|
||||
id = has_id ? id : NULL;
|
||||
@ -2372,7 +2373,11 @@ void qmp_blockdev_close_tray(bool has_device, const char *device,
|
||||
return;
|
||||
}
|
||||
|
||||
blk_dev_change_media_cb(blk, true);
|
||||
blk_dev_change_media_cb(blk, true, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void qmp_x_blockdev_remove_medium(bool has_device, const char *device,
|
||||
@ -2425,7 +2430,7 @@ void qmp_x_blockdev_remove_medium(bool has_device, const char *device,
|
||||
* called at all); therefore, the medium needs to be ejected here.
|
||||
* Do it after blk_remove_bs() so blk_is_inserted(blk) returns the @load
|
||||
* value passed here (i.e. false). */
|
||||
blk_dev_change_media_cb(blk, false);
|
||||
blk_dev_change_media_cb(blk, false, &error_abort);
|
||||
}
|
||||
|
||||
out:
|
||||
@ -2435,6 +2440,7 @@ out:
|
||||
static void qmp_blockdev_insert_anon_medium(BlockBackend *blk,
|
||||
BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
bool has_device;
|
||||
int ret;
|
||||
|
||||
@ -2467,7 +2473,12 @@ static void qmp_blockdev_insert_anon_medium(BlockBackend *blk,
|
||||
* slot here.
|
||||
* Do it after blk_insert_bs() so blk_is_inserted(blk) returns the @load
|
||||
* value passed here (i.e. true). */
|
||||
blk_dev_change_media_cb(blk, true);
|
||||
blk_dev_change_media_cb(blk, true, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
blk_remove_bs(blk);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -469,7 +469,7 @@ static void fd_revalidate(FDrive *drv)
|
||||
}
|
||||
}
|
||||
|
||||
static void fd_change_cb(void *opaque, bool load)
|
||||
static void fd_change_cb(void *opaque, bool load, Error **errp)
|
||||
{
|
||||
FDrive *drive = opaque;
|
||||
|
||||
|
@ -1120,7 +1120,7 @@ static void ide_cfata_metadata_write(IDEState *s)
|
||||
}
|
||||
|
||||
/* called when the inserted state of the media has changed */
|
||||
static void ide_cd_change_cb(void *opaque, bool load)
|
||||
static void ide_cd_change_cb(void *opaque, bool load, Error **errp)
|
||||
{
|
||||
IDEState *s = opaque;
|
||||
uint64_t nb_sectors;
|
||||
|
@ -2240,7 +2240,7 @@ static void scsi_disk_resize_cb(void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
static void scsi_cd_change_media_cb(void *opaque, bool load)
|
||||
static void scsi_cd_change_media_cb(void *opaque, bool load, Error **errp)
|
||||
{
|
||||
SCSIDiskState *s = opaque;
|
||||
|
||||
|
@ -458,7 +458,7 @@ static bool sd_get_readonly(SDState *sd)
|
||||
return sd->wp_switch;
|
||||
}
|
||||
|
||||
static void sd_cardchange(void *opaque, bool load)
|
||||
static void sd_cardchange(void *opaque, bool load, Error **errp)
|
||||
{
|
||||
SDState *sd = opaque;
|
||||
DeviceState *dev = DEVICE(sd);
|
||||
|
@ -891,7 +891,7 @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
|
||||
uint64_t *nperm, uint64_t *nshared);
|
||||
|
||||
const char *bdrv_get_parent_name(const BlockDriverState *bs);
|
||||
void blk_dev_change_media_cb(BlockBackend *blk, bool load);
|
||||
void blk_dev_change_media_cb(BlockBackend *blk, bool load, Error **errp);
|
||||
bool blk_dev_has_removable_media(BlockBackend *blk);
|
||||
bool blk_dev_has_tray(BlockBackend *blk);
|
||||
void blk_dev_eject_request(BlockBackend *blk, bool force);
|
||||
|
@ -34,7 +34,7 @@ typedef struct BlockDevOps {
|
||||
* changes. Sure would be useful if it did.
|
||||
* Device models with removable media must implement this callback.
|
||||
*/
|
||||
void (*change_media_cb)(void *opaque, bool load);
|
||||
void (*change_media_cb)(void *opaque, bool load, Error **errp);
|
||||
/*
|
||||
* Runs when an eject request is issued from the monitor, the tray
|
||||
* is closed, and the medium is locked.
|
||||
|
Loading…
Reference in New Issue
Block a user