qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
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

  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).