diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-11-03 18:34:08 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-11-03 18:34:09 +0000 |
commit | 9a33c0c851829d876fe6c2c7a7f2f415e27f9386 (patch) | |
tree | cab28d999990185564efaae7cda52950ce89b67f /block/stream.c | |
parent | eb5f222b5c125de1b47970c6096a3107ffe1d69b (diff) | |
parent | b112a65c52aa45a23b83b1e0d56db3b7cc44597e (diff) |
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
# gpg: Signature made Mon 03 Nov 2014 11:50:53 GMT using RSA key ID 81AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>"
* remotes/stefanha/tags/block-pull-request: (53 commits)
block: declare blockjobs and dataplane friends!
block: let commit blockjob run in BDS AioContext
block: let mirror blockjob run in BDS AioContext
block: let stream blockjob run in BDS AioContext
block: let backup blockjob run in BDS AioContext
block: add bdrv_drain()
blockjob: add block_job_defer_to_main_loop()
blockdev: add note that block_job_cb() must be thread-safe
blockdev: acquire AioContext in blockdev_mark_auto_del()
blockdev: acquire AioContext in do_qmp_query_block_jobs_one()
block: acquire AioContext in generic blockjob QMP commands
iotests: Expand test 061
block/qcow2: Simplify shared L2 handling in amend
block/qcow2: Make get_refcount() global
block/qcow2: Implement status CB for amend
qemu-img: Fix insignificant memleak
qemu-img: Add progress output for amend
block: Add status callback to bdrv_amend_options()
block: qemu-iotest 107 supports NFS
iotests: Add test for qcow2's bdrv_make_empty
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'block/stream.c')
-rw-r--r-- | block/stream.c | 50 |
1 files changed, 36 insertions, 14 deletions
diff --git a/block/stream.c b/block/stream.c index a1dc8da484..a628901f69 100644 --- a/block/stream.c +++ b/block/stream.c @@ -79,9 +79,39 @@ static void close_unused_images(BlockDriverState *top, BlockDriverState *base, bdrv_refresh_limits(top, NULL); } +typedef struct { + int ret; + bool reached_end; +} StreamCompleteData; + +static void stream_complete(BlockJob *job, void *opaque) +{ + StreamBlockJob *s = container_of(job, StreamBlockJob, common); + StreamCompleteData *data = opaque; + BlockDriverState *base = s->base; + + if (!block_job_is_cancelled(&s->common) && data->reached_end && + data->ret == 0) { + const char *base_id = NULL, *base_fmt = NULL; + if (base) { + base_id = s->backing_file_str; + if (base->drv) { + base_fmt = base->drv->format_name; + } + } + data->ret = bdrv_change_backing_file(job->bs, base_id, base_fmt); + close_unused_images(job->bs, base, base_id); + } + + g_free(s->backing_file_str); + block_job_completed(&s->common, data->ret); + g_free(data); +} + static void coroutine_fn stream_run(void *opaque) { StreamBlockJob *s = opaque; + StreamCompleteData *data; BlockDriverState *bs = s->common.bs; BlockDriverState *base = s->base; int64_t sector_num, end; @@ -183,21 +213,13 @@ wait: /* Do not remove the backing file if an error was there but ignored. */ ret = error; - if (!block_job_is_cancelled(&s->common) && sector_num == end && ret == 0) { - const char *base_id = NULL, *base_fmt = NULL; - if (base) { - base_id = s->backing_file_str; - if (base->drv) { - base_fmt = base->drv->format_name; - } - } - ret = bdrv_change_backing_file(bs, base_id, base_fmt); - close_unused_images(bs, base, base_id); - } - qemu_vfree(buf); - g_free(s->backing_file_str); - block_job_completed(&s->common, ret); + + /* Modify backing chain and close BDSes in main loop */ + data = g_malloc(sizeof(*data)); + data->ret = ret; + data->reached_end = sector_num == end; + block_job_defer_to_main_loop(&s->common, stream_complete, data); } static void stream_set_speed(BlockJob *job, int64_t speed, Error **errp) |