[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-block] [PATCH v8 04/11] block: Support streaming to an intermediat
From: |
Alberto Garcia |
Subject: |
[Qemu-block] [PATCH v8 04/11] block: Support streaming to an intermediate layer |
Date: |
Tue, 23 Jun 2015 00:32:19 +0300 |
This makes sure that the image we are steaming into is open in
read-write mode during the operation.
Operation blockers are also set in all intermediate nodes, since they
will be removed from the chain afterwards.
Finally, this also unblocks the stream operation in backing files.
Signed-off-by: Alberto Garcia <address@hidden>
Reviewed-by: Max Reitz <address@hidden>
---
block.c | 4 +++-
block/stream.c | 33 +++++++++++++++++++++++++++++++++
2 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/block.c b/block.c
index 0ffb855..bc5d002 100644
--- a/block.c
+++ b/block.c
@@ -1124,9 +1124,11 @@ void bdrv_set_backing_hd(BlockDriverState *bs,
BlockDriverState *backing_hd)
backing_hd->drv ? backing_hd->drv->format_name : "");
bdrv_op_block_all(bs->backing_hd, bs->backing_blocker);
- /* Otherwise we won't be able to commit due to check in bdrv_commit */
+ /* Otherwise we won't be able to commit or stream */
bdrv_op_unblock(bs->backing_hd, BLOCK_OP_TYPE_COMMIT_TARGET,
bs->backing_blocker);
+ bdrv_op_unblock(bs->backing_hd, BLOCK_OP_TYPE_STREAM,
+ bs->backing_blocker);
out:
bdrv_refresh_limits(bs, NULL);
}
diff --git a/block/stream.c b/block/stream.c
index 37bfd8b..8ba5a24 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -33,6 +33,8 @@ typedef struct StreamBlockJob {
BlockDriverState *base;
BlockdevOnError on_error;
char *backing_file_str;
+ int bs_flags;
+ Error *blocker;
} StreamBlockJob;
static int coroutine_fn stream_populate(BlockDriverState *bs,
@@ -89,6 +91,13 @@ static void stream_complete(BlockJob *job, void *opaque)
StreamBlockJob *s = container_of(job, StreamBlockJob, common);
StreamCompleteData *data = opaque;
BlockDriverState *base = s->base;
+ BlockDriverState *bs;
+
+ /* Remove all blockers set in stream_start() */
+ for (bs = job->bs->backing_hd; bs && bs != s->base; bs = bs->backing_hd) {
+ bdrv_op_unblock_all(bs, s->blocker);
+ }
+ error_free(s->blocker);
if (!block_job_is_cancelled(&s->common) && data->reached_end &&
data->ret == 0) {
@@ -103,6 +112,11 @@ static void stream_complete(BlockJob *job, void *opaque)
close_unused_images(job->bs, base, base_id);
}
+ /* Reopen the image back in read-only mode if necessary */
+ if (s->bs_flags != bdrv_get_flags(job->bs)) {
+ bdrv_reopen(job->bs, s->bs_flags, NULL);
+ }
+
g_free(s->backing_file_str);
block_job_completed(&s->common, data->ret);
g_free(data);
@@ -246,7 +260,9 @@ void stream_start(BlockDriverState *bs, BlockDriverState
*base,
BlockCompletionFunc *cb,
void *opaque, Error **errp)
{
+ BlockDriverState *iter;
StreamBlockJob *s;
+ int orig_bs_flags;
if ((on_error == BLOCKDEV_ON_ERROR_STOP ||
on_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
@@ -255,13 +271,30 @@ void stream_start(BlockDriverState *bs, BlockDriverState
*base,
return;
}
+ /* Make sure that the image is opened in read-write mode */
+ orig_bs_flags = bdrv_get_flags(bs);
+ if (!(orig_bs_flags & BDRV_O_RDWR)) {
+ if (bdrv_reopen(bs, orig_bs_flags | BDRV_O_RDWR, errp) != 0) {
+ return;
+ }
+ }
+
s = block_job_create(&stream_job_driver, bs, speed, cb, opaque, errp);
if (!s) {
return;
}
+ /* Block all intermediate nodes between bs and base, because they
+ * will disappear from the chain after this operation */
+ error_setg(&s->blocker, "blocked by the block-stream operation in '%s'",
+ bdrv_get_device_or_node_name(bs));
+ for (iter = bs->backing_hd; iter && iter != base; iter = iter->backing_hd)
{
+ bdrv_op_block_all(iter, s->blocker);
+ }
+
s->base = base;
s->backing_file_str = g_strdup(backing_file_str);
+ s->bs_flags = orig_bs_flags;
s->on_error = on_error;
s->common.co = qemu_coroutine_create(stream_run);
--
2.1.4
- [Qemu-block] [PATCH v8 00/11] Support streaming to an intermediate layer, Alberto Garcia, 2015/06/22
- [Qemu-block] [PATCH v8 11/11] qemu-iotests: test overlapping block-stream operations, Alberto Garcia, 2015/06/22
- [Qemu-block] [PATCH v8 09/11] qemu-iotests: test streaming to an intermediate layer, Alberto Garcia, 2015/06/22
- [Qemu-block] [PATCH v8 06/11] docs: Document how to stream to an intermediate layer, Alberto Garcia, 2015/06/22
- [Qemu-block] [PATCH v8 08/11] qemu-iotests: add no-op streaming test, Alberto Garcia, 2015/06/22
- [Qemu-block] [PATCH v8 07/11] qemu-iotests: fix test_stream_partial(), Alberto Garcia, 2015/06/22
- [Qemu-block] [PATCH v8 04/11] block: Support streaming to an intermediate layer,
Alberto Garcia <=
- [Qemu-block] [PATCH v8 10/11] qemu-iotests: test block-stream operations in parallel, Alberto Garcia, 2015/06/22
- [Qemu-block] [PATCH v8 03/11] block: never cancel a streaming job without running stream_complete(), Alberto Garcia, 2015/06/22
- [Qemu-block] [PATCH v8 05/11] block: Add QMP support for streaming to an intermediate layer, Alberto Garcia, 2015/06/22
- [Qemu-block] [PATCH v8 01/11] block: keep a list of block jobs, Alberto Garcia, 2015/06/22
- [Qemu-block] [PATCH v8 02/11] block: allow block jobs in any arbitrary node, Alberto Garcia, 2015/06/22
- Re: [Qemu-block] [PATCH v8 00/11] Support streaming to an intermediate layer, Stefan Hajnoczi, 2015/06/23