qmp: add block_job_cancel command

Add block_job_cancel, which stops an active block streaming operation.
When the operation has been cancelled the new BLOCK_JOB_CANCELLED event
is emitted.

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Acked-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2012-01-18 14:40:48 +00:00 committed by Kevin Wolf
parent 2d47c6e9aa
commit 370521a1d6
10 changed files with 107 additions and 1 deletions

View File

@ -293,3 +293,27 @@ Example:
"len": 10737418240, "offset": 10737418240,
"speed": 0 },
"timestamp": { "seconds": 1267061043, "microseconds": 959568 } }
BLOCK_JOB_CANCELLED
-------------------
Emitted when a block job has been cancelled.
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)
On success this is equal to len.
On failure this is less than len.
- "speed": Rate limit, bytes per second (json-int)
Example:
{ "event": "BLOCK_JOB_CANCELLED",
"data": { "type": "stream", "device": "virtio-disk0",
"len": 10737418240, "offset": 134217728,
"speed": 0 },
"timestamp": { "seconds": 1267061043, "microseconds": 959568 } }

View File

@ -928,7 +928,11 @@ static void block_stream_cb(void *opaque, int ret)
qdict_put(dict, "error", qstring_from_str(strerror(-ret)));
}
monitor_protocol_event(QEVENT_BLOCK_JOB_COMPLETED, obj);
if (block_job_is_cancelled(bs->job)) {
monitor_protocol_event(QEVENT_BLOCK_JOB_CANCELLED, obj);
} else {
monitor_protocol_event(QEVENT_BLOCK_JOB_COMPLETED, obj);
}
qobject_decref(obj);
}
@ -989,3 +993,16 @@ void qmp_block_job_set_speed(const char *device, int64_t value, Error **errp)
error_set(errp, QERR_NOT_SUPPORTED);
}
}
void qmp_block_job_cancel(const char *device, Error **errp)
{
BlockJob *job = find_block_job(device);
if (!job) {
error_set(errp, QERR_DEVICE_NOT_ACTIVE, device);
return;
}
trace_qmp_block_job_cancel(job);
block_job_cancel(job);
}

View File

@ -95,6 +95,20 @@ STEXI
@item block_job_set_stream
@findex block_job_set_stream
Set maximum speed for a background block operation.
ETEXI
{
.name = "block_job_cancel",
.args_type = "device:B",
.params = "device",
.help = "stop an active block streaming operation",
.mhandler.cmd = hmp_block_job_cancel,
},
STEXI
@item block_job_cancel
@findex block_job_cancel
Stop an active block streaming operation.
ETEXI
{

10
hmp.c
View File

@ -805,3 +805,13 @@ void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict)
hmp_handle_error(mon, &error);
}
void hmp_block_job_cancel(Monitor *mon, const QDict *qdict)
{
Error *error = NULL;
const char *device = qdict_get_str(qdict, "device");
qmp_block_job_cancel(device, &error);
hmp_handle_error(mon, &error);
}

1
hmp.h
View File

@ -56,5 +56,6 @@ 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_block_job_set_speed(Monitor *mon, const QDict *qdict);
void hmp_block_job_cancel(Monitor *mon, const QDict *qdict);
#endif

View File

@ -482,6 +482,9 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
case QEVENT_BLOCK_JOB_COMPLETED:
event_name = "BLOCK_JOB_COMPLETED";
break;
case QEVENT_BLOCK_JOB_CANCELLED:
event_name = "BLOCK_JOB_CANCELLED";
break;
default:
abort();
break;

View File

@ -37,6 +37,7 @@ typedef enum MonitorEvent {
QEVENT_SPICE_INITIALIZED,
QEVENT_SPICE_DISCONNECTED,
QEVENT_BLOCK_JOB_COMPLETED,
QEVENT_BLOCK_JOB_CANCELLED,
QEVENT_MAX,
} MonitorEvent;

View File

@ -1487,3 +1487,32 @@
##
{ 'command': 'block_job_set_speed',
'data': { 'device': 'str', 'value': 'int' } }
##
# @block_job_cancel:
#
# Stop an active block streaming operation.
#
# This command returns immediately after marking the active block streaming
# operation for cancellation. It is an error to call this command if no
# operation is in progress.
#
# The operation will cancel as soon as possible and then emit the
# BLOCK_JOB_CANCELLED event. Before that happens the job is still visible when
# enumerated using query-block-jobs.
#
# The image file retains its backing file unless the streaming operation happens
# to complete just as it is being cancelled.
#
# A new block streaming operation can be started at a later time to finish
# copying all data from the backing file.
#
# @device: the device name
#
# Returns: Nothing on success
# If streaming is not active on this device, DeviceNotActive
# If cancellation already in progress, DeviceInUse
#
# Since: 1.1
##
{ 'command': 'block_job_cancel', 'data': { 'device': 'str' } }

View File

@ -660,6 +660,12 @@ EQMP
.mhandler.cmd_new = qmp_marshal_input_block_job_set_speed,
},
{
.name = "block_job_cancel",
.args_type = "device:B",
.mhandler.cmd_new = qmp_marshal_input_block_job_cancel,
},
{
.name = "blockdev-snapshot-sync",
.args_type = "device:B,snapshot-file:s,format:s?",

View File

@ -75,6 +75,7 @@ stream_one_iteration(void *s, int64_t sector_num, int nb_sectors, int is_allocat
stream_start(void *bs, void *base, void *s, void *co, void *opaque) "bs %p base %p s %p co %p opaque %p"
# blockdev.c
qmp_block_job_cancel(void *job) "job %p"
block_stream_cb(void *bs, void *job, int ret) "bs %p job %p ret %d"
qmp_block_stream(void *bs, void *job) "bs %p job %p"