Message ID | 20200127103647.17761-10-mlevitsk@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | RFC: [for 5.0]: HMP monitor handlers cleanups | expand |
* Maxim Levitsky (mlevitsk@redhat.com) wrote: > Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com> > --- > block/monitor/block-hmp-cmds.c | 138 +++++++++++++++++++++++++++++ > include/block/block-hmp-commands.h | 9 ++ > include/monitor/hmp.h | 6 -- > monitor/hmp-cmds.c | 137 ---------------------------- > 4 files changed, 147 insertions(+), 143 deletions(-) > > diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c > index df0178d0f9..60d63bfe18 100644 > --- a/block/monitor/block-hmp-cmds.c > +++ b/block/monitor/block-hmp-cmds.c > @@ -29,6 +29,7 @@ > #include "block/block_int.h" > #include "block/block-hmp-commands.h" > #include "monitor/hmp.h" > +#include "qemu-io.h" > > void hmp_drive_add(Monitor *mon, const QDict *qdict) > { > @@ -415,3 +416,140 @@ void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict) > qmp_nbd_server_stop(&err); > hmp_handle_error(mon, err); > } > + > +void hmp_block_resize(Monitor *mon, const QDict *qdict) > +{ > + const char *device = qdict_get_str(qdict, "device"); > + int64_t size = qdict_get_int(qdict, "size"); > + Error *err = NULL; > + > + qmp_block_resize(true, device, false, NULL, size, &err); > + hmp_handle_error(mon, err); > +} > + > +void hmp_block_stream(Monitor *mon, const QDict *qdict) > +{ > + Error *error = NULL; > + const char *device = qdict_get_str(qdict, "device"); > + const char *base = qdict_get_try_str(qdict, "base"); > + int64_t speed = qdict_get_try_int(qdict, "speed", 0); > + > + qmp_block_stream(true, device, device, base != NULL, base, false, NULL, > + false, NULL, qdict_haskey(qdict, "speed"), speed, true, > + BLOCKDEV_ON_ERROR_REPORT, false, false, false, false, > + &error); > + > + hmp_handle_error(mon, error); > +} > + > +void hmp_block_passwd(Monitor *mon, const QDict *qdict) > +{ > + const char *device = qdict_get_str(qdict, "device"); > + const char *password = qdict_get_str(qdict, "password"); > + Error *err = NULL; > + > + qmp_block_passwd(true, device, false, NULL, password, &err); > + hmp_handle_error(mon, err); > +} > + > +void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict) > +{ > + Error *err = NULL; > + char *device = (char *) qdict_get_str(qdict, "device"); > + BlockIOThrottle throttle = { > + .bps = qdict_get_int(qdict, "bps"), > + .bps_rd = qdict_get_int(qdict, "bps_rd"), > + .bps_wr = qdict_get_int(qdict, "bps_wr"), > + .iops = qdict_get_int(qdict, "iops"), > + .iops_rd = qdict_get_int(qdict, "iops_rd"), > + .iops_wr = qdict_get_int(qdict, "iops_wr"), > + }; > + > + /* qmp_block_set_io_throttle has separate parameters for the > + * (deprecated) block device name and the qdev ID but the HMP > + * version has only one, so we must decide which one to pass. */ > + if (blk_by_name(device)) { > + throttle.has_device = true; > + throttle.device = device; > + } else { > + throttle.has_id = true; > + throttle.id = device; > + } > + > + qmp_block_set_io_throttle(&throttle, &err); > + hmp_handle_error(mon, err); > +} > + > +void hmp_eject(Monitor *mon, const QDict *qdict) > +{ > + bool force = qdict_get_try_bool(qdict, "force", false); > + const char *device = qdict_get_str(qdict, "device"); > + Error *err = NULL; > + > + qmp_eject(true, device, false, NULL, true, force, &err); > + hmp_handle_error(mon, err); > +} > + > +void hmp_qemu_io(Monitor *mon, const QDict *qdict) > +{ > + BlockBackend *blk; > + BlockBackend *local_blk = NULL; > + bool qdev = qdict_get_try_bool(qdict, "qdev", false); > + const char* device = qdict_get_str(qdict, "device"); > + const char* command = qdict_get_str(qdict, "command"); > + Error *err = NULL; > + int ret; > + > + if (qdev) { > + blk = blk_by_qdev_id(device, &err); > + if (!blk) { > + goto fail; > + } > + } else { > + blk = blk_by_name(device); > + if (!blk) { > + BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err); > + if (bs) { > + blk = local_blk = blk_new(bdrv_get_aio_context(bs), > + 0, BLK_PERM_ALL); > + ret = blk_insert_bs(blk, bs, &err); > + if (ret < 0) { > + goto fail; > + } > + } else { > + goto fail; > + } > + } > + } > + > + /* > + * Notably absent: Proper permission management. This is sad, but it seems > + * almost impossible to achieve without changing the semantics and thereby > + * limiting the use cases of the qemu-io HMP command. > + * > + * In an ideal world we would unconditionally create a new BlockBackend for > + * qemuio_command(), but we have commands like 'reopen' and want them to > + * take effect on the exact BlockBackend whose name the user passed instead > + * of just on a temporary copy of it. > + * > + * Another problem is that deleting the temporary BlockBackend involves > + * draining all requests on it first, but some qemu-iotests cases want to > + * issue multiple aio_read/write requests and expect them to complete in > + * the background while the monitor has already returned. > + * > + * This is also what prevents us from saving the original permissions and > + * restoring them later: We can't revoke permissions until all requests > + * have completed, and we don't know when that is nor can we really let > + * anything else run before we have revoken them to avoid race conditions. > + * > + * What happens now is that command() in qemu-io-cmds.c can extend the > + * permissions if necessary for the qemu-io command. And they simply stay > + * extended, possibly resulting in a read-only guest device keeping write > + * permissions. Ugly, but it appears to be the lesser evil. > + */ > + qemuio_command(blk, command); > + > +fail: > + blk_unref(local_blk); > + hmp_handle_error(mon, err); > +} > diff --git a/include/block/block-hmp-commands.h b/include/block/block-hmp-commands.h > index 721b9a1978..99145c8fcf 100644 > --- a/include/block/block-hmp-commands.h > +++ b/include/block/block-hmp-commands.h > @@ -26,4 +26,13 @@ void hmp_nbd_server_add(Monitor *mon, const QDict *qdict); > void hmp_nbd_server_remove(Monitor *mon, const QDict *qdict); > void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict); > > +void hmp_block_resize(Monitor *mon, const QDict *qdict); > +void hmp_block_stream(Monitor *mon, const QDict *qdict); > +void hmp_block_passwd(Monitor *mon, const QDict *qdict); > +void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict); > +void hmp_eject(Monitor *mon, const QDict *qdict); > + > +void hmp_qemu_io(Monitor *mon, const QDict *qdict); > + > + > #endif > diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h > index 736a969131..47a7cad734 100644 > --- a/include/monitor/hmp.h > +++ b/include/monitor/hmp.h > @@ -58,9 +58,7 @@ void hmp_cont(Monitor *mon, const QDict *qdict); > void hmp_system_wakeup(Monitor *mon, const QDict *qdict); > void hmp_nmi(Monitor *mon, const QDict *qdict); > void hmp_set_link(Monitor *mon, const QDict *qdict); > -void hmp_block_passwd(Monitor *mon, const QDict *qdict); > void hmp_balloon(Monitor *mon, const QDict *qdict); > -void hmp_block_resize(Monitor *mon, const QDict *qdict); > void hmp_loadvm(Monitor *mon, const QDict *qdict); > void hmp_savevm(Monitor *mon, const QDict *qdict); > void hmp_delvm(Monitor *mon, const QDict *qdict); > @@ -80,10 +78,7 @@ void hmp_migrate_start_postcopy(Monitor *mon, const QDict *qdict); > void hmp_x_colo_lost_heartbeat(Monitor *mon, const QDict *qdict); > void hmp_set_password(Monitor *mon, const QDict *qdict); > void hmp_expire_password(Monitor *mon, const QDict *qdict); > -void hmp_eject(Monitor *mon, const QDict *qdict); > void hmp_change(Monitor *mon, const QDict *qdict); > -void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict); > -void hmp_block_stream(Monitor *mon, const QDict *qdict); > void hmp_migrate(Monitor *mon, const QDict *qdict); > void hmp_device_add(Monitor *mon, const QDict *qdict); > void hmp_device_del(Monitor *mon, const QDict *qdict); > @@ -98,7 +93,6 @@ void hmp_chardev_add(Monitor *mon, const QDict *qdict); > void hmp_chardev_change(Monitor *mon, const QDict *qdict); > void hmp_chardev_remove(Monitor *mon, const QDict *qdict); > void hmp_chardev_send_break(Monitor *mon, const QDict *qdict); > -void hmp_qemu_io(Monitor *mon, const QDict *qdict); > void hmp_cpu_add(Monitor *mon, const QDict *qdict); > void hmp_object_add(Monitor *mon, const QDict *qdict); > void hmp_object_del(Monitor *mon, const QDict *qdict); > diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c > index 67d2ca8a4c..c224e0f338 100644 > --- a/monitor/hmp-cmds.c > +++ b/monitor/hmp-cmds.c > @@ -46,7 +46,6 @@ > #include "qom/object_interfaces.h" > #include "ui/console.h" > #include "block/qapi.h" > -#include "qemu-io.h" > #include "qemu/cutils.h" > #include "qemu/error-report.h" > #include "exec/ramlist.h" > @@ -1307,16 +1306,6 @@ void hmp_set_link(Monitor *mon, const QDict *qdict) > hmp_handle_error(mon, err); > } > > -void hmp_block_passwd(Monitor *mon, const QDict *qdict) > -{ > - const char *device = qdict_get_str(qdict, "device"); > - const char *password = qdict_get_str(qdict, "password"); > - Error *err = NULL; > - > - qmp_block_passwd(true, device, false, NULL, password, &err); > - hmp_handle_error(mon, err); > -} > - > void hmp_balloon(Monitor *mon, const QDict *qdict) > { > int64_t value = qdict_get_int(qdict, "value"); > @@ -1326,16 +1315,6 @@ void hmp_balloon(Monitor *mon, const QDict *qdict) > hmp_handle_error(mon, err); > } > > -void hmp_block_resize(Monitor *mon, const QDict *qdict) > -{ > - const char *device = qdict_get_str(qdict, "device"); > - int64_t size = qdict_get_int(qdict, "size"); > - Error *err = NULL; > - > - qmp_block_resize(true, device, false, NULL, size, &err); > - hmp_handle_error(mon, err); > -} > - > void hmp_loadvm(Monitor *mon, const QDict *qdict) > { > int saved_vm_running = runstate_is_running(); > @@ -1818,15 +1797,6 @@ void hmp_expire_password(Monitor *mon, const QDict *qdict) > hmp_handle_error(mon, err); > } > > -void hmp_eject(Monitor *mon, const QDict *qdict) > -{ > - bool force = qdict_get_try_bool(qdict, "force", false); > - const char *device = qdict_get_str(qdict, "device"); > - Error *err = NULL; > - > - qmp_eject(true, device, false, NULL, true, force, &err); > - hmp_handle_error(mon, err); > -} > > #ifdef CONFIG_VNC > static void hmp_change_read_arg(void *opaque, const char *password, > @@ -1884,49 +1854,6 @@ void hmp_change(Monitor *mon, const QDict *qdict) > hmp_handle_error(mon, err); > } > > -void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict) > -{ > - Error *err = NULL; > - char *device = (char *) qdict_get_str(qdict, "device"); > - BlockIOThrottle throttle = { > - .bps = qdict_get_int(qdict, "bps"), > - .bps_rd = qdict_get_int(qdict, "bps_rd"), > - .bps_wr = qdict_get_int(qdict, "bps_wr"), > - .iops = qdict_get_int(qdict, "iops"), > - .iops_rd = qdict_get_int(qdict, "iops_rd"), > - .iops_wr = qdict_get_int(qdict, "iops_wr"), > - }; > - > - /* qmp_block_set_io_throttle has separate parameters for the > - * (deprecated) block device name and the qdev ID but the HMP > - * version has only one, so we must decide which one to pass. */ > - if (blk_by_name(device)) { > - throttle.has_device = true; > - throttle.device = device; > - } else { > - throttle.has_id = true; > - throttle.id = device; > - } > - > - qmp_block_set_io_throttle(&throttle, &err); > - hmp_handle_error(mon, err); > -} > - > -void hmp_block_stream(Monitor *mon, const QDict *qdict) > -{ > - Error *error = NULL; > - const char *device = qdict_get_str(qdict, "device"); > - const char *base = qdict_get_try_str(qdict, "base"); > - int64_t speed = qdict_get_try_int(qdict, "speed", 0); > - > - qmp_block_stream(true, device, device, base != NULL, base, false, NULL, > - false, NULL, qdict_haskey(qdict, "speed"), speed, true, > - BLOCKDEV_ON_ERROR_REPORT, false, false, false, false, > - &error); > - > - hmp_handle_error(mon, error); > -} > - > typedef struct HMPMigrationStatus > { > QEMUTimer *timer; > @@ -2219,70 +2146,6 @@ void hmp_chardev_send_break(Monitor *mon, const QDict *qdict) > hmp_handle_error(mon, local_err); > } > > -void hmp_qemu_io(Monitor *mon, const QDict *qdict) > -{ > - BlockBackend *blk; > - BlockBackend *local_blk = NULL; > - bool qdev = qdict_get_try_bool(qdict, "qdev", false); > - const char* device = qdict_get_str(qdict, "device"); > - const char* command = qdict_get_str(qdict, "command"); > - Error *err = NULL; > - int ret; > - > - if (qdev) { > - blk = blk_by_qdev_id(device, &err); > - if (!blk) { > - goto fail; > - } > - } else { > - blk = blk_by_name(device); > - if (!blk) { > - BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err); > - if (bs) { > - blk = local_blk = blk_new(bdrv_get_aio_context(bs), > - 0, BLK_PERM_ALL); > - ret = blk_insert_bs(blk, bs, &err); > - if (ret < 0) { > - goto fail; > - } > - } else { > - goto fail; > - } > - } > - } > - > - /* > - * Notably absent: Proper permission management. This is sad, but it seems > - * almost impossible to achieve without changing the semantics and thereby > - * limiting the use cases of the qemu-io HMP command. > - * > - * In an ideal world we would unconditionally create a new BlockBackend for > - * qemuio_command(), but we have commands like 'reopen' and want them to > - * take effect on the exact BlockBackend whose name the user passed instead > - * of just on a temporary copy of it. > - * > - * Another problem is that deleting the temporary BlockBackend involves > - * draining all requests on it first, but some qemu-iotests cases want to > - * issue multiple aio_read/write requests and expect them to complete in > - * the background while the monitor has already returned. > - * > - * This is also what prevents us from saving the original permissions and > - * restoring them later: We can't revoke permissions until all requests > - * have completed, and we don't know when that is nor can we really let > - * anything else run before we have revoken them to avoid race conditions. > - * > - * What happens now is that command() in qemu-io-cmds.c can extend the > - * permissions if necessary for the qemu-io command. And they simply stay > - * extended, possibly resulting in a read-only guest device keeping write > - * permissions. Ugly, but it appears to be the lesser evil. > - */ > - qemuio_command(blk, command); > - > -fail: > - blk_unref(local_blk); > - hmp_handle_error(mon, err); > -} > - > void hmp_object_del(Monitor *mon, const QDict *qdict) > { > const char *id = qdict_get_str(qdict, "id"); > -- > 2.17.2 > -- Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
* Maxim Levitsky (mlevitsk@redhat.com) wrote: > Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com> > --- > block/monitor/block-hmp-cmds.c | 138 +++++++++++++++++++++++++++++ > include/block/block-hmp-commands.h | 9 ++ > include/monitor/hmp.h | 6 -- > monitor/hmp-cmds.c | 137 ---------------------------- > 4 files changed, 147 insertions(+), 143 deletions(-) > > diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c > index df0178d0f9..60d63bfe18 100644 > --- a/block/monitor/block-hmp-cmds.c > +++ b/block/monitor/block-hmp-cmds.c > @@ -29,6 +29,7 @@ > #include "block/block_int.h" > #include "block/block-hmp-commands.h" > #include "monitor/hmp.h" > +#include "qemu-io.h" > > void hmp_drive_add(Monitor *mon, const QDict *qdict) > { > @@ -415,3 +416,140 @@ void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict) > qmp_nbd_server_stop(&err); > hmp_handle_error(mon, err); > } > + > +void hmp_block_resize(Monitor *mon, const QDict *qdict) > +{ > + const char *device = qdict_get_str(qdict, "device"); > + int64_t size = qdict_get_int(qdict, "size"); > + Error *err = NULL; > + > + qmp_block_resize(true, device, false, NULL, size, &err); > + hmp_handle_error(mon, err); > +} > + > +void hmp_block_stream(Monitor *mon, const QDict *qdict) > +{ > + Error *error = NULL; > + const char *device = qdict_get_str(qdict, "device"); > + const char *base = qdict_get_try_str(qdict, "base"); > + int64_t speed = qdict_get_try_int(qdict, "speed", 0); > + > + qmp_block_stream(true, device, device, base != NULL, base, false, NULL, > + false, NULL, qdict_haskey(qdict, "speed"), speed, true, > + BLOCKDEV_ON_ERROR_REPORT, false, false, false, false, > + &error); > + > + hmp_handle_error(mon, error); > +} > + > +void hmp_block_passwd(Monitor *mon, const QDict *qdict) > +{ > + const char *device = qdict_get_str(qdict, "device"); > + const char *password = qdict_get_str(qdict, "password"); > + Error *err = NULL; > + > + qmp_block_passwd(true, device, false, NULL, password, &err); > + hmp_handle_error(mon, err); > +} > + > +void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict) > +{ > + Error *err = NULL; > + char *device = (char *) qdict_get_str(qdict, "device"); > + BlockIOThrottle throttle = { > + .bps = qdict_get_int(qdict, "bps"), > + .bps_rd = qdict_get_int(qdict, "bps_rd"), > + .bps_wr = qdict_get_int(qdict, "bps_wr"), > + .iops = qdict_get_int(qdict, "iops"), > + .iops_rd = qdict_get_int(qdict, "iops_rd"), > + .iops_wr = qdict_get_int(qdict, "iops_wr"), > + }; > + > + /* qmp_block_set_io_throttle has separate parameters for the > + * (deprecated) block device name and the qdev ID but the HMP > + * version has only one, so we must decide which one to pass. */ > + if (blk_by_name(device)) { > + throttle.has_device = true; > + throttle.device = device; > + } else { > + throttle.has_id = true; > + throttle.id = device; > + } > + > + qmp_block_set_io_throttle(&throttle, &err); > + hmp_handle_error(mon, err); > +} > + > +void hmp_eject(Monitor *mon, const QDict *qdict) > +{ > + bool force = qdict_get_try_bool(qdict, "force", false); > + const char *device = qdict_get_str(qdict, "device"); > + Error *err = NULL; > + > + qmp_eject(true, device, false, NULL, true, force, &err); > + hmp_handle_error(mon, err); > +} > + > +void hmp_qemu_io(Monitor *mon, const QDict *qdict) > +{ > + BlockBackend *blk; > + BlockBackend *local_blk = NULL; > + bool qdev = qdict_get_try_bool(qdict, "qdev", false); > + const char* device = qdict_get_str(qdict, "device"); > + const char* command = qdict_get_str(qdict, "command"); > + Error *err = NULL; > + int ret; > + > + if (qdev) { > + blk = blk_by_qdev_id(device, &err); > + if (!blk) { > + goto fail; > + } > + } else { > + blk = blk_by_name(device); > + if (!blk) { > + BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err); > + if (bs) { > + blk = local_blk = blk_new(bdrv_get_aio_context(bs), > + 0, BLK_PERM_ALL); > + ret = blk_insert_bs(blk, bs, &err); > + if (ret < 0) { > + goto fail; > + } > + } else { > + goto fail; > + } > + } > + } > + > + /* > + * Notably absent: Proper permission management. This is sad, but it seems > + * almost impossible to achieve without changing the semantics and thereby > + * limiting the use cases of the qemu-io HMP command. > + * > + * In an ideal world we would unconditionally create a new BlockBackend for > + * qemuio_command(), but we have commands like 'reopen' and want them to > + * take effect on the exact BlockBackend whose name the user passed instead > + * of just on a temporary copy of it. > + * > + * Another problem is that deleting the temporary BlockBackend involves > + * draining all requests on it first, but some qemu-iotests cases want to > + * issue multiple aio_read/write requests and expect them to complete in > + * the background while the monitor has already returned. > + * > + * This is also what prevents us from saving the original permissions and > + * restoring them later: We can't revoke permissions until all requests > + * have completed, and we don't know when that is nor can we really let > + * anything else run before we have revoken them to avoid race conditions. > + * > + * What happens now is that command() in qemu-io-cmds.c can extend the > + * permissions if necessary for the qemu-io command. And they simply stay > + * extended, possibly resulting in a read-only guest device keeping write > + * permissions. Ugly, but it appears to be the lesser evil. > + */ > + qemuio_command(blk, command); > + > +fail: > + blk_unref(local_blk); > + hmp_handle_error(mon, err); > +} > diff --git a/include/block/block-hmp-commands.h b/include/block/block-hmp-commands.h > index 721b9a1978..99145c8fcf 100644 > --- a/include/block/block-hmp-commands.h > +++ b/include/block/block-hmp-commands.h > @@ -26,4 +26,13 @@ void hmp_nbd_server_add(Monitor *mon, const QDict *qdict); > void hmp_nbd_server_remove(Monitor *mon, const QDict *qdict); > void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict); > > +void hmp_block_resize(Monitor *mon, const QDict *qdict); > +void hmp_block_stream(Monitor *mon, const QDict *qdict); > +void hmp_block_passwd(Monitor *mon, const QDict *qdict); > +void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict); > +void hmp_eject(Monitor *mon, const QDict *qdict); > + > +void hmp_qemu_io(Monitor *mon, const QDict *qdict); > + > + > #endif > diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h > index 736a969131..47a7cad734 100644 > --- a/include/monitor/hmp.h > +++ b/include/monitor/hmp.h > @@ -58,9 +58,7 @@ void hmp_cont(Monitor *mon, const QDict *qdict); > void hmp_system_wakeup(Monitor *mon, const QDict *qdict); > void hmp_nmi(Monitor *mon, const QDict *qdict); > void hmp_set_link(Monitor *mon, const QDict *qdict); > -void hmp_block_passwd(Monitor *mon, const QDict *qdict); > void hmp_balloon(Monitor *mon, const QDict *qdict); > -void hmp_block_resize(Monitor *mon, const QDict *qdict); > void hmp_loadvm(Monitor *mon, const QDict *qdict); > void hmp_savevm(Monitor *mon, const QDict *qdict); > void hmp_delvm(Monitor *mon, const QDict *qdict); > @@ -80,10 +78,7 @@ void hmp_migrate_start_postcopy(Monitor *mon, const QDict *qdict); > void hmp_x_colo_lost_heartbeat(Monitor *mon, const QDict *qdict); > void hmp_set_password(Monitor *mon, const QDict *qdict); > void hmp_expire_password(Monitor *mon, const QDict *qdict); > -void hmp_eject(Monitor *mon, const QDict *qdict); > void hmp_change(Monitor *mon, const QDict *qdict); > -void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict); > -void hmp_block_stream(Monitor *mon, const QDict *qdict); > void hmp_migrate(Monitor *mon, const QDict *qdict); > void hmp_device_add(Monitor *mon, const QDict *qdict); > void hmp_device_del(Monitor *mon, const QDict *qdict); > @@ -98,7 +93,6 @@ void hmp_chardev_add(Monitor *mon, const QDict *qdict); > void hmp_chardev_change(Monitor *mon, const QDict *qdict); > void hmp_chardev_remove(Monitor *mon, const QDict *qdict); > void hmp_chardev_send_break(Monitor *mon, const QDict *qdict); > -void hmp_qemu_io(Monitor *mon, const QDict *qdict); > void hmp_cpu_add(Monitor *mon, const QDict *qdict); > void hmp_object_add(Monitor *mon, const QDict *qdict); > void hmp_object_del(Monitor *mon, const QDict *qdict); > diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c > index 67d2ca8a4c..c224e0f338 100644 > --- a/monitor/hmp-cmds.c > +++ b/monitor/hmp-cmds.c > @@ -46,7 +46,6 @@ > #include "qom/object_interfaces.h" > #include "ui/console.h" > #include "block/qapi.h" > -#include "qemu-io.h" > #include "qemu/cutils.h" > #include "qemu/error-report.h" > #include "exec/ramlist.h" > @@ -1307,16 +1306,6 @@ void hmp_set_link(Monitor *mon, const QDict *qdict) > hmp_handle_error(mon, err); > } > > -void hmp_block_passwd(Monitor *mon, const QDict *qdict) > -{ > - const char *device = qdict_get_str(qdict, "device"); > - const char *password = qdict_get_str(qdict, "password"); > - Error *err = NULL; > - > - qmp_block_passwd(true, device, false, NULL, password, &err); > - hmp_handle_error(mon, err); > -} > - > void hmp_balloon(Monitor *mon, const QDict *qdict) > { > int64_t value = qdict_get_int(qdict, "value"); > @@ -1326,16 +1315,6 @@ void hmp_balloon(Monitor *mon, const QDict *qdict) > hmp_handle_error(mon, err); > } > > -void hmp_block_resize(Monitor *mon, const QDict *qdict) > -{ > - const char *device = qdict_get_str(qdict, "device"); > - int64_t size = qdict_get_int(qdict, "size"); > - Error *err = NULL; > - > - qmp_block_resize(true, device, false, NULL, size, &err); > - hmp_handle_error(mon, err); > -} > - > void hmp_loadvm(Monitor *mon, const QDict *qdict) > { > int saved_vm_running = runstate_is_running(); > @@ -1818,15 +1797,6 @@ void hmp_expire_password(Monitor *mon, const QDict *qdict) > hmp_handle_error(mon, err); > } > > -void hmp_eject(Monitor *mon, const QDict *qdict) > -{ > - bool force = qdict_get_try_bool(qdict, "force", false); > - const char *device = qdict_get_str(qdict, "device"); > - Error *err = NULL; > - > - qmp_eject(true, device, false, NULL, true, force, &err); > - hmp_handle_error(mon, err); > -} > > #ifdef CONFIG_VNC > static void hmp_change_read_arg(void *opaque, const char *password, > @@ -1884,49 +1854,6 @@ void hmp_change(Monitor *mon, const QDict *qdict) > hmp_handle_error(mon, err); > } > > -void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict) > -{ > - Error *err = NULL; > - char *device = (char *) qdict_get_str(qdict, "device"); > - BlockIOThrottle throttle = { > - .bps = qdict_get_int(qdict, "bps"), > - .bps_rd = qdict_get_int(qdict, "bps_rd"), > - .bps_wr = qdict_get_int(qdict, "bps_wr"), > - .iops = qdict_get_int(qdict, "iops"), > - .iops_rd = qdict_get_int(qdict, "iops_rd"), > - .iops_wr = qdict_get_int(qdict, "iops_wr"), > - }; > - > - /* qmp_block_set_io_throttle has separate parameters for the > - * (deprecated) block device name and the qdev ID but the HMP > - * version has only one, so we must decide which one to pass. */ > - if (blk_by_name(device)) { > - throttle.has_device = true; > - throttle.device = device; > - } else { > - throttle.has_id = true; > - throttle.id = device; > - } > - > - qmp_block_set_io_throttle(&throttle, &err); > - hmp_handle_error(mon, err); > -} > - > -void hmp_block_stream(Monitor *mon, const QDict *qdict) > -{ > - Error *error = NULL; > - const char *device = qdict_get_str(qdict, "device"); > - const char *base = qdict_get_try_str(qdict, "base"); > - int64_t speed = qdict_get_try_int(qdict, "speed", 0); > - > - qmp_block_stream(true, device, device, base != NULL, base, false, NULL, > - false, NULL, qdict_haskey(qdict, "speed"), speed, true, > - BLOCKDEV_ON_ERROR_REPORT, false, false, false, false, > - &error); > - > - hmp_handle_error(mon, error); > -} > - > typedef struct HMPMigrationStatus > { > QEMUTimer *timer; > @@ -2219,70 +2146,6 @@ void hmp_chardev_send_break(Monitor *mon, const QDict *qdict) > hmp_handle_error(mon, local_err); > } > > -void hmp_qemu_io(Monitor *mon, const QDict *qdict) > -{ > - BlockBackend *blk; > - BlockBackend *local_blk = NULL; > - bool qdev = qdict_get_try_bool(qdict, "qdev", false); > - const char* device = qdict_get_str(qdict, "device"); > - const char* command = qdict_get_str(qdict, "command"); > - Error *err = NULL; > - int ret; > - > - if (qdev) { > - blk = blk_by_qdev_id(device, &err); > - if (!blk) { > - goto fail; > - } > - } else { > - blk = blk_by_name(device); > - if (!blk) { > - BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err); > - if (bs) { > - blk = local_blk = blk_new(bdrv_get_aio_context(bs), > - 0, BLK_PERM_ALL); > - ret = blk_insert_bs(blk, bs, &err); > - if (ret < 0) { > - goto fail; > - } > - } else { > - goto fail; > - } > - } > - } > - > - /* > - * Notably absent: Proper permission management. This is sad, but it seems > - * almost impossible to achieve without changing the semantics and thereby > - * limiting the use cases of the qemu-io HMP command. > - * > - * In an ideal world we would unconditionally create a new BlockBackend for > - * qemuio_command(), but we have commands like 'reopen' and want them to > - * take effect on the exact BlockBackend whose name the user passed instead > - * of just on a temporary copy of it. > - * > - * Another problem is that deleting the temporary BlockBackend involves > - * draining all requests on it first, but some qemu-iotests cases want to > - * issue multiple aio_read/write requests and expect them to complete in > - * the background while the monitor has already returned. > - * > - * This is also what prevents us from saving the original permissions and > - * restoring them later: We can't revoke permissions until all requests > - * have completed, and we don't know when that is nor can we really let > - * anything else run before we have revoken them to avoid race conditions. > - * > - * What happens now is that command() in qemu-io-cmds.c can extend the > - * permissions if necessary for the qemu-io command. And they simply stay > - * extended, possibly resulting in a read-only guest device keeping write > - * permissions. Ugly, but it appears to be the lesser evil. > - */ > - qemuio_command(blk, command); > - > -fail: > - blk_unref(local_blk); > - hmp_handle_error(mon, err); > -} > - > void hmp_object_del(Monitor *mon, const QDict *qdict) > { > const char *id = qdict_get_str(qdict, "id"); > -- > 2.17.2 > -- Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c index df0178d0f9..60d63bfe18 100644 --- a/block/monitor/block-hmp-cmds.c +++ b/block/monitor/block-hmp-cmds.c @@ -29,6 +29,7 @@ #include "block/block_int.h" #include "block/block-hmp-commands.h" #include "monitor/hmp.h" +#include "qemu-io.h" void hmp_drive_add(Monitor *mon, const QDict *qdict) { @@ -415,3 +416,140 @@ void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict) qmp_nbd_server_stop(&err); hmp_handle_error(mon, err); } + +void hmp_block_resize(Monitor *mon, const QDict *qdict) +{ + const char *device = qdict_get_str(qdict, "device"); + int64_t size = qdict_get_int(qdict, "size"); + Error *err = NULL; + + qmp_block_resize(true, device, false, NULL, size, &err); + hmp_handle_error(mon, err); +} + +void hmp_block_stream(Monitor *mon, const QDict *qdict) +{ + Error *error = NULL; + const char *device = qdict_get_str(qdict, "device"); + const char *base = qdict_get_try_str(qdict, "base"); + int64_t speed = qdict_get_try_int(qdict, "speed", 0); + + qmp_block_stream(true, device, device, base != NULL, base, false, NULL, + false, NULL, qdict_haskey(qdict, "speed"), speed, true, + BLOCKDEV_ON_ERROR_REPORT, false, false, false, false, + &error); + + hmp_handle_error(mon, error); +} + +void hmp_block_passwd(Monitor *mon, const QDict *qdict) +{ + const char *device = qdict_get_str(qdict, "device"); + const char *password = qdict_get_str(qdict, "password"); + Error *err = NULL; + + qmp_block_passwd(true, device, false, NULL, password, &err); + hmp_handle_error(mon, err); +} + +void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict) +{ + Error *err = NULL; + char *device = (char *) qdict_get_str(qdict, "device"); + BlockIOThrottle throttle = { + .bps = qdict_get_int(qdict, "bps"), + .bps_rd = qdict_get_int(qdict, "bps_rd"), + .bps_wr = qdict_get_int(qdict, "bps_wr"), + .iops = qdict_get_int(qdict, "iops"), + .iops_rd = qdict_get_int(qdict, "iops_rd"), + .iops_wr = qdict_get_int(qdict, "iops_wr"), + }; + + /* qmp_block_set_io_throttle has separate parameters for the + * (deprecated) block device name and the qdev ID but the HMP + * version has only one, so we must decide which one to pass. */ + if (blk_by_name(device)) { + throttle.has_device = true; + throttle.device = device; + } else { + throttle.has_id = true; + throttle.id = device; + } + + qmp_block_set_io_throttle(&throttle, &err); + hmp_handle_error(mon, err); +} + +void hmp_eject(Monitor *mon, const QDict *qdict) +{ + bool force = qdict_get_try_bool(qdict, "force", false); + const char *device = qdict_get_str(qdict, "device"); + Error *err = NULL; + + qmp_eject(true, device, false, NULL, true, force, &err); + hmp_handle_error(mon, err); +} + +void hmp_qemu_io(Monitor *mon, const QDict *qdict) +{ + BlockBackend *blk; + BlockBackend *local_blk = NULL; + bool qdev = qdict_get_try_bool(qdict, "qdev", false); + const char* device = qdict_get_str(qdict, "device"); + const char* command = qdict_get_str(qdict, "command"); + Error *err = NULL; + int ret; + + if (qdev) { + blk = blk_by_qdev_id(device, &err); + if (!blk) { + goto fail; + } + } else { + blk = blk_by_name(device); + if (!blk) { + BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err); + if (bs) { + blk = local_blk = blk_new(bdrv_get_aio_context(bs), + 0, BLK_PERM_ALL); + ret = blk_insert_bs(blk, bs, &err); + if (ret < 0) { + goto fail; + } + } else { + goto fail; + } + } + } + + /* + * Notably absent: Proper permission management. This is sad, but it seems + * almost impossible to achieve without changing the semantics and thereby + * limiting the use cases of the qemu-io HMP command. + * + * In an ideal world we would unconditionally create a new BlockBackend for + * qemuio_command(), but we have commands like 'reopen' and want them to + * take effect on the exact BlockBackend whose name the user passed instead + * of just on a temporary copy of it. + * + * Another problem is that deleting the temporary BlockBackend involves + * draining all requests on it first, but some qemu-iotests cases want to + * issue multiple aio_read/write requests and expect them to complete in + * the background while the monitor has already returned. + * + * This is also what prevents us from saving the original permissions and + * restoring them later: We can't revoke permissions until all requests + * have completed, and we don't know when that is nor can we really let + * anything else run before we have revoken them to avoid race conditions. + * + * What happens now is that command() in qemu-io-cmds.c can extend the + * permissions if necessary for the qemu-io command. And they simply stay + * extended, possibly resulting in a read-only guest device keeping write + * permissions. Ugly, but it appears to be the lesser evil. + */ + qemuio_command(blk, command); + +fail: + blk_unref(local_blk); + hmp_handle_error(mon, err); +} diff --git a/include/block/block-hmp-commands.h b/include/block/block-hmp-commands.h index 721b9a1978..99145c8fcf 100644 --- a/include/block/block-hmp-commands.h +++ b/include/block/block-hmp-commands.h @@ -26,4 +26,13 @@ void hmp_nbd_server_add(Monitor *mon, const QDict *qdict); void hmp_nbd_server_remove(Monitor *mon, const QDict *qdict); void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict); +void hmp_block_resize(Monitor *mon, const QDict *qdict); +void hmp_block_stream(Monitor *mon, const QDict *qdict); +void hmp_block_passwd(Monitor *mon, const QDict *qdict); +void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict); +void hmp_eject(Monitor *mon, const QDict *qdict); + +void hmp_qemu_io(Monitor *mon, const QDict *qdict); + + #endif diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h index 736a969131..47a7cad734 100644 --- a/include/monitor/hmp.h +++ b/include/monitor/hmp.h @@ -58,9 +58,7 @@ void hmp_cont(Monitor *mon, const QDict *qdict); void hmp_system_wakeup(Monitor *mon, const QDict *qdict); void hmp_nmi(Monitor *mon, const QDict *qdict); void hmp_set_link(Monitor *mon, const QDict *qdict); -void hmp_block_passwd(Monitor *mon, const QDict *qdict); void hmp_balloon(Monitor *mon, const QDict *qdict); -void hmp_block_resize(Monitor *mon, const QDict *qdict); void hmp_loadvm(Monitor *mon, const QDict *qdict); void hmp_savevm(Monitor *mon, const QDict *qdict); void hmp_delvm(Monitor *mon, const QDict *qdict); @@ -80,10 +78,7 @@ void hmp_migrate_start_postcopy(Monitor *mon, const QDict *qdict); void hmp_x_colo_lost_heartbeat(Monitor *mon, const QDict *qdict); void hmp_set_password(Monitor *mon, const QDict *qdict); void hmp_expire_password(Monitor *mon, const QDict *qdict); -void hmp_eject(Monitor *mon, const QDict *qdict); void hmp_change(Monitor *mon, const QDict *qdict); -void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict); -void hmp_block_stream(Monitor *mon, const QDict *qdict); void hmp_migrate(Monitor *mon, const QDict *qdict); void hmp_device_add(Monitor *mon, const QDict *qdict); void hmp_device_del(Monitor *mon, const QDict *qdict); @@ -98,7 +93,6 @@ void hmp_chardev_add(Monitor *mon, const QDict *qdict); void hmp_chardev_change(Monitor *mon, const QDict *qdict); void hmp_chardev_remove(Monitor *mon, const QDict *qdict); void hmp_chardev_send_break(Monitor *mon, const QDict *qdict); -void hmp_qemu_io(Monitor *mon, const QDict *qdict); void hmp_cpu_add(Monitor *mon, const QDict *qdict); void hmp_object_add(Monitor *mon, const QDict *qdict); void hmp_object_del(Monitor *mon, const QDict *qdict); diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index 67d2ca8a4c..c224e0f338 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -46,7 +46,6 @@ #include "qom/object_interfaces.h" #include "ui/console.h" #include "block/qapi.h" -#include "qemu-io.h" #include "qemu/cutils.h" #include "qemu/error-report.h" #include "exec/ramlist.h" @@ -1307,16 +1306,6 @@ void hmp_set_link(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, err); } -void hmp_block_passwd(Monitor *mon, const QDict *qdict) -{ - const char *device = qdict_get_str(qdict, "device"); - const char *password = qdict_get_str(qdict, "password"); - Error *err = NULL; - - qmp_block_passwd(true, device, false, NULL, password, &err); - hmp_handle_error(mon, err); -} - void hmp_balloon(Monitor *mon, const QDict *qdict) { int64_t value = qdict_get_int(qdict, "value"); @@ -1326,16 +1315,6 @@ void hmp_balloon(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, err); } -void hmp_block_resize(Monitor *mon, const QDict *qdict) -{ - const char *device = qdict_get_str(qdict, "device"); - int64_t size = qdict_get_int(qdict, "size"); - Error *err = NULL; - - qmp_block_resize(true, device, false, NULL, size, &err); - hmp_handle_error(mon, err); -} - void hmp_loadvm(Monitor *mon, const QDict *qdict) { int saved_vm_running = runstate_is_running(); @@ -1818,15 +1797,6 @@ void hmp_expire_password(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, err); } -void hmp_eject(Monitor *mon, const QDict *qdict) -{ - bool force = qdict_get_try_bool(qdict, "force", false); - const char *device = qdict_get_str(qdict, "device"); - Error *err = NULL; - - qmp_eject(true, device, false, NULL, true, force, &err); - hmp_handle_error(mon, err); -} #ifdef CONFIG_VNC static void hmp_change_read_arg(void *opaque, const char *password, @@ -1884,49 +1854,6 @@ void hmp_change(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, err); } -void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict) -{ - Error *err = NULL; - char *device = (char *) qdict_get_str(qdict, "device"); - BlockIOThrottle throttle = { - .bps = qdict_get_int(qdict, "bps"), - .bps_rd = qdict_get_int(qdict, "bps_rd"), - .bps_wr = qdict_get_int(qdict, "bps_wr"), - .iops = qdict_get_int(qdict, "iops"), - .iops_rd = qdict_get_int(qdict, "iops_rd"), - .iops_wr = qdict_get_int(qdict, "iops_wr"), - }; - - /* qmp_block_set_io_throttle has separate parameters for the - * (deprecated) block device name and the qdev ID but the HMP - * version has only one, so we must decide which one to pass. */ - if (blk_by_name(device)) { - throttle.has_device = true; - throttle.device = device; - } else { - throttle.has_id = true; - throttle.id = device; - } - - qmp_block_set_io_throttle(&throttle, &err); - hmp_handle_error(mon, err); -} - -void hmp_block_stream(Monitor *mon, const QDict *qdict) -{ - Error *error = NULL; - const char *device = qdict_get_str(qdict, "device"); - const char *base = qdict_get_try_str(qdict, "base"); - int64_t speed = qdict_get_try_int(qdict, "speed", 0); - - qmp_block_stream(true, device, device, base != NULL, base, false, NULL, - false, NULL, qdict_haskey(qdict, "speed"), speed, true, - BLOCKDEV_ON_ERROR_REPORT, false, false, false, false, - &error); - - hmp_handle_error(mon, error); -} - typedef struct HMPMigrationStatus { QEMUTimer *timer; @@ -2219,70 +2146,6 @@ void hmp_chardev_send_break(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, local_err); } -void hmp_qemu_io(Monitor *mon, const QDict *qdict) -{ - BlockBackend *blk; - BlockBackend *local_blk = NULL; - bool qdev = qdict_get_try_bool(qdict, "qdev", false); - const char* device = qdict_get_str(qdict, "device"); - const char* command = qdict_get_str(qdict, "command"); - Error *err = NULL; - int ret; - - if (qdev) { - blk = blk_by_qdev_id(device, &err); - if (!blk) { - goto fail; - } - } else { - blk = blk_by_name(device); - if (!blk) { - BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err); - if (bs) { - blk = local_blk = blk_new(bdrv_get_aio_context(bs), - 0, BLK_PERM_ALL); - ret = blk_insert_bs(blk, bs, &err); - if (ret < 0) { - goto fail; - } - } else { - goto fail; - } - } - } - - /* - * Notably absent: Proper permission management. This is sad, but it seems - * almost impossible to achieve without changing the semantics and thereby - * limiting the use cases of the qemu-io HMP command. - * - * In an ideal world we would unconditionally create a new BlockBackend for - * qemuio_command(), but we have commands like 'reopen' and want them to - * take effect on the exact BlockBackend whose name the user passed instead - * of just on a temporary copy of it. - * - * Another problem is that deleting the temporary BlockBackend involves - * draining all requests on it first, but some qemu-iotests cases want to - * issue multiple aio_read/write requests and expect them to complete in - * the background while the monitor has already returned. - * - * This is also what prevents us from saving the original permissions and - * restoring them later: We can't revoke permissions until all requests - * have completed, and we don't know when that is nor can we really let - * anything else run before we have revoken them to avoid race conditions. - * - * What happens now is that command() in qemu-io-cmds.c can extend the - * permissions if necessary for the qemu-io command. And they simply stay - * extended, possibly resulting in a read-only guest device keeping write - * permissions. Ugly, but it appears to be the lesser evil. - */ - qemuio_command(blk, command); - -fail: - blk_unref(local_blk); - hmp_handle_error(mon, err); -} - void hmp_object_del(Monitor *mon, const QDict *qdict) { const char *id = qdict_get_str(qdict, "id");
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> --- block/monitor/block-hmp-cmds.c | 138 +++++++++++++++++++++++++++++ include/block/block-hmp-commands.h | 9 ++ include/monitor/hmp.h | 6 -- monitor/hmp-cmds.c | 137 ---------------------------- 4 files changed, 147 insertions(+), 143 deletions(-)