From: Jeff Cody <jcody@redhat.com>
To: qemu-block@nongnu.org
Cc: peter.maydell@linaro.org, jcody@redhat.com,
qemu-devel@nongnu.org, stefanha@redhat.com
Subject: [Qemu-devel] [PULL for-2.8 02/13] blockjob: add .clean property
Date: Mon, 14 Nov 2016 23:14:40 -0500 [thread overview]
Message-ID: <1479183291-14086-3-git-send-email-jcody@redhat.com> (raw)
In-Reply-To: <1479183291-14086-1-git-send-email-jcody@redhat.com>
From: John Snow <jsnow@redhat.com>
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>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Message-id: 1478587839-9834-3-git-send-email-jsnow@redhat.com
Signed-off-by: Jeff Cody <jcody@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
next prev parent reply other threads:[~2016-11-15 4:15 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-11-15 4:14 [Qemu-devel] [PULL for-2.8 00/13] Block patches for 2.8 Jeff Cody
2016-11-15 4:14 ` [Qemu-devel] [PULL for-2.8 01/13] blockjob: fix dead pointer in txn list Jeff Cody
2016-11-15 4:14 ` Jeff Cody [this message]
2016-11-15 4:14 ` [Qemu-devel] [PULL for-2.8 03/13] blockjob: add .start field Jeff Cody
2016-11-15 4:14 ` [Qemu-devel] [PULL for-2.8 04/13] blockjob: add block_job_start Jeff Cody
2016-11-15 4:14 ` [Qemu-devel] [PULL for-2.8 05/13] blockjob: refactor backup_start as backup_job_create Jeff Cody
2016-11-15 4:14 ` [Qemu-devel] [PULL for-2.8 06/13] iotests: add transactional failure race test Jeff Cody
2016-11-15 4:14 ` [Qemu-devel] [PULL for-2.8 07/13] qemu-iotests: avoid spurious failure on test 109 Jeff Cody
2016-11-15 4:14 ` [Qemu-devel] [PULL for-2.8 08/13] block/curl: Drop TFTP "support" Jeff Cody
2016-11-15 4:14 ` [Qemu-devel] [PULL for-2.8 09/13] block/curl: Use BDRV_SECTOR_SIZE Jeff Cody
2016-11-15 4:14 ` [Qemu-devel] [PULL for-2.8 10/13] block/curl: Fix return value from curl_read_cb Jeff Cody
2016-11-15 4:14 ` [Qemu-devel] [PULL for-2.8 11/13] block/curl: Remember all sockets Jeff Cody
2016-11-15 4:14 ` [Qemu-devel] [PULL for-2.8 12/13] block/curl: Do not wait for data beyond EOF Jeff Cody
2016-11-15 4:14 ` [Qemu-devel] [PULL for-2.8 13/13] mirror: do not flush every time the disks are synced Jeff Cody
2016-11-15 11:20 ` [Qemu-devel] [Qemu-block] [PULL for-2.8 00/13] Block patches for 2.8 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=1479183291-14086-3-git-send-email-jcody@redhat.com \
--to=jcody@redhat.com \
--cc=peter.maydell@linaro.org \
--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 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).