[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v13 02/19] block: Pause all jobs during bdrv_reopen_
From: |
Alberto Garcia |
Subject: |
[Qemu-devel] [PATCH v13 02/19] block: Pause all jobs during bdrv_reopen_multiple() |
Date: |
Fri, 28 Oct 2016 10:08:03 +0300 |
When a BlockDriverState is about to be reopened it can trigger certain
operations that need to write to disk. During this process a different
block job can be woken up. If that block job completes and also needs
to call bdrv_reopen() it can happen that it needs to do it on the same
BlockDriverState that is still in the process of being reopened.
This can have fatal consequences, like in this example:
1) Block job A starts and sleeps after a while.
2) Block job B starts and tries to reopen node1 (a qcow2 file).
3) Reopening node1 means flushing and replacing its qcow2 cache.
4) While the qcow2 cache is being flushed, job A wakes up.
5) Job A completes and reopens node1, replacing its cache.
6) Job B resumes, but the cache that was being flushed no longer
exists.
This patch splits the bdrv_drain_all() call to keep all block jobs
paused during bdrv_reopen_multiple(), so that step 4 can never happen
and the operation is safe.
Note that this scenario can only happen if both bdrv_reopen() calls
are made by block jobs on the same backing chain. Otherwise there's no
chance that the same BlockDriverState appears in both reopen queues.
Signed-off-by: Alberto Garcia <address@hidden>
Reviewed-by: Paolo Bonzini <address@hidden>
Reviewed-by: Kevin Wolf <address@hidden>
---
block.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/block.c b/block.c
index 7f3e7bc..adbecd0 100644
--- a/block.c
+++ b/block.c
@@ -2090,7 +2090,7 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue,
Error **errp)
assert(bs_queue != NULL);
- bdrv_drain_all();
+ bdrv_drain_all_begin();
QSIMPLEQ_FOREACH(bs_entry, bs_queue, entry) {
if (bdrv_reopen_prepare(&bs_entry->state, bs_queue, &local_err)) {
@@ -2120,6 +2120,9 @@ cleanup:
g_free(bs_entry);
}
g_free(bs_queue);
+
+ bdrv_drain_all_end();
+
return ret;
}
--
2.9.3
- [Qemu-devel] [PATCH v13 00/19] Support streaming to an intermediate layer, Alberto Garcia, 2016/10/28
- [Qemu-devel] [PATCH v13 03/19] block: Add block_job_add_bdrv(), Alberto Garcia, 2016/10/28
- [Qemu-devel] [PATCH v13 02/19] block: Pause all jobs during bdrv_reopen_multiple(),
Alberto Garcia <=
- [Qemu-devel] [PATCH v13 06/19] block: Check blockers in all nodes involved in a block-commit job, Alberto Garcia, 2016/10/28
- [Qemu-devel] [PATCH v13 04/19] block: Use block_job_add_bdrv() in mirror_start_job(), Alberto Garcia, 2016/10/28
- [Qemu-devel] [PATCH v13 07/19] block: Block all nodes involved in the block-commit operation, Alberto Garcia, 2016/10/28
- [Qemu-devel] [PATCH v13 01/19] block: Add bdrv_drain_all_{begin, end}(), Alberto Garcia, 2016/10/28
- [Qemu-devel] [PATCH v13 12/19] qemu-iotests: Test streaming to an intermediate layer, Alberto Garcia, 2016/10/28
- [Qemu-devel] [PATCH v13 09/19] block: Support streaming to an intermediate layer, Alberto Garcia, 2016/10/28
- [Qemu-devel] [PATCH v13 19/19] qemu-iotests: Test the 'base-node' parameter of 'block-stream', Alberto Garcia, 2016/10/28
- [Qemu-devel] [PATCH v13 17/19] qemu-iotests: Test streaming to a Quorum child, Alberto Garcia, 2016/10/28
- [Qemu-devel] [PATCH v13 05/19] block: Use block_job_add_bdrv() in backup_start(), Alberto Garcia, 2016/10/28
- [Qemu-devel] [PATCH v13 08/19] block: Block all intermediate nodes in commit_active_start(), Alberto Garcia, 2016/10/28