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:
parent
2d47c6e9aa
commit
370521a1d6
@ -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 } }
|
||||
|
19
blockdev.c
19
blockdev.c
@ -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);
|
||||
}
|
||||
|
@ -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
10
hmp.c
@ -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
1
hmp.h
@ -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
|
||||
|
@ -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;
|
||||
|
@ -37,6 +37,7 @@ typedef enum MonitorEvent {
|
||||
QEVENT_SPICE_INITIALIZED,
|
||||
QEVENT_SPICE_DISCONNECTED,
|
||||
QEVENT_BLOCK_JOB_COMPLETED,
|
||||
QEVENT_BLOCK_JOB_CANCELLED,
|
||||
QEVENT_MAX,
|
||||
} MonitorEvent;
|
||||
|
||||
|
@ -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' } }
|
||||
|
@ -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?",
|
||||
|
@ -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"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user