mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-09-06 18:05:37 +00:00
qmp: add block-job-pause and block-job-resume
Add QMP commands matching the functionality. Paused jobs cannot be canceled without first resuming them. This ensures that I/O errors are never missed by management. However, an optional force argument can be specified to allow that. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
8acc72a4d2
commit
6e37fb811a
41
blockdev.c
41
blockdev.c
|
@ -1213,7 +1213,29 @@ void qmp_block_job_set_speed(const char *device, int64_t speed, Error **errp)
|
|||
block_job_set_speed(job, speed, errp);
|
||||
}
|
||||
|
||||
void qmp_block_job_cancel(const char *device, Error **errp)
|
||||
void qmp_block_job_cancel(const char *device,
|
||||
bool has_force, bool force, Error **errp)
|
||||
{
|
||||
BlockJob *job = find_block_job(device);
|
||||
|
||||
if (!has_force) {
|
||||
force = false;
|
||||
}
|
||||
|
||||
if (!job) {
|
||||
error_set(errp, QERR_BLOCK_JOB_NOT_ACTIVE, device);
|
||||
return;
|
||||
}
|
||||
if (job->paused && !force) {
|
||||
error_set(errp, QERR_BLOCK_JOB_PAUSED, device);
|
||||
return;
|
||||
}
|
||||
|
||||
trace_qmp_block_job_cancel(job);
|
||||
block_job_cancel(job);
|
||||
}
|
||||
|
||||
void qmp_block_job_pause(const char *device, Error **errp)
|
||||
{
|
||||
BlockJob *job = find_block_job(device);
|
||||
|
||||
|
@ -1221,13 +1243,22 @@ void qmp_block_job_cancel(const char *device, Error **errp)
|
|||
error_set(errp, QERR_BLOCK_JOB_NOT_ACTIVE, device);
|
||||
return;
|
||||
}
|
||||
if (job->paused) {
|
||||
error_set(errp, QERR_BLOCK_JOB_PAUSED, device);
|
||||
|
||||
trace_qmp_block_job_pause(job);
|
||||
block_job_pause(job);
|
||||
}
|
||||
|
||||
void qmp_block_job_resume(const char *device, Error **errp)
|
||||
{
|
||||
BlockJob *job = find_block_job(device);
|
||||
|
||||
if (!job) {
|
||||
error_set(errp, QERR_BLOCK_JOB_NOT_ACTIVE, device);
|
||||
return;
|
||||
}
|
||||
|
||||
trace_qmp_block_job_cancel(job);
|
||||
block_job_cancel(job);
|
||||
trace_qmp_block_job_resume(job);
|
||||
block_job_resume(job);
|
||||
}
|
||||
|
||||
static void do_qmp_query_block_jobs_one(void *opaque, BlockDriverState *bs)
|
||||
|
|
|
@ -99,9 +99,10 @@ ETEXI
|
|||
|
||||
{
|
||||
.name = "block_job_cancel",
|
||||
.args_type = "device:B",
|
||||
.params = "device",
|
||||
.help = "stop an active background block operation",
|
||||
.args_type = "force:-f,device:B",
|
||||
.params = "[-f] device",
|
||||
.help = "stop an active background block operation (use -f"
|
||||
"\n\t\t\t if the operation is currently paused)",
|
||||
.mhandler.cmd = hmp_block_job_cancel,
|
||||
},
|
||||
|
||||
|
@ -109,6 +110,34 @@ STEXI
|
|||
@item block_job_cancel
|
||||
@findex block_job_cancel
|
||||
Stop an active block streaming operation.
|
||||
ETEXI
|
||||
|
||||
{
|
||||
.name = "block_job_pause",
|
||||
.args_type = "device:B",
|
||||
.params = "device",
|
||||
.help = "pause an active background block operation",
|
||||
.mhandler.cmd = hmp_block_job_pause,
|
||||
},
|
||||
|
||||
STEXI
|
||||
@item block_job_pause
|
||||
@findex block_job_pause
|
||||
Pause an active block streaming operation.
|
||||
ETEXI
|
||||
|
||||
{
|
||||
.name = "block_job_resume",
|
||||
.args_type = "device:B",
|
||||
.params = "device",
|
||||
.help = "resume a paused background block operation",
|
||||
.mhandler.cmd = hmp_block_job_resume,
|
||||
},
|
||||
|
||||
STEXI
|
||||
@item block_job_resume
|
||||
@findex block_job_resume
|
||||
Resume a paused block streaming operation.
|
||||
ETEXI
|
||||
|
||||
{
|
||||
|
|
23
hmp.c
23
hmp.c
|
@ -950,8 +950,29 @@ void hmp_block_job_cancel(Monitor *mon, const QDict *qdict)
|
|||
{
|
||||
Error *error = NULL;
|
||||
const char *device = qdict_get_str(qdict, "device");
|
||||
bool force = qdict_get_try_bool(qdict, "force", 0);
|
||||
|
||||
qmp_block_job_cancel(device, &error);
|
||||
qmp_block_job_cancel(device, true, force, &error);
|
||||
|
||||
hmp_handle_error(mon, &error);
|
||||
}
|
||||
|
||||
void hmp_block_job_pause(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
Error *error = NULL;
|
||||
const char *device = qdict_get_str(qdict, "device");
|
||||
|
||||
qmp_block_job_pause(device, &error);
|
||||
|
||||
hmp_handle_error(mon, &error);
|
||||
}
|
||||
|
||||
void hmp_block_job_resume(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
Error *error = NULL;
|
||||
const char *device = qdict_get_str(qdict, "device");
|
||||
|
||||
qmp_block_job_resume(device, &error);
|
||||
|
||||
hmp_handle_error(mon, &error);
|
||||
}
|
||||
|
|
2
hmp.h
2
hmp.h
|
@ -64,6 +64,8 @@ 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);
|
||||
void hmp_block_job_pause(Monitor *mon, const QDict *qdict);
|
||||
void hmp_block_job_resume(Monitor *mon, const QDict *qdict);
|
||||
void hmp_migrate(Monitor *mon, const QDict *qdict);
|
||||
void hmp_device_del(Monitor *mon, const QDict *qdict);
|
||||
void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict);
|
||||
|
|
|
@ -1893,12 +1893,56 @@
|
|||
#
|
||||
# @device: the device name
|
||||
#
|
||||
# @force: #optional whether to allow cancellation of a paused job (default
|
||||
# false). Since 1.3.
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If no background operation is active on this device, DeviceNotActive
|
||||
#
|
||||
# Since: 1.1
|
||||
##
|
||||
{ 'command': 'block-job-cancel', 'data': { 'device': 'str' } }
|
||||
{ 'command': 'block-job-cancel', 'data': { 'device': 'str', '*force': 'bool' } }
|
||||
|
||||
##
|
||||
# @block-job-pause:
|
||||
#
|
||||
# Pause an active background block operation.
|
||||
#
|
||||
# This command returns immediately after marking the active background block
|
||||
# operation for pausing. It is an error to call this command if no
|
||||
# operation is in progress. Pausing an already paused job has no cumulative
|
||||
# effect; a single block-job-resume command will resume the job.
|
||||
#
|
||||
# The operation will pause as soon as possible. No event is emitted when
|
||||
# the operation is actually paused. Cancelling a paused job automatically
|
||||
# resumes it.
|
||||
#
|
||||
# @device: the device name
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If no background operation is active on this device, DeviceNotActive
|
||||
#
|
||||
# Since: 1.3
|
||||
##
|
||||
{ 'command': 'block-job-pause', 'data': { 'device': 'str' } }
|
||||
|
||||
##
|
||||
# @block-job-resume:
|
||||
#
|
||||
# Resume an active background block operation.
|
||||
#
|
||||
# This command returns immediately after resuming a paused background block
|
||||
# operation. It is an error to call this command if no operation is in
|
||||
# progress. Resuming an already running job is not an error.
|
||||
#
|
||||
# @device: the device name
|
||||
#
|
||||
# Returns: Nothing on success
|
||||
# If no background operation is active on this device, DeviceNotActive
|
||||
#
|
||||
# Since: 1.3
|
||||
##
|
||||
{ 'command': 'block-job-resume', 'data': { 'device': 'str' } }
|
||||
|
||||
##
|
||||
# @ObjectTypeInfo:
|
||||
|
|
|
@ -805,9 +805,19 @@ EQMP
|
|||
|
||||
{
|
||||
.name = "block-job-cancel",
|
||||
.args_type = "device:B",
|
||||
.args_type = "device:B,force:b?",
|
||||
.mhandler.cmd_new = qmp_marshal_input_block_job_cancel,
|
||||
},
|
||||
{
|
||||
.name = "block-job-pause",
|
||||
.args_type = "device:B",
|
||||
.mhandler.cmd_new = qmp_marshal_input_block_job_pause,
|
||||
},
|
||||
{
|
||||
.name = "block-job-resume",
|
||||
.args_type = "device:B",
|
||||
.mhandler.cmd_new = qmp_marshal_input_block_job_resume,
|
||||
},
|
||||
{
|
||||
.name = "transaction",
|
||||
.args_type = "actions:q",
|
||||
|
|
|
@ -79,6 +79,8 @@ commit_start(void *bs, void *base, void *top, void *s, void *co, void *opaque) "
|
|||
|
||||
# blockdev.c
|
||||
qmp_block_job_cancel(void *job) "job %p"
|
||||
qmp_block_job_pause(void *job) "job %p"
|
||||
qmp_block_job_resume(void *job) "job %p"
|
||||
block_job_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 a new issue