The modification is useful to workaround exclusive file access restrictions, e.g. to implement VM migration with shared disk stored on a storage with the exclusive file opening model: a destination VM is started waiting for incomming migration with a fake image drive, and later, on the last migration phase, the fake image file is replaced with the real one.
Signed-off-by: Denis Plotnikov <[email protected]> --- blockdev.c | 69 +++++++++++++++++++++++++++++++------------- hmp.c | 2 ++ qapi/block-core.json | 7 +++-- qmp.c | 3 +- 4 files changed, 57 insertions(+), 24 deletions(-) diff --git a/blockdev.c b/blockdev.c index d358169995..23f3465cfc 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2609,6 +2609,8 @@ void qmp_blockdev_change_medium(bool has_device, const char *device, bool has_format, const char *format, bool has_read_only, BlockdevChangeReadOnlyMode read_only, + bool has_medium_name, + const char *medium_name, Error **errp) { BlockBackend *blk; @@ -2667,29 +2669,56 @@ void qmp_blockdev_change_medium(bool has_device, const char *device, goto fail; } - rc = do_open_tray(has_device ? device : NULL, - has_id ? id : NULL, - false, &err); - if (rc && rc != -ENOSYS) { - error_propagate(errp, err); - goto fail; - } - error_free(err); - err = NULL; + if (blk_dev_has_removable_media(blk)) { + rc = do_open_tray(has_device ? device : NULL, + has_id ? id : NULL, + false, &err); + if (rc && rc != -ENOSYS) { + error_propagate(errp, err); + goto fail; + } + error_free(err); + err = NULL; - blockdev_remove_medium(has_device, device, has_id, id, &err); - if (err) { - error_propagate(errp, err); - goto fail; - } + blockdev_remove_medium(has_device, device, has_id, id, &err); + if (err) { + error_propagate(errp, err); + goto fail; + } - qmp_blockdev_insert_anon_medium(blk, medium_bs, &err); - if (err) { - error_propagate(errp, err); - goto fail; - } + qmp_blockdev_insert_anon_medium(blk, medium_bs, &err); + if (err) { + error_propagate(errp, err); + goto fail; + } + + qmp_blockdev_close_tray(has_device, device, has_id, id, errp); + } else { + if (!medium_name) { + error_setg(errp, "A medium name should be given"); + goto fail; + } - qmp_blockdev_close_tray(has_device, device, has_id, id, errp); + if (runstate_is_running()) { + error_setg(errp, "Can't set a medium for non-removable device " + "in a running VM"); + goto fail; + } + + if (strlen(blk_name(blk))) { + error_setg(errp, "The device already has a medium"); + goto fail; + } + + if (blk_insert_bs(blk, medium_bs, &err) < 0) { + error_propagate(errp, err); + goto fail; + } + + if (!monitor_add_blk(blk, medium_name, &err)) { + error_propagate(errp, err); + } + } fail: /* If the medium has been inserted, the device has its own reference, so diff --git a/hmp.c b/hmp.c index 8eec768088..fc7bac5b4b 100644 --- a/hmp.c +++ b/hmp.c @@ -1948,6 +1948,7 @@ void hmp_change(Monitor *mon, const QDict *qdict) const char *target = qdict_get_str(qdict, "target"); const char *arg = qdict_get_try_str(qdict, "arg"); const char *read_only = qdict_get_try_str(qdict, "read-only-mode"); + const char *target_name = qdict_get_try_str(qdict, "target-name"); BlockdevChangeReadOnlyMode read_only_mode = 0; Error *err = NULL; @@ -1982,6 +1983,7 @@ void hmp_change(Monitor *mon, const QDict *qdict) qmp_blockdev_change_medium(true, device, false, NULL, target, !!arg, arg, !!read_only, read_only_mode, + !!target_name, target_name, &err); } diff --git a/qapi/block-core.json b/qapi/block-core.json index 7ccbfff9d0..f493a7c737 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -4769,6 +4769,8 @@ # @read-only-mode: change the read-only mode of the device; defaults # to 'retain' # +# @medium-name: drive-name when changing the media in non-removable devices +# ignored when changing media in removable devices # Since: 2.5 # # Examples: @@ -4807,9 +4809,8 @@ '*id': 'str', 'filename': 'str', '*format': 'str', - '*read-only-mode': 'BlockdevChangeReadOnlyMode' } } - - + '*read-only-mode': 'BlockdevChangeReadOnlyMode', + '*medium-name': 'str' } } ## # @BlockErrorAction: # diff --git a/qmp.c b/qmp.c index b92d62cd5f..c95831a49f 100644 --- a/qmp.c +++ b/qmp.c @@ -399,7 +399,8 @@ void qmp_change(const char *device, const char *target, #endif } else { qmp_blockdev_change_medium(true, device, false, NULL, target, - has_arg, arg, false, 0, errp); + has_arg, arg, false, 0, false, NULL, + errp); } } -- 2.17.0
