Expose the new read-only option of qmp_change_blockdev() for the 'change' QMP command. Leave it unset for HMP for now.
Signed-off-by: Max Reitz <mre...@redhat.com> --- hmp.c | 2 +- qapi-schema.json | 7 ++++++- qmp-commands.hx | 24 +++++++++++++++++++++++- qmp.c | 15 ++++++++++++--- 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/hmp.c b/hmp.c index 94b27df..0719fa3 100644 --- a/hmp.c +++ b/hmp.c @@ -1133,7 +1133,7 @@ void hmp_change(Monitor *mon, const QDict *qdict) } } - qmp_change(device, target, !!arg, arg, &err); + qmp_change(device, target, !!arg, arg, false, 0, &err); if (err && error_get_class(err) == ERROR_CLASS_DEVICE_ENCRYPTED) { error_free(err); diff --git a/qapi-schema.json b/qapi-schema.json index 441e001..80aaa63 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1581,6 +1581,10 @@ # password to set. If this argument is an empty string, then no future # logins will be allowed. # +# @read-only: #optional, only valid for block devices. This option allows +# changing the read-only mode of the block device; defaults to +# 'retain'. (Since 2.3) +# # Returns: Nothing on success. # If @device is not a valid block device, DeviceNotFound # If the new block device is encrypted, DeviceEncrypted. Note that @@ -1595,7 +1599,8 @@ # Since: 0.14.0 ## { 'command': 'change', - 'data': {'device': 'str', 'target': 'str', '*arg': 'str'} } + 'data': {'device': 'str', 'target': 'str', '*arg': 'str', + '*read-only': 'BlockdevChangeReadOnlyMode'} } ## # @ObjectTypeInfo: diff --git a/qmp-commands.hx b/qmp-commands.hx index 6ef1b28..edc1783 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -109,7 +109,7 @@ EQMP { .name = "change", - .args_type = "device:B,target:F,arg:s?", + .args_type = "device:B,target:F,arg:s?,read-only:s?", .mhandler.cmd_new = qmp_marshal_input_change, }, @@ -124,6 +124,8 @@ Arguments: - "device": device name (json-string) - "target": filename or item (json-string) - "arg": additional argument (json-string, optional) +- "read-only": new read-only mode (json-string, optional) + - Possible values: "retain" (default), "ro", "rw", "auto" Examples: @@ -141,6 +143,26 @@ Examples: "arg": "foobar1" } } <- { "return": {} } +3. Load a read-only medium into a writable drive + +-> { "execute": "change", + "arguments": { "device": "isa-fd0", + "target": "/srv/images/ro.img", + "arg": "raw", + "read-only": "retain" } } + +<- { "error": + { "class": "GenericError", + "desc": "Could not open '/srv/images/ro.img': Permission denied" } } + +-> { "execute": "change", + "arguments": { "device": "isa-fd0", + "target": "/srv/images/ro.img", + "arg": "raw", + "read-only": "auto" } } + +<- { "return": {} } + EQMP { diff --git a/qmp.c b/qmp.c index bd63cf4..d12035b 100644 --- a/qmp.c +++ b/qmp.c @@ -397,13 +397,22 @@ static void qmp_change_vnc(const char *target, bool has_arg, const char *arg, #endif /* !CONFIG_VNC */ void qmp_change(const char *device, const char *target, - bool has_arg, const char *arg, Error **errp) + bool has_arg, const char *arg, + bool has_read_only, BlockdevChangeReadOnlyMode read_only, + Error **errp) { + if (!has_read_only) { + read_only = BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN; + } + if (strcmp(device, "vnc") == 0) { + if (has_read_only) { + error_setg(errp, "Parameter 'read-only' is invalid for VNC"); + return; + } qmp_change_vnc(target, has_arg, arg, errp); } else { - qmp_change_blockdev(device, target, arg, - BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN, errp); + qmp_change_blockdev(device, target, arg, read_only, errp); } } -- 1.9.3