qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Jeff Cody <jcody@redhat.com>
To: John Snow <jsnow@redhat.com>
Cc: qemu-block@nongnu.org, kwolf@redhat.com,
	vsementsov@virtuozzo.com, stefanha@redhat.com,
	pbonzini@redhat.com, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v3 2/6] blockjob: add .clean property
Date: Mon, 7 Nov 2016 21:51:51 -0500	[thread overview]
Message-ID: <20161108025151.GD23932@localhost.localdomain> (raw)
In-Reply-To: <1478109056-25198-3-git-send-email-jsnow@redhat.com>

On Wed, Nov 02, 2016 at 01:50:52PM -0400, John Snow wrote:
> Cleaning up after we have deferred to the main thread but before the
> transaction has converged can be dangerous and result in deadlocks
> if the job cleanup invokes any BH polling loops.
> 
> A job may attempt to begin cleaning up, but may induce another job to
> enter its cleanup routine. The second job, part of our same transaction,
> will block waiting for the first job to finish, so neither job may now
> make progress.
> 
> To rectify this, allow jobs to register a cleanup operation that will
> always run regardless of if the job was in a transaction or not, and
> if the transaction job group completed successfully or not.
> 
> Move sensitive cleanup to this callback instead which is guaranteed to
> be run only after the transaction has converged, which removes sensitive
> timing constraints from said cleanup.
> 
> Furthermore, in future patches these cleanup operations will be performed
> regardless of whether or not we actually started the job. Therefore,
> cleanup callbacks should essentially confine themselves to undoing create
> operations, e.g. setup actions taken in what is now backup_start.
> 
> Reported-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
> Signed-off-by: John Snow <jsnow@redhat.com>
> ---
>  block/backup.c               | 15 ++++++++++-----
>  blockjob.c                   |  3 +++
>  include/block/blockjob_int.h |  8 ++++++++
>  3 files changed, 21 insertions(+), 5 deletions(-)
> 
> diff --git a/block/backup.c b/block/backup.c
> index 7b5d8a3..734a24c 100644
> --- a/block/backup.c
> +++ b/block/backup.c
> @@ -242,6 +242,14 @@ static void backup_abort(BlockJob *job)
>      }
>  }
>  
> +static void backup_clean(BlockJob *job)
> +{
> +    BackupBlockJob *s = container_of(job, BackupBlockJob, common);
> +    assert(s->target);
> +    blk_unref(s->target);
> +    s->target = NULL;
> +}
> +
>  static void backup_attached_aio_context(BlockJob *job, AioContext *aio_context)
>  {
>      BackupBlockJob *s = container_of(job, BackupBlockJob, common);
> @@ -321,6 +329,7 @@ static const BlockJobDriver backup_job_driver = {
>      .set_speed              = backup_set_speed,
>      .commit                 = backup_commit,
>      .abort                  = backup_abort,
> +    .clean                  = backup_clean,
>      .attached_aio_context   = backup_attached_aio_context,
>      .drain                  = backup_drain,
>  };
> @@ -343,12 +352,8 @@ typedef struct {
>  
>  static void backup_complete(BlockJob *job, void *opaque)
>  {
> -    BackupBlockJob *s = container_of(job, BackupBlockJob, common);
>      BackupCompleteData *data = opaque;
>  
> -    blk_unref(s->target);
> -    s->target = NULL;
> -
>      block_job_completed(job, data->ret);
>      g_free(data);
>  }
> @@ -658,7 +663,7 @@ void backup_start(const char *job_id, BlockDriverState *bs,
>          bdrv_reclaim_dirty_bitmap(bs, sync_bitmap, NULL);
>      }
>      if (job) {
> -        blk_unref(job->target);
> +        backup_clean(&job->common);
>          block_job_unref(&job->common);
>      }
>  }
> diff --git a/blockjob.c b/blockjob.c
> index 4d0ef53..e3c458c 100644
> --- a/blockjob.c
> +++ b/blockjob.c
> @@ -241,6 +241,9 @@ static void block_job_completed_single(BlockJob *job)
>              job->driver->abort(job);
>          }
>      }
> +    if (job->driver->clean) {
> +        job->driver->clean(job);
> +    }
>  
>      if (job->cb) {
>          job->cb(job->opaque, job->ret);
> diff --git a/include/block/blockjob_int.h b/include/block/blockjob_int.h
> index 40275e4..60d91a0 100644
> --- a/include/block/blockjob_int.h
> +++ b/include/block/blockjob_int.h
> @@ -74,6 +74,14 @@ struct BlockJobDriver {
>      void (*abort)(BlockJob *job);
>  
>      /**
> +     * If the callback is not NULL, it will be invoked after a call to either
> +     * .commit() or .abort(). Regardless of which callback is invoked after
> +     * completion, .clean() will always be called, even if the job does not
> +     * belong to a transaction group.
> +     */
> +    void (*clean)(BlockJob *job);
> +
> +    /**
>       * If the callback is not NULL, it will be invoked when the job transitions
>       * into the paused state.  Paused jobs must not perform any asynchronous
>       * I/O or event loop activity.  This callback is used to quiesce jobs.
> -- 
> 2.7.4
> 

Reviewed-by: Jeff Cody <jcody@redhat.com>

  reply	other threads:[~2016-11-08  2:52 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-02 17:50 [Qemu-devel] [PATCH v3 0/6] jobs: fix transactional race condition John Snow
2016-11-02 17:50 ` [Qemu-devel] [PATCH v3 1/6] blockjob: fix dead pointer in txn list John Snow
2016-11-08  2:47   ` Jeff Cody
2016-11-02 17:50 ` [Qemu-devel] [PATCH v3 2/6] blockjob: add .clean property John Snow
2016-11-08  2:51   ` Jeff Cody [this message]
2016-11-02 17:50 ` [Qemu-devel] [PATCH v3 3/6] blockjob: add .start field John Snow
2016-11-08  2:58   ` Jeff Cody
2016-11-02 17:50 ` [Qemu-devel] [PATCH v3 4/6] blockjob: add block_job_start John Snow
2016-11-03 12:17   ` Kevin Wolf
2016-11-08  2:02     ` John Snow
2016-11-08  2:05       ` Jeff Cody
2016-11-08  2:20         ` John Snow
2016-11-08  9:16         ` Kevin Wolf
2016-11-02 17:50 ` [Qemu-devel] [PATCH v3 5/6] blockjob: refactor backup_start as backup_job_create John Snow
2016-11-03 13:17   ` Kevin Wolf
2016-11-08  5:41     ` John Snow
2016-11-08  9:11       ` Kevin Wolf
2016-11-08 15:24         ` John Snow
2016-11-08 18:30           ` Jeff Cody
2016-11-08  3:14   ` Jeff Cody
2016-11-02 17:50 ` [Qemu-devel] [PATCH v3 6/6] iotests: add transactional failure race test John Snow
2016-11-03 13:21 ` [Qemu-devel] [PATCH v3 0/6] jobs: fix transactional race condition Kevin Wolf

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=20161108025151.GD23932@localhost.localdomain \
    --to=jcody@redhat.com \
    --cc=jsnow@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    --cc=vsementsov@virtuozzo.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).