All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: Fam Zheng <famz@redhat.com>, qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>, Jeff Cody <jcody@redhat.com>,
	berto@igalia.com, qemu-block@nongnu.org,
	Stefan Hajnoczi <stefanha@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v2 1/4] blockjob: Allow nested pause
Date: Fri, 03 Apr 2015 16:13:55 +0200	[thread overview]
Message-ID: <551EA023.8010205@redhat.com> (raw)
In-Reply-To: <1428069921-2957-2-git-send-email-famz@redhat.com>



On 03/04/2015 16:05, Fam Zheng wrote:
> This patch changes block_job_pause to increase the pause counter and
> block_job_resume to decrease it.
> 
> The counter will allow calling block_job_pause/block_job_resume
> unconditionally on a job when we need to suspend the IO temporarily.
> 
> From now on, each block_job_resume must be paired with a block_job_pause
> to keep the counter balanced.
> 
> The user pause from QMP or HMP will only trigger block_job_pause once
> until it's resumed, this is achieved by adding a user_paused flag in
> BlockJob.
> 
> One occurrence of block_job_resume in mirror_complete is replaced with
> block_job_enter which does what is necessary.
> 
> In block_job_cancel, the cancel flag is good enough to instruct
> coroutines to quit loop, so use block_job_enter to replace the unpaired
> block_job_resume.
> 
> Upon block job IO error, user is notified about the entering to the
> pause state, so this pause belongs to user pause, set the flag
> accordingly and expect a matching QMP resume.
> 
> Signed-off-by: Fam Zheng <famz@redhat.com>
> ---
>  block/mirror.c           |  2 +-
>  blockdev.c               |  8 +++++---
>  blockjob.c               | 23 +++++++++++++++++------
>  include/block/blockjob.h | 20 ++++++++++++++++----
>  4 files changed, 39 insertions(+), 14 deletions(-)
> 
> diff --git a/block/mirror.c b/block/mirror.c
> index 4056164..65b1718 100644
> --- a/block/mirror.c
> +++ b/block/mirror.c
> @@ -634,7 +634,7 @@ static void mirror_complete(BlockJob *job, Error **errp)
>      }
>  
>      s->should_complete = true;
> -    block_job_resume(job);
> +    block_job_enter(&s->common);
>  }
>  
>  static const BlockJobDriver mirror_job_driver = {
> diff --git a/blockdev.c b/blockdev.c
> index fbb3a79..9132d69 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -2699,7 +2699,7 @@ void qmp_block_job_cancel(const char *device,
>          force = false;
>      }
>  
> -    if (job->paused && !force) {
> +    if (job->user_paused && !force) {
>          error_setg(errp, "The block job for device '%s' is currently paused",
>                     device);
>          goto out;
> @@ -2716,10 +2716,11 @@ void qmp_block_job_pause(const char *device, Error **errp)
>      AioContext *aio_context;
>      BlockJob *job = find_block_job(device, &aio_context, errp);
>  
> -    if (!job) {
> +    if (!job || job->user_paused) {
>          return;
>      }
>  
> +    job->user_paused = true;
>      trace_qmp_block_job_pause(job);
>      block_job_pause(job);
>      aio_context_release(aio_context);
> @@ -2730,10 +2731,11 @@ void qmp_block_job_resume(const char *device, Error **errp)
>      AioContext *aio_context;
>      BlockJob *job = find_block_job(device, &aio_context, errp);
>  
> -    if (!job) {
> +    if (!job || !job->user_paused) {
>          return;
>      }
>  
> +    job->user_paused = false;
>      trace_qmp_block_job_resume(job);
>      block_job_resume(job);
>      aio_context_release(aio_context);
> diff --git a/blockjob.c b/blockjob.c
> index ba2255d..2755465 100644
> --- a/blockjob.c
> +++ b/blockjob.c
> @@ -107,7 +107,7 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
>  
>  void block_job_complete(BlockJob *job, Error **errp)
>  {
> -    if (job->paused || job->cancelled || !job->driver->complete) {
> +    if (job->pause_count || job->cancelled || !job->driver->complete) {
>          error_set(errp, QERR_BLOCK_JOB_NOT_READY,
>                    bdrv_get_device_name(job->bs));
>          return;
> @@ -118,17 +118,26 @@ void block_job_complete(BlockJob *job, Error **errp)
>  
>  void block_job_pause(BlockJob *job)
>  {
> -    job->paused = true;
> +    job->pause_count++;
>  }
>  
>  bool block_job_is_paused(BlockJob *job)
>  {
> -    return job->paused;
> +    return job->pause_count > 0;
>  }
>  
>  void block_job_resume(BlockJob *job)
>  {
> -    job->paused = false;
> +    assert(job->pause_count > 0);
> +    job->pause_count--;
> +    if (job->pause_count) {
> +        return;
> +    }
> +    block_job_enter(job);
> +}
> +
> +void block_job_enter(BlockJob *job)
> +{
>      block_job_iostatus_reset(job);
>      if (job->co && !job->busy) {
>          qemu_coroutine_enter(job->co, NULL);
> @@ -138,7 +147,7 @@ void block_job_resume(BlockJob *job)
>  void block_job_cancel(BlockJob *job)
>  {
>      job->cancelled = true;
> -    block_job_resume(job);
> +    block_job_enter(job);
>  }
>  
>  bool block_job_is_cancelled(BlockJob *job)
> @@ -258,7 +267,7 @@ BlockJobInfo *block_job_query(BlockJob *job)
>      info->device    = g_strdup(bdrv_get_device_name(job->bs));
>      info->len       = job->len;
>      info->busy      = job->busy;
> -    info->paused    = job->paused;
> +    info->paused    = job->pause_count > 0;
>      info->offset    = job->offset;
>      info->speed     = job->speed;
>      info->io_status = job->iostatus;
> @@ -335,6 +344,8 @@ BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs,
>                                      IO_OPERATION_TYPE_WRITE,
>                                      action, &error_abort);
>      if (action == BLOCK_ERROR_ACTION_STOP) {
> +        /* make the pause user visible, which will be resumed from QMP. */
> +        job->user_paused = true;
>          block_job_pause(job);
>          block_job_iostatus_set_err(job, error);
>          if (bs != job->bs) {
> diff --git a/include/block/blockjob.h b/include/block/blockjob.h
> index b6d4ebb..9f4b20d 100644
> --- a/include/block/blockjob.h
> +++ b/include/block/blockjob.h
> @@ -79,10 +79,14 @@ struct BlockJob {
>      bool cancelled;
>  
>      /**
> -     * Set to true if the job is either paused, or will pause itself
> -     * as soon as possible (if busy == true).
> +     * Counter for pause request. If non-zero, the block job will pause.

Why not keep the more complete comment ("If non-zero, the block job is
either paused, or if busy == true will pause itself as soon as possible")?

>       */
> -    bool paused;
> +    int pause_count;
> +
> +    /**
> +     * Set to true if the job is paused by user.

... and can be unpaused with the block-job-resume QMP command.

> +     */
> +    bool user_paused;
>  
>      /**
>       * Set to false by the job while it is in a quiescent state, where
> @@ -225,11 +229,19 @@ void block_job_pause(BlockJob *job);
>   * block_job_resume:
>   * @job: The job to be resumed.
>   *
> - * Resume the specified job.
> + * Resume the specified job.  Must be paired with a preceding block_job_pause.
>   */
>  void block_job_resume(BlockJob *job);
>  
>  /**
> + * block_job_enter:
> + * @job: The job to enter.
> + *
> + * Continue the specified job by entering the coroutine.
> + */
> +void block_job_enter(BlockJob *job);
> +
> +/**
>   * block_job_event_cancelled:
>   * @job: The job whose information is requested.
>   *
> 

Apart from this,

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>

  reply	other threads:[~2015-04-03 14:14 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-04-03 14:05 [Qemu-devel] [PATCH v2 0/4] Fix "stop" draining block jobs Fam Zheng
2015-04-03 14:05 ` [Qemu-devel] [PATCH v2 1/4] blockjob: Allow nested pause Fam Zheng
2015-04-03 14:13   ` Paolo Bonzini [this message]
2015-04-20 17:11     ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi
2015-04-08  7:25   ` [Qemu-devel] " Alberto Garcia
2015-04-08 10:31   ` Stefan Hajnoczi
2015-04-03 14:05 ` [Qemu-devel] [PATCH v2 2/4] block: Pause block jobs in bdrv_drain_all Fam Zheng
2015-04-07 13:59   ` Alberto Garcia
2015-04-08 10:37   ` Stefan Hajnoczi
2015-04-08 14:56     ` Alberto Garcia
2015-04-09 10:34       ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi
2015-04-03 14:05 ` [Qemu-devel] [PATCH v2 3/4] qemu-iotests: Test that "stop" doesn't drain block jobs Fam Zheng
2015-04-07 14:46   ` Alberto Garcia
2015-04-08 10:39   ` Stefan Hajnoczi
2015-04-24 15:43   ` [Qemu-devel] [Qemu-block] " Max Reitz
2015-04-27  5:14     ` Fam Zheng
2015-04-27 11:08       ` Max Reitz
2015-04-03 14:05 ` [Qemu-devel] [PATCH v2 4/4] blockjob: Update function name in comments Fam Zheng
2015-04-07 14:46   ` Alberto Garcia
2015-04-08 10:40 ` [Qemu-devel] [PATCH v2 0/4] Fix "stop" draining block jobs Stefan Hajnoczi
2015-04-20 15:38 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi

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=551EA023.8010205@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=berto@igalia.com \
    --cc=famz@redhat.com \
    --cc=jcody@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.