[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 25/47] block: add block-job-complete
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PATCH 25/47] block: add block-job-complete |
Date: |
Tue, 24 Jul 2012 13:04:03 +0200 |
While streaming can be dropped as soon as it progressed through the whole
image, mirroring needs to be completed manually for two reasons: 1) so that
management knows exactly when the VM switches to the target; 2) because
for other use cases such as replication, we may leave the operation running
for the whole life of the virtual machine.
Add a new block job command that manually completes background operations.
Signed-off-by: Paolo Bonzini <address@hidden>
---
blockdev.c | 13 +++++++++++++
blockjob.c | 10 ++++++++++
blockjob.h | 15 +++++++++++++++
hmp-commands.hx | 17 ++++++++++++++++-
hmp.c | 10 ++++++++++
hmp.h | 1 +
qapi-schema.json | 27 +++++++++++++++++++++++++++
qerror.c | 4 ++++
qerror.h | 3 +++
qmp-commands.hx | 5 +++++
trace-events | 1 +
11 files changed, 105 insertions(+), 1 deletion(-)
diff --git a/blockdev.c b/blockdev.c
index 49ade14..7544afc 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1200,6 +1200,19 @@ void qmp_block_job_resume(const char *device, Error
**errp)
block_job_resume(job);
}
+void qmp_block_job_complete(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_complete(job);
+ block_job_complete(job, errp);
+}
+
static void do_qmp_query_block_jobs_one(void *opaque, BlockDriverState *bs)
{
BlockJobInfoList **prev = opaque;
diff --git a/blockjob.c b/blockjob.c
index 651ee8d..e5b5e63 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -99,6 +99,16 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error
**errp)
job->speed = speed;
}
+void block_job_complete(BlockJob *job, Error **errp)
+{
+ if (job->paused || job->cancelled || !job->job_type->complete) {
+ error_set(errp, QERR_BLOCK_JOB_NOT_READY, job->bs->device_name);
+ return;
+ }
+
+ job->job_type->complete(job, errp);
+}
+
void block_job_pause(BlockJob *job)
{
job->paused = true;
diff --git a/blockjob.h b/blockjob.h
index 5e03b5d..61fdafb 100644
--- a/blockjob.h
+++ b/blockjob.h
@@ -47,6 +47,12 @@ typedef struct BlockJobType {
* of BlockJobInfo.
*/
void (*query)(BlockJob *job, BlockJobInfo *info);
+
+ /**
+ * Optional callback for job types whose completion must be triggered
+ * manually.
+ */
+ void (*complete)(BlockJob *job, Error **errp);
} BlockJobType;
/**
@@ -170,6 +176,15 @@ void block_job_set_speed(BlockJob *job, int64_t speed,
Error **errp);
void block_job_cancel(BlockJob *job);
/**
+ * block_job_complete:
+ * @job: The job to be completed.
+ * @errp: Error object.
+ *
+ * Synchronously complete the specified job.
+ */
+void block_job_complete(BlockJob *job, Error **errp);
+
+/**
* block_job_is_cancelled:
* @job: The job being queried.
*
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 3c60626..7a72122 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -109,7 +109,22 @@ ETEXI
STEXI
@item block_job_cancel
@findex block_job_cancel
-Stop an active block streaming operation.
+Stop an active background block operation (streaming, mirroring).
+ETEXI
+
+ {
+ .name = "block_job_complete",
+ .args_type = "device:B",
+ .params = "device",
+ .help = "stop an active background block operation",
+ .mhandler.cmd = hmp_block_job_complete,
+ },
+
+STEXI
address@hidden block_job_complete
address@hidden block_job_complete
+Manually trigger completion of an active background block operation.
+For mirroring, this will switch the device to the destination path.
ETEXI
{
diff --git a/hmp.c b/hmp.c
index 5d4e6ac..206e920 100644
--- a/hmp.c
+++ b/hmp.c
@@ -893,6 +893,16 @@ void hmp_block_job_resume(Monitor *mon, const QDict *qdict)
hmp_handle_error(mon, &error);
}
+void hmp_block_job_complete(Monitor *mon, const QDict *qdict)
+{
+ Error *error = NULL;
+ const char *device = qdict_get_str(qdict, "device");
+
+ qmp_block_job_complete(device, &error);
+
+ hmp_handle_error(mon, &error);
+}
+
typedef struct MigrationStatus
{
QEMUTimer *timer;
diff --git a/hmp.h b/hmp.h
index 39a71c4..24e551e 100644
--- a/hmp.h
+++ b/hmp.h
@@ -61,6 +61,7 @@ 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_block_job_complete(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 2697220..e081ddf 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1792,6 +1792,33 @@
{ 'command': 'block-job-resume', 'data': { 'device': 'str' } }
##
+# @block-job-complete:
+#
+# Manually trigger completion of an active background block operation. This
+# is supported for drive mirroring, where it also switches the device to
+# write to the target path only.
+#
+# This command completes an active background block operation synchronously.
+# The ordering of this command's return with the BLOCK_JOB_COMPLETED event
+# is not defined. Note that if an I/O error occurs during the processing of
+# this command: 1) the command itself will fail; 2) the error will be processed
+# according to the rerror/werror arguments that were specified when starting
+# the operation.
+#
+# A cancelled or paused job cannot be completed.
+#
+# @device: the device name
+#
+# Returns: Nothing on success
+# If no background operation is active on this device,
BlockJobNotActive
+# If the operation cannot be completed manually (either in general, or
+# not at the time the command is invoked), BlockJobNotReady
+#
+# Since: 1.2
+##
+{ 'command': 'block-job-complete', 'data': { 'device': 'str' } }
+
+##
# @ObjectTypeInfo:
#
# This structure describes a search result from @qom-list-types
diff --git a/qerror.c b/qerror.c
index 72183ec..60303a4 100644
--- a/qerror.c
+++ b/qerror.c
@@ -68,6 +68,10 @@ static const QErrorStringTable qerror_table[] = {
.desc = "The block job for device '%(name)' is currently paused",
},
{
+ .error_fmt = QERR_BLOCK_JOB_NOT_READY,
+ .desc = "The active block job for device '%(name)' cannot be
completed",
+ },
+ {
.error_fmt = QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
.desc = "Block format '%(format)' used by device '%(name)' does
not support feature '%(feature)'",
},
diff --git a/qerror.h b/qerror.h
index d1baea0..c15e933 100644
--- a/qerror.h
+++ b/qerror.h
@@ -70,6 +70,9 @@ QError *qobject_to_qerror(const QObject *obj);
#define QERR_BLOCK_JOB_PAUSED \
"{ 'class': 'BlockJobPaused', 'data': { 'name': %s } }"
+#define QERR_BLOCK_JOB_NOT_READY \
+ "{ 'class': 'BlockJobNotReady', 'data': { 'name': %s } }"
+
#define QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED \
"{ 'class': 'BlockFormatFeatureNotSupported', 'data': { 'format': %s,
'name': %s, 'feature': %s } }"
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 7026a4a..56f953d 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -744,6 +744,11 @@ EQMP
.mhandler.cmd_new = qmp_marshal_input_block_job_resume,
},
{
+ .name = "block-job-complete",
+ .args_type = "device:B",
+ .mhandler.cmd_new = qmp_marshal_input_block_job_complete,
+ },
+ {
.name = "transaction",
.args_type = "actions:q",
.mhandler.cmd_new = qmp_marshal_input_transaction,
diff --git a/trace-events b/trace-events
index 416b723..58dfe6c 100644
--- a/trace-events
+++ b/trace-events
@@ -79,6 +79,7 @@ stream_start(void *bs, void *base, void *s, void *co, void
*opaque) "bs %p base
qmp_block_job_cancel(void *job) "job %p"
qmp_block_job_pause(void *job) "job %p"
qmp_block_job_resume(void *job) "job %p"
+qmp_block_job_complete(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
- [Qemu-devel] [PATCH 18/47] block: live snapshot documentation tweaks, (continued)
- [Qemu-devel] [PATCH 18/47] block: live snapshot documentation tweaks, Paolo Bonzini, 2012/07/24
- [Qemu-devel] [PATCH 22/47] block: make device optional in BlockInfo, Paolo Bonzini, 2012/07/24
- [Qemu-devel] [PATCH 30/47] mirror: implement completion, Paolo Bonzini, 2012/07/24
- [Qemu-devel] [PATCH 28/47] qmp: add drive-mirror command, Paolo Bonzini, 2012/07/24
- [Qemu-devel] [PATCH 21/47] block: add bdrv_ensure_backing_file, Paolo Bonzini, 2012/07/24
- [Qemu-devel] [PATCH 35/47] qemu-iotests: add testcases for mirroring on-source-error/on-target-error, Paolo Bonzini, 2012/07/24
- [Qemu-devel] [PATCH 24/47] block: introduce new dirty bitmap functionality, Paolo Bonzini, 2012/07/24
- [Qemu-devel] [PATCH 45/47] mirror: add buf-size argument to drive-mirror, Paolo Bonzini, 2012/07/24
- [Qemu-devel] [PATCH 25/47] block: add block-job-complete,
Paolo Bonzini <=
- [Qemu-devel] [PATCH 43/47] mirror: allow customizing the granularity, Paolo Bonzini, 2012/07/24
[Qemu-devel] [PATCH 44/47] mirror: switch mirror_iteration to AIO, Paolo Bonzini, 2012/07/24
[Qemu-devel] [PATCH 38/47] block: implement dirty bitmap using HBitmap, Paolo Bonzini, 2012/07/24
Re: [Qemu-devel] [PATCH 00/47] Block job improvements for 1.2, Eric Blake, 2012/07/28