[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 01/12] mirror: Confirm we're quiesced only if the job
From: |
Kevin Wolf |
Subject: |
[Qemu-devel] [PULL 01/12] mirror: Confirm we're quiesced only if the job is paused or cancelled |
Date: |
Tue, 19 Mar 2019 16:46:09 +0100 |
From: Sergio Lopez <address@hidden>
While child_job_drained_begin() calls to job_pause(), the job doesn't
actually transition between states until it runs again and reaches a
pause point. This means bdrv_drained_begin() may return with some jobs
using the node still having 'busy == true'.
As a consequence, block_job_detach_aio_context() may get into a
deadlock, waiting for the job to be actually paused, while the coroutine
servicing the job is yielding and doesn't get the opportunity to get
scheduled again. This situation can be reproduced by issuing a
'block-commit' immediately followed by a 'device_del'.
To ensure bdrv_drained_begin() only returns when the jobs have been
paused, we change mirror_drained_poll() to only confirm it's quiesced
when job->paused == true and there aren't any in-flight requests, except
if we reached that point by a drained section initiated by the
mirror/commit job itself.
The other block jobs shouldn't need any changes, as the default
drained_poll() behavior is to only confirm it's quiesced if the job is
not busy or completed.
Signed-off-by: Sergio Lopez <address@hidden>
Signed-off-by: Kevin Wolf <address@hidden>
---
block/mirror.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/block/mirror.c b/block/mirror.c
index 010fdafd79..eb9a4cdf56 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -80,6 +80,7 @@ typedef struct MirrorBlockJob {
bool initial_zeroing_ongoing;
int in_active_write_counter;
bool prepared;
+ bool in_drain;
} MirrorBlockJob;
typedef struct MirrorBDSOpaque {
@@ -683,6 +684,7 @@ static int mirror_exit_common(Job *job)
/* The mirror job has no requests in flight any more, but we need to
* drain potential other users of the BDS before changing the graph. */
+ assert(s->in_drain);
bdrv_drained_begin(target_bs);
bdrv_replace_node(to_replace, target_bs, &local_err);
bdrv_drained_end(target_bs);
@@ -721,6 +723,7 @@ static int mirror_exit_common(Job *job)
bs_opaque->job = NULL;
bdrv_drained_end(src);
+ s->in_drain = false;
bdrv_unref(mirror_top_bs);
bdrv_unref(src);
@@ -1004,10 +1007,12 @@ static int coroutine_fn mirror_run(Job *job, Error
**errp)
*/
trace_mirror_before_drain(s, cnt);
+ s->in_drain = true;
bdrv_drained_begin(bs);
cnt = bdrv_get_dirty_count(s->dirty_bitmap);
if (cnt > 0 || mirror_flush(s) < 0) {
bdrv_drained_end(bs);
+ s->in_drain = false;
continue;
}
@@ -1055,6 +1060,7 @@ immediate_exit:
bdrv_dirty_iter_free(s->dbi);
if (need_drain) {
+ s->in_drain = true;
bdrv_drained_begin(bs);
}
@@ -1123,6 +1129,16 @@ static void coroutine_fn mirror_pause(Job *job)
static bool mirror_drained_poll(BlockJob *job)
{
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
+
+ /* If the job isn't paused nor cancelled, we can't be sure that it won't
+ * issue more requests. We make an exception if we've reached this point
+ * from one of our own drain sections, to avoid a deadlock waiting for
+ * ourselves.
+ */
+ if (!s->common.job.paused && !s->common.job.cancelled && !s->in_drain) {
+ return true;
+ }
+
return !!s->in_flight;
}
--
2.20.1
- [Qemu-devel] [PULL 00/12] Block layer patches, Kevin Wolf, 2019/03/19
- [Qemu-devel] [PULL 07/12] vl: Fix to create migration object before block backends again, Kevin Wolf, 2019/03/19
- [Qemu-devel] [PULL 06/12] iotests: 153: Wait for an answer to QMP commands, Kevin Wolf, 2019/03/19
- [Qemu-devel] [PULL 09/12] blockjob: fix user pause in block_job_error_action, Kevin Wolf, 2019/03/19
- [Qemu-devel] [PULL 05/12] block: Silence Coverity in bdrv_drop_intermediate(), Kevin Wolf, 2019/03/19
- [Qemu-devel] [PULL 12/12] qemu-iotests: Treat custom TEST_DIR in 051, Kevin Wolf, 2019/03/19
- [Qemu-devel] [PULL 10/12] block: Make bdrv_{copy_on_read, crypto_luks, replication} static, Kevin Wolf, 2019/03/19
- [Qemu-devel] [PULL 11/12] blockdev: Check @replaces in blockdev_mirror_common, Kevin Wolf, 2019/03/19
- [Qemu-devel] [PULL 08/12] qemu-iotests: Fix 232 for non-qcow2, Kevin Wolf, 2019/03/19
- [Qemu-devel] [PULL 02/12] qcow2: Fix data file error condition in qcow2_co_create(), Kevin Wolf, 2019/03/19
- [Qemu-devel] [PULL 01/12] mirror: Confirm we're quiesced only if the job is paused or cancelled,
Kevin Wolf <=
- [Qemu-devel] [PULL 03/12] qapi: fix block-latency-histogram-set description and examples, Kevin Wolf, 2019/03/19
- [Qemu-devel] [PULL 04/12] vmdk: Support version=3 in VMDK descriptor files, Kevin Wolf, 2019/03/19
- Re: [Qemu-devel] [PULL 00/12] Block layer patches, Peter Maydell, 2019/03/19