[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC PATCH 28/36] block: add block-job-complete
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [RFC PATCH 28/36] block: add block-job-complete |
Date: |
Fri, 15 Jun 2012 17:05:51 +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 4000d16..b46a86c 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1328,6 +1328,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 d3819df..602e669 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 02e0363..563b0a2 100644
--- a/blockjob.h
+++ b/blockjob.h
@@ -52,6 +52,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;
/**
@@ -175,6 +181,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 7ee8de8..47827bf 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 ce0d040..ef0b87f 100644
--- a/hmp.c
+++ b/hmp.c
@@ -920,6 +920,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 4e86083..61fadc1 100644
--- a/hmp.h
+++ b/hmp.h
@@ -62,6 +62,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 250edf2..bbcfa0e 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1840,6 +1840,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.1
+##
+{ '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 aff1660..f1b0f90 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 306faf6..65db490 100644
--- a/trace-events
+++ b/trace-events
@@ -83,6 +83,7 @@ mirror_one_iteration(void *s, int64_t sector_num) "s %p
sector_num %"PRId64
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_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"
--
1.7.10.2
- [Qemu-devel] [RFC PATCH 35/36] block: allow customizing the granularity of the dirty bitmap, (continued)
- [Qemu-devel] [RFC PATCH 35/36] block: allow customizing the granularity of the dirty bitmap, Paolo Bonzini, 2012/06/15
- [Qemu-devel] [RFC PATCH 36/36] mirror: allow customizing the granularity, Paolo Bonzini, 2012/06/15
- [Qemu-devel] [RFC PATCH 17/36] block: add bdrv_query_stats, Paolo Bonzini, 2012/06/15
- [Qemu-devel] [RFC PATCH 30/36] add hierarchical bitmap data type and test cases, Paolo Bonzini, 2012/06/15
- [Qemu-devel] [RFC PATCH 18/36] block: make device optional in BlockInfo, Paolo Bonzini, 2012/06/15
- [Qemu-devel] [RFC PATCH 16/36] block: add bdrv_query_info, Paolo Bonzini, 2012/06/15
- [Qemu-devel] [RFC PATCH 31/36] block: implement dirty bitmap using HBitmap, Paolo Bonzini, 2012/06/15
- [Qemu-devel] [RFC PATCH 27/36] block: add bdrv_ensure_backing_file, Paolo Bonzini, 2012/06/15
- [Qemu-devel] [RFC PATCH 28/36] block: add block-job-complete,
Paolo Bonzini <=
- [Qemu-devel] [RFC PATCH 32/36] block: make round_to_clusters public, Paolo Bonzini, 2012/06/15
- [Qemu-devel] [RFC PATCH 23/36] qmp: add drive-mirror command, Paolo Bonzini, 2012/06/15
- [Qemu-devel] [RFC PATCH 14/36] stream: add on_error argument, Paolo Bonzini, 2012/06/15