[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 06/47] qmp: add block-job-pause and block-job-resume
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PATCH 06/47] qmp: add block-job-pause and block-job-resume |
Date: |
Tue, 24 Jul 2012 13:03:44 +0200 |
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. Right now,
jobs do not see the difference between a forced and a normal resume.
This can be changed in the future if needed.
Signed-off-by: Paolo Bonzini <address@hidden>
---
blockdev.c | 35 +++++++++++++++++++++++++++++++++--
hmp-commands.hx | 35 ++++++++++++++++++++++++++++++++---
hmp.c | 23 ++++++++++++++++++++++-
hmp.h | 2 ++
qapi-schema.json | 47 +++++++++++++++++++++++++++++++++++++++++++++--
qmp-commands.hx | 12 +++++++++++-
trace-events | 2 ++
7 files changed, 147 insertions(+), 9 deletions(-)
diff --git a/blockdev.c b/blockdev.c
index 33ac7e0..d29a408 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1147,15 +1147,20 @@ 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) {
+ if (job->paused && !force) {
error_set(errp, QERR_BLOCK_JOB_PAUSED, device);
return;
}
@@ -1164,6 +1169,32 @@ void qmp_block_job_cancel(const char *device, Error
**errp)
block_job_cancel(job);
}
+void qmp_block_job_pause(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_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_resume(job);
+ block_job_resume(job);
+}
+
static void do_qmp_query_block_jobs_one(void *opaque, BlockDriverState *bs)
{
BlockJobInfoList **prev = opaque;
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 9bbc7f7..3c60626 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -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,
},
@@ -112,6 +113,34 @@ 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
address@hidden block_job_pause
address@hidden 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
address@hidden block_job_resume
address@hidden block_job_resume
+Resume a paused block streaming operation.
+ETEXI
+
+ {
.name = "eject",
.args_type = "force:-f,device:B",
.params = "[-f] device",
diff --git a/hmp.c b/hmp.c
index 6b72a64..a4c6629 100644
--- a/hmp.c
+++ b/hmp.c
@@ -865,8 +865,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);
}
diff --git a/hmp.h b/hmp.h
index 8d2b0d7..39a71c4 100644
--- a/hmp.h
+++ b/hmp.h
@@ -59,6 +59,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);
diff --git a/qapi-schema.json b/qapi-schema.json
index f52ce3c..ef7caab 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1686,13 +1686,56 @@
#
# @device: the device name
#
+# @force: #optional whether to allow cancellation of a paused job (default
false)
+#
# Returns: Nothing on success
# If no background operation is active on this device,
BlockJobNotActive
-# If the job is currently paused, BlockJobPaused
+# If the job is paused and force is absent or false, BlockJobPaused
#
# 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.
+#
+# 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.2
+##
+{ '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 for cancellation. It is an error to call this command if no
+# operation is in progress.
+#
+# @device: the device name
+#
+# Returns: Nothing on success
+# If no background operation is active on this device, DeviceNotActive
+# If cancellation already in progress, DeviceInUse
+#
+# Since: 1.2
+##
+{ 'command': 'block-job-resume', 'data': { 'device': 'str' } }
##
# @ObjectTypeInfo:
diff --git a/qmp-commands.hx b/qmp-commands.hx
index e3cf3c5..f0c98a1 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -730,10 +730,20 @@ 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",
.mhandler.cmd_new = qmp_marshal_input_transaction,
diff --git a/trace-events b/trace-events
index 2034353..416b723 100644
--- a/trace-events
+++ b/trace-events
@@ -77,6 +77,8 @@ stream_start(void *bs, void *base, void *s, void *co, void
*opaque) "bs %p base
# 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_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"
--
1.7.10.4
- Re: [Qemu-devel] [PATCH 02/47] qerror/block: introduce QERR_BLOCK_JOB_NOT_ACTIVE, (continued)
[Qemu-devel] [PATCH 05/47] block: add support for job pause/resume, Paolo Bonzini, 2012/07/24
[Qemu-devel] [PATCH 04/47] block: add block_job_query, Paolo Bonzini, 2012/07/24
[Qemu-devel] [PATCH 06/47] qmp: add block-job-pause and block-job-resume,
Paolo Bonzini <=
[Qemu-devel] [PATCH 03/47] block: move job APIs to separate files, Paolo Bonzini, 2012/07/24
[Qemu-devel] [PATCH 07/47] qemu-iotests: add test for pausing a streaming operation, Paolo Bonzini, 2012/07/24
[Qemu-devel] [PATCH 08/47] block: rename block_job_complete to block_job_completed, Paolo Bonzini, 2012/07/24
[Qemu-devel] [PATCH 10/47] block: move BlockdevOnError declaration to QAPI, Paolo Bonzini, 2012/07/24
[Qemu-devel] [PATCH 09/47] block: rename BlockErrorAction, BlockQMPEventAction, Paolo Bonzini, 2012/07/24
[Qemu-devel] [PATCH 12/47] block: sort BlockDeviceIoStatus errors by severity, Paolo Bonzini, 2012/07/24
[Qemu-devel] [PATCH 13/47] block: introduce block job error, Paolo Bonzini, 2012/07/24
[Qemu-devel] [PATCH 11/47] block: reorganize io error code, Paolo Bonzini, 2012/07/24