Add query-block-jobs, which shows the progress of ongoing block device operations.
Signed-off-by: Stefan Hajnoczi <stefa...@linux.vnet.ibm.com> --- blockdev.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ blockdev.h | 2 ++ monitor.c | 16 ++++++++++++++++ qmp-commands.hx | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 0 deletions(-) diff --git a/blockdev.c b/blockdev.c index 5ad7d3b..6d78597 100644 --- a/blockdev.c +++ b/blockdev.c @@ -919,3 +919,49 @@ int do_block_job_cancel(Monitor *mon, const QDict *params, block_job_cancel(job, do_block_job_cancel_cb, cancel_data); return 0; } + +static void monitor_print_block_jobs_one(QObject *info, void *opaque) +{ + QDict *stream = qobject_to_qdict(info); + Monitor *mon = opaque; + + /* TODO libvirt searches for "Streaming device" but this might be a + * non-stream job */ + monitor_printf(mon, "Streaming device %s: Completed %" PRId64 " of %" + PRId64 " bytes, speed limit %" PRId64 " bytes/s\n", + qdict_get_str(stream, "device"), + qdict_get_int(stream, "offset"), + qdict_get_int(stream, "len"), + qdict_get_int(stream, "speed")); +} + +void monitor_print_block_jobs(Monitor *mon, const QObject *data) +{ + QList *list = qobject_to_qlist(data); + + assert(list); + + if (qlist_empty(list)) { + monitor_printf(mon, "No active jobs\n"); + return; + } + + qlist_iter(list, monitor_print_block_jobs_one, mon); +} + +static void do_info_block_jobs_one(void *opaque, BlockDriverState *bs) +{ + QList *list = opaque; + BlockJob *job = bs->job; + + if (job) { + qlist_append_obj(list, qobject_from_block_job(job)); + } +} + +void do_info_block_jobs(Monitor *mon, QObject **ret_data) +{ + QList *list = qlist_new(); + bdrv_iterate(do_info_block_jobs_one, list); + *ret_data = QOBJECT(list); +} diff --git a/blockdev.h b/blockdev.h index 7d3db30..9bfc33d 100644 --- a/blockdev.h +++ b/blockdev.h @@ -71,5 +71,7 @@ int do_block_job_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data); int do_block_job_cancel(Monitor *mon, const QDict *params, MonitorCompletion *cb, void *opaque); +void monitor_print_block_jobs(Monitor *mon, const QObject *data); +void do_info_block_jobs(Monitor *mon, QObject **ret_data); #endif diff --git a/monitor.c b/monitor.c index 38addcf..ad878af 100644 --- a/monitor.c +++ b/monitor.c @@ -2786,6 +2786,14 @@ static const mon_cmd_t info_cmds[] = { .mhandler.info_new = bdrv_info_stats, }, { + .name = "block-jobs", + .args_type = "", + .params = "", + .help = "show progress of ongoing block device operations", + .user_print = monitor_print_block_jobs, + .mhandler.info_new = do_info_block_jobs, + }, + { .name = "registers", .args_type = "", .params = "", @@ -3080,6 +3088,14 @@ static const mon_cmd_t qmp_query_cmds[] = { .mhandler.info_new = bdrv_info_stats, }, { + .name = "block-jobs", + .args_type = "", + .params = "", + .help = "show progress of ongoing block device operations", + .user_print = monitor_print_block_jobs, + .mhandler.info_new = do_info_block_jobs, + }, + { .name = "cpus", .args_type = "", .params = "", diff --git a/qmp-commands.hx b/qmp-commands.hx index 741c2f8..6e8207b 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -2089,3 +2089,35 @@ Example: EQMP +SQMP + +query-block-jobs +---------------- + +Show progress of ongoing block device operations. + +Return a json-array of all block device operations. If no operation is active +then return an empty array. Each operation is a json-object with the following +data: + +- type: job type ("stream" for image streaming, json-string) +- device: device name (json-string) +- len: maximum progress value (json-int) +- offset: current progress value (json-int) +- speed: rate limit, bytes per second (json-int) + +Progress can be observed as offset increases and it reaches len when the +operation completes. Offset and len have undefined units but can be used to +calculate a percentage indicating the progress that has been made. + +Example: + +-> { "execute": "query-block-jobs" } +<- { "return":[ + { "type": "stream", "device": "virtio0", + "len": 10737418240, "offset": 709632, + "speed": 0 } + ] + } + +EQMP -- 1.7.7