From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com, stefanha@linux.vnet.ibm.com, lcapitulino@redhat.com
Subject: [Qemu-devel] [RFC PATCH 05/36] block: add support for job pause/resume
Date: Fri, 15 Jun 2012 17:05:28 +0200 [thread overview]
Message-ID: <1339772759-31004-6-git-send-email-pbonzini@redhat.com> (raw)
In-Reply-To: <1339772759-31004-1-git-send-email-pbonzini@redhat.com>
Job pausing reuses the existing support for cancellable sleeps. A pause
happens at the next sleeping point and lasts until the coroutine is
re-entered explicitly. Cancellation was already doing a forced resume,
so implement it explicitly in terms of resume.
Paused jobs cannot be canceled without first resuming them. This ensures
that I/O errors are never missed by management.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
blockdev.c | 4 ++++
blockjob.c | 35 ++++++++++++++++++++++++++++++-----
blockjob.h | 30 ++++++++++++++++++++++++++++++
qapi-schema.json | 5 ++++-
qerror.c | 4 ++++
qerror.h | 3 +++
6 files changed, 75 insertions(+), 6 deletions(-)
diff --git a/blockdev.c b/blockdev.c
index 3dba4b8..8bf659a 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1159,6 +1159,10 @@ 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);
+ return;
+ }
trace_qmp_block_job_cancel(job);
block_job_cancel(job);
diff --git a/blockjob.c b/blockjob.c
index a947a6e..5d62191 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -99,14 +99,30 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
job->speed = speed;
}
-void block_job_cancel(BlockJob *job)
+void block_job_pause(BlockJob *job)
{
- job->cancelled = true;
+ job->paused = true;
+}
+
+bool block_job_is_paused(BlockJob *job)
+{
+ return job->paused;
+}
+
+void block_job_resume(BlockJob *job)
+{
+ job->paused = false;
if (job->co && !job->busy) {
qemu_coroutine_enter(job->co, NULL);
}
}
+void block_job_cancel(BlockJob *job)
+{
+ job->cancelled = true;
+ block_job_resume(job);
+}
+
bool block_job_is_cancelled(BlockJob *job)
{
return job->cancelled;
@@ -154,12 +170,20 @@ int block_job_cancel_sync(BlockJob *job)
void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns)
{
+ assert(job->busy);
+
/* Check cancellation *before* setting busy = false, too! */
- if (!block_job_is_cancelled(job)) {
- job->busy = false;
+ if (block_job_is_cancelled(job)) {
+ return;
+ }
+
+ job->busy = false;
+ if (block_job_is_paused(job)) {
+ qemu_coroutine_yield();
+ } else {
co_sleep_ns(clock, ns);
- job->busy = true;
}
+ job->busy = true;
}
BlockJobInfo *block_job_query(BlockJob *job)
@@ -168,6 +192,7 @@ BlockJobInfo *block_job_query(BlockJob *job)
info->type = g_strdup(job->job_type->job_type);
info->device = g_strdup(bdrv_get_device_name(job->bs));
info->len = job->len;
+ info->paused = job->paused;
info->offset = job->offset;
info->speed = job->speed;
return info;
diff --git a/blockjob.h b/blockjob.h
index 32854b8..d35c65b 100644
--- a/blockjob.h
+++ b/blockjob.h
@@ -72,6 +72,12 @@ struct BlockJob {
bool cancelled;
/**
+ * Set to true if the job is either paused, or will pause itself
+ * as soon as possible (if busy == true).
+ */
+ bool paused;
+
+ /**
* Set to false by the job while it is in a quiescent state, where
* no I/O is pending and the job has yielded on any condition
* that is not detected by #qemu_aio_wait, such as a timer.
@@ -173,6 +179,30 @@ bool block_job_is_cancelled(BlockJob *job);
BlockJobInfo *block_job_query(BlockJob *job);
/**
+ * block_job_pause:
+ * @job: The job to be paused.
+ *
+ * Asynchronously pause the specified job.
+ */
+void block_job_pause(BlockJob *job);
+
+/**
+ * block_job_resume:
+ * @job: The job to be resumed.
+ *
+ * Resume the specified job.
+ */
+void block_job_resume(BlockJob *job);
+
+/**
+ * block_job_is_paused:
+ * @job: The job being queried.
+ *
+ * Returns whether the job is currently paused.
+ */
+bool block_job_is_paused(BlockJob *job);
+
+/**
* block_job_cancel_sync:
* @job: The job to be canceled.
*
diff --git a/qapi-schema.json b/qapi-schema.json
index 35c16f3..178549d 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -906,6 +906,8 @@
#
# @len: the maximum progress value
#
+# @paused: whether the job is paused
+#
# @offset: the current progress value
#
# @speed: the rate limit, bytes per second
@@ -914,7 +916,7 @@
##
{ 'type': 'BlockJobInfo',
'data': {'type': 'str', 'device': 'str', 'len': 'int',
- 'offset': 'int', 'speed': 'int'} }
+ 'offset': 'int', 'paused': 'bool', 'speed': 'int'} }
##
# @query-block-jobs:
@@ -1680,6 +1682,7 @@
#
# Returns: Nothing on success
# If no background operation is active on this device, BlockJobNotActive
+# If the job is currently paused, BlockJobPaused
#
# Since: 1.1
##
diff --git a/qerror.c b/qerror.c
index bc672a5..72183ec 100644
--- a/qerror.c
+++ b/qerror.c
@@ -64,6 +64,10 @@ static const QErrorStringTable qerror_table[] = {
.desc = "No active block job on device '%(name)'",
},
{
+ .error_fmt = QERR_BLOCK_JOB_PAUSED,
+ .desc = "The block job for device '%(name)' is currently paused",
+ },
+ {
.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 7cf7d22..d1baea0 100644
--- a/qerror.h
+++ b/qerror.h
@@ -67,6 +67,9 @@ QError *qobject_to_qerror(const QObject *obj);
#define QERR_BLOCK_JOB_NOT_ACTIVE \
"{ 'class': 'BlockJobNotActive', 'data': { 'name': %s } }"
+#define QERR_BLOCK_JOB_PAUSED \
+ "{ 'class': 'BlockJobPaused', 'data': { 'name': %s } }"
+
#define QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED \
"{ 'class': 'BlockFormatFeatureNotSupported', 'data': { 'format': %s, 'name': %s, 'feature': %s } }"
--
1.7.10.2
next prev parent reply other threads:[~2012-06-15 15:06 UTC|newest]
Thread overview: 65+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-06-15 15:05 [Qemu-devel] [RFC PATCH 00/36] A peek at the current block job patches Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 01/36] qapi: generalize documentation of streaming commands Paolo Bonzini
2012-06-15 16:45 ` Eric Blake
2012-07-11 16:00 ` Paolo Bonzini
2012-07-12 8:07 ` Kevin Wolf
2012-07-12 20:41 ` Blue Swirl
2012-07-13 9:13 ` Kevin Wolf
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 02/36] qerror/block: introduce QERR_BLOCK_JOB_NOT_ACTIVE Paolo Bonzini
2012-06-15 16:51 ` Eric Blake
2012-06-15 16:56 ` Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 03/36] block: move job APIs to separate files Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 04/36] block: add block_job_query Paolo Bonzini
2012-06-15 15:05 ` Paolo Bonzini [this message]
2012-06-15 17:22 ` [Qemu-devel] [RFC PATCH 05/36] block: add support for job pause/resume Eric Blake
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 06/36] qmp: add block-job-pause and block-job-resume Paolo Bonzini
2012-06-15 17:32 ` Eric Blake
2012-07-11 16:02 ` Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 07/36] qemu-iotests: add test for pausing a streaming operation Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 08/36] block: rename block_job_complete to block_job_completed Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 09/36] block: rename BlockErrorAction, BlockQMPEventAction Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 10/36] block: move BlockdevOnError declaration to QAPI Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 11/36] block: reorganize io error code Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 12/36] block: sort BlockDeviceIoStatus errors by severity Paolo Bonzini
2012-06-15 17:45 ` Eric Blake
2012-07-11 16:03 ` Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 13/36] block: introduce block job error Paolo Bonzini
2012-06-15 17:50 ` Eric Blake
2012-07-11 16:10 ` Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 14/36] stream: add on_error argument Paolo Bonzini
2012-06-15 17:58 ` Eric Blake
2012-07-11 16:12 ` Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 15/36] qemu-iotests: add tests for streaming error handling Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 16/36] block: add bdrv_query_info Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 17/36] block: add bdrv_query_stats Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 18/36] block: make device optional in BlockInfo Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 19/36] block: add target info to QMP query-blockjobs command Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 20/36] block: forward bdrv_iostatus_reset to block job Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 21/36] block: introduce new dirty bitmap functionality Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 22/36] block: add mirror job Paolo Bonzini
2012-06-15 18:20 ` Eric Blake
2012-07-12 13:45 ` Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 23/36] qmp: add drive-mirror command Paolo Bonzini
2012-06-15 20:12 ` Eric Blake
2012-07-11 16:23 ` Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 24/36] mirror: support querying target file Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 25/36] mirror: add support for on_source_error/on_target_error Paolo Bonzini
2012-06-15 21:12 ` Eric Blake
2012-07-11 16:28 ` Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 26/36] block: live snapshot documentation tweaks Paolo Bonzini
2012-06-15 21:14 ` Eric Blake
2012-07-11 16:16 ` Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 27/36] block: add bdrv_ensure_backing_file Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 28/36] block: add block-job-complete Paolo Bonzini
2012-06-15 21:42 ` Eric Blake
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 29/36] mirror: implement completion Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 30/36] add hierarchical bitmap data type and test cases Paolo Bonzini
2012-06-15 23:02 ` Eric Blake
2012-07-11 16:35 ` Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 31/36] block: implement dirty bitmap using HBitmap Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 32/36] block: make round_to_clusters public Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 33/36] mirror: perform COW if the cluster size is bigger than the granularity Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 34/36] block: return count of dirty sectors, not chunks Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 35/36] block: allow customizing the granularity of the dirty bitmap Paolo Bonzini
2012-06-15 15:05 ` [Qemu-devel] [RFC PATCH 36/36] mirror: allow customizing the granularity Paolo Bonzini
2012-06-15 23:24 ` Eric Blake
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1339772759-31004-6-git-send-email-pbonzini@redhat.com \
--to=pbonzini@redhat.com \
--cc=kwolf@redhat.com \
--cc=lcapitulino@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@linux.vnet.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).