2012-01-18 22:40:44 +08:00
|
|
|
/*
|
|
|
|
* Image streaming
|
|
|
|
*
|
|
|
|
* Copyright IBM, Corp. 2011
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU LGPL, version 2 or later.
|
|
|
|
* See the COPYING.LIB file in the top-level directory.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2016-01-19 02:01:42 +08:00
|
|
|
#include "qemu/osdep.h"
|
2012-01-18 22:40:44 +08:00
|
|
|
#include "trace.h"
|
2012-12-18 01:19:44 +08:00
|
|
|
#include "block/block_int.h"
|
|
|
|
#include "block/blockjob.h"
|
include/qemu/osdep.h: Don't include qapi/error.h
Commit 57cb38b included qapi/error.h into qemu/osdep.h to get the
Error typedef. Since then, we've moved to include qemu/osdep.h
everywhere. Its file comment explains: "To avoid getting into
possible circular include dependencies, this file should not include
any other QEMU headers, with the exceptions of config-host.h,
compiler.h, os-posix.h and os-win32.h, all of which are doing a
similar job to this file and are under similar constraints."
qapi/error.h doesn't do a similar job, and it doesn't adhere to
similar constraints: it includes qapi-types.h. That's in excess of
100KiB of crap most .c files don't actually need.
Add the typedef to qemu/typedefs.h, and include that instead of
qapi/error.h. Include qapi/error.h in .c files that need it and don't
get it now. Include qapi-types.h in qom/object.h for uint16List.
Update scripts/clean-includes accordingly. Update it further to match
reality: replace config.h by config-target.h, add sysemu/os-posix.h,
sysemu/os-win32.h. Update the list of includes in the qemu/osdep.h
comment quoted above similarly.
This reduces the number of objects depending on qapi/error.h from "all
of them" to less than a third. Unfortunately, the number depending on
qapi-types.h shrinks only a little. More work is needed for that one.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
[Fix compilation without the spice devel packages. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2016-03-14 16:01:28 +08:00
|
|
|
#include "qapi/error.h"
|
2015-03-18 00:22:46 +08:00
|
|
|
#include "qapi/qmp/qerror.h"
|
2012-05-09 22:09:46 +08:00
|
|
|
#include "qemu/ratelimit.h"
|
2015-10-19 23:53:22 +08:00
|
|
|
#include "sysemu/block-backend.h"
|
2012-01-18 22:40:44 +08:00
|
|
|
|
|
|
|
enum {
|
|
|
|
/*
|
|
|
|
* Size of data buffer for populating the image file. This should be large
|
|
|
|
* enough to process multiple clusters in a single call, so that populating
|
|
|
|
* contiguous regions of the image is efficient.
|
|
|
|
*/
|
|
|
|
STREAM_BUFFER_SIZE = 512 * 1024, /* in bytes */
|
|
|
|
};
|
|
|
|
|
2012-01-18 22:40:45 +08:00
|
|
|
#define SLICE_TIME 100000000ULL /* ns */
|
|
|
|
|
2012-01-18 22:40:44 +08:00
|
|
|
typedef struct StreamBlockJob {
|
|
|
|
BlockJob common;
|
2012-01-18 22:40:45 +08:00
|
|
|
RateLimit limit;
|
2012-01-18 22:40:44 +08:00
|
|
|
BlockDriverState *base;
|
2012-09-28 23:22:59 +08:00
|
|
|
BlockdevOnError on_error;
|
block: add backing-file option to block-stream
On some image chains, QEMU may not always be able to resolve the
filenames properly, when updating the backing file of an image
after a block job.
For instance, certain relative pathnames may fail, or drives may
have been specified originally by file descriptor (e.g. /dev/fd/???),
or a relative protocol pathname may have been used.
In these instances, QEMU may lack the information to be able to make
the correct choice, but the user or management layer most likely does
have that knowledge.
With this extension to the block-stream api, the user is able to change
the backing file of the active layer as part of the block-stream
operation.
This allows the change to be 'safe', in the sense that if the attempt
to write the active image metadata fails, then the block-stream
operation returns failure, without disrupting the guest.
If a backing file string is not specified in the command, the backing
file string to use is determined in the same manner as it was
previously.
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Jeff Cody <jcody@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-26 03:40:11 +08:00
|
|
|
char *backing_file_str;
|
2012-01-18 22:40:44 +08:00
|
|
|
} StreamBlockJob;
|
|
|
|
|
2016-04-12 21:15:49 +08:00
|
|
|
static int coroutine_fn stream_populate(BlockBackend *blk,
|
2012-01-18 22:40:44 +08:00
|
|
|
int64_t sector_num, int nb_sectors,
|
|
|
|
void *buf)
|
|
|
|
{
|
|
|
|
struct iovec iov = {
|
|
|
|
.iov_base = buf,
|
|
|
|
.iov_len = nb_sectors * BDRV_SECTOR_SIZE,
|
|
|
|
};
|
|
|
|
QEMUIOVector qiov;
|
|
|
|
|
|
|
|
qemu_iovec_init_external(&qiov, &iov, 1);
|
|
|
|
|
|
|
|
/* Copy-on-read the unallocated clusters */
|
2016-04-12 21:15:49 +08:00
|
|
|
return blk_co_preadv(blk, sector_num * BDRV_SECTOR_SIZE, qiov.size, &qiov,
|
|
|
|
BDRV_REQ_COPY_ON_READ);
|
2012-01-18 22:40:44 +08:00
|
|
|
}
|
|
|
|
|
2014-10-21 19:03:57 +08:00
|
|
|
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;
|
2016-04-12 21:15:49 +08:00
|
|
|
BlockDriverState *bs = blk_bs(job->blk);
|
2014-10-21 19:03:57 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2016-04-12 21:15:49 +08:00
|
|
|
data->ret = bdrv_change_backing_file(bs, base_id, base_fmt);
|
|
|
|
bdrv_set_backing_hd(bs, base);
|
2014-10-21 19:03:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
g_free(s->backing_file_str);
|
|
|
|
block_job_completed(&s->common, data->ret);
|
|
|
|
g_free(data);
|
|
|
|
}
|
|
|
|
|
2012-01-18 22:40:44 +08:00
|
|
|
static void coroutine_fn stream_run(void *opaque)
|
|
|
|
{
|
|
|
|
StreamBlockJob *s = opaque;
|
2014-10-21 19:03:57 +08:00
|
|
|
StreamCompleteData *data;
|
2016-04-12 21:15:49 +08:00
|
|
|
BlockBackend *blk = s->common.blk;
|
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
2012-01-18 22:40:53 +08:00
|
|
|
BlockDriverState *base = s->base;
|
2016-03-21 21:47:25 +08:00
|
|
|
int64_t sector_num = 0;
|
|
|
|
int64_t end = -1;
|
2012-09-28 23:22:59 +08:00
|
|
|
int error = 0;
|
2012-01-18 22:40:44 +08:00
|
|
|
int ret = 0;
|
2012-05-10 22:10:42 +08:00
|
|
|
int n = 0;
|
2012-01-18 22:40:44 +08:00
|
|
|
void *buf;
|
|
|
|
|
2015-06-17 20:55:21 +08:00
|
|
|
if (!bs->backing) {
|
2016-03-21 21:47:25 +08:00
|
|
|
goto out;
|
2013-11-14 03:37:58 +08:00
|
|
|
}
|
|
|
|
|
2012-01-18 22:40:44 +08:00
|
|
|
s->common.len = bdrv_getlength(bs);
|
|
|
|
if (s->common.len < 0) {
|
2016-03-21 21:47:25 +08:00
|
|
|
ret = s->common.len;
|
|
|
|
goto out;
|
2012-01-18 22:40:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
end = s->common.len >> BDRV_SECTOR_BITS;
|
|
|
|
buf = qemu_blockalign(bs, STREAM_BUFFER_SIZE);
|
|
|
|
|
|
|
|
/* Turn on copy-on-read for the whole block device so that guest read
|
|
|
|
* requests help us make progress. Only do this when copying the entire
|
|
|
|
* backing chain since the copy-on-read operation does not take base into
|
|
|
|
* account.
|
|
|
|
*/
|
|
|
|
if (!base) {
|
|
|
|
bdrv_enable_copy_on_read(bs);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (sector_num = 0; sector_num < end; sector_num += n) {
|
2012-05-08 22:51:45 +08:00
|
|
|
uint64_t delay_ns = 0;
|
2012-05-08 22:52:00 +08:00
|
|
|
bool copy;
|
2012-05-08 22:51:45 +08:00
|
|
|
|
|
|
|
wait:
|
|
|
|
/* Note that even when no rate limit is applied we need to yield
|
2012-11-13 23:35:13 +08:00
|
|
|
* with no pending I/O here so that bdrv_drain_all() returns.
|
2012-05-08 22:51:45 +08:00
|
|
|
*/
|
2013-08-21 23:03:05 +08:00
|
|
|
block_job_sleep_ns(&s->common, QEMU_CLOCK_REALTIME, delay_ns);
|
2012-01-18 22:40:44 +08:00
|
|
|
if (block_job_is_cancelled(&s->common)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-09-22 14:19:10 +08:00
|
|
|
copy = false;
|
|
|
|
|
2013-09-05 01:00:22 +08:00
|
|
|
ret = bdrv_is_allocated(bs, sector_num,
|
|
|
|
STREAM_BUFFER_SIZE / BDRV_SECTOR_SIZE, &n);
|
2012-05-08 22:52:00 +08:00
|
|
|
if (ret == 1) {
|
|
|
|
/* Allocated in the top, no need to copy. */
|
2013-09-05 01:00:25 +08:00
|
|
|
} else if (ret >= 0) {
|
2012-05-08 22:52:00 +08:00
|
|
|
/* Copy if allocated in the intermediate images. Limit to the
|
|
|
|
* known-unallocated area [sector_num, sector_num+n). */
|
2015-06-17 20:55:21 +08:00
|
|
|
ret = bdrv_is_allocated_above(backing_bs(bs), base,
|
2013-09-05 01:00:24 +08:00
|
|
|
sector_num, n, &n);
|
2012-08-28 22:26:48 +08:00
|
|
|
|
|
|
|
/* Finish early if end of backing file has been reached */
|
|
|
|
if (ret == 0 && n == 0) {
|
|
|
|
n = end - sector_num;
|
|
|
|
}
|
|
|
|
|
2012-05-08 22:52:00 +08:00
|
|
|
copy = (ret == 1);
|
|
|
|
}
|
2012-01-18 22:40:44 +08:00
|
|
|
trace_stream_one_iteration(s, sector_num, n, ret);
|
2013-09-22 14:19:10 +08:00
|
|
|
if (copy) {
|
2012-01-18 22:40:45 +08:00
|
|
|
if (s->common.speed) {
|
2012-05-08 22:51:45 +08:00
|
|
|
delay_ns = ratelimit_calculate_delay(&s->limit, n);
|
2012-01-18 22:40:45 +08:00
|
|
|
if (delay_ns > 0) {
|
2012-05-08 22:51:45 +08:00
|
|
|
goto wait;
|
2012-01-18 22:40:45 +08:00
|
|
|
}
|
|
|
|
}
|
2016-04-12 21:15:49 +08:00
|
|
|
ret = stream_populate(blk, sector_num, n, buf);
|
2012-01-18 22:40:44 +08:00
|
|
|
}
|
|
|
|
if (ret < 0) {
|
2012-09-28 23:22:59 +08:00
|
|
|
BlockErrorAction action =
|
2016-04-18 17:36:38 +08:00
|
|
|
block_job_error_action(&s->common, s->on_error, true, -ret);
|
2014-06-18 14:43:30 +08:00
|
|
|
if (action == BLOCK_ERROR_ACTION_STOP) {
|
2012-09-28 23:22:59 +08:00
|
|
|
n = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (error == 0) {
|
|
|
|
error = ret;
|
|
|
|
}
|
2014-06-18 14:43:30 +08:00
|
|
|
if (action == BLOCK_ERROR_ACTION_REPORT) {
|
2012-09-28 23:22:59 +08:00
|
|
|
break;
|
|
|
|
}
|
2012-01-18 22:40:44 +08:00
|
|
|
}
|
2012-01-18 22:40:53 +08:00
|
|
|
ret = 0;
|
2012-01-18 22:40:44 +08:00
|
|
|
|
|
|
|
/* Publish progress */
|
|
|
|
s->common.offset += n * BDRV_SECTOR_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!base) {
|
|
|
|
bdrv_disable_copy_on_read(bs);
|
|
|
|
}
|
|
|
|
|
2012-09-28 23:22:59 +08:00
|
|
|
/* Do not remove the backing file if an error was there but ignored. */
|
|
|
|
ret = error;
|
|
|
|
|
2012-01-18 22:40:44 +08:00
|
|
|
qemu_vfree(buf);
|
2014-10-21 19:03:57 +08:00
|
|
|
|
2016-03-21 21:47:25 +08:00
|
|
|
out:
|
2014-10-21 19:03:57 +08:00
|
|
|
/* 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);
|
2012-01-18 22:40:44 +08:00
|
|
|
}
|
|
|
|
|
2012-04-25 23:51:02 +08:00
|
|
|
static void stream_set_speed(BlockJob *job, int64_t speed, Error **errp)
|
2012-01-18 22:40:45 +08:00
|
|
|
{
|
|
|
|
StreamBlockJob *s = container_of(job, StreamBlockJob, common);
|
|
|
|
|
2012-04-25 23:51:02 +08:00
|
|
|
if (speed < 0) {
|
2015-03-17 18:54:50 +08:00
|
|
|
error_setg(errp, QERR_INVALID_PARAMETER, "speed");
|
2012-04-25 23:51:01 +08:00
|
|
|
return;
|
2012-01-18 22:40:45 +08:00
|
|
|
}
|
2012-05-09 22:09:46 +08:00
|
|
|
ratelimit_set_speed(&s->limit, speed / BDRV_SECTOR_SIZE, SLICE_TIME);
|
2012-01-18 22:40:45 +08:00
|
|
|
}
|
|
|
|
|
2013-10-08 17:29:38 +08:00
|
|
|
static const BlockJobDriver stream_job_driver = {
|
2012-01-18 22:40:44 +08:00
|
|
|
.instance_size = sizeof(StreamBlockJob),
|
2013-10-08 17:29:40 +08:00
|
|
|
.job_type = BLOCK_JOB_TYPE_STREAM,
|
2012-01-18 22:40:45 +08:00
|
|
|
.set_speed = stream_set_speed,
|
2012-01-18 22:40:44 +08:00
|
|
|
};
|
|
|
|
|
2012-04-25 23:51:00 +08:00
|
|
|
void stream_start(BlockDriverState *bs, BlockDriverState *base,
|
block: add backing-file option to block-stream
On some image chains, QEMU may not always be able to resolve the
filenames properly, when updating the backing file of an image
after a block job.
For instance, certain relative pathnames may fail, or drives may
have been specified originally by file descriptor (e.g. /dev/fd/???),
or a relative protocol pathname may have been used.
In these instances, QEMU may lack the information to be able to make
the correct choice, but the user or management layer most likely does
have that knowledge.
With this extension to the block-stream api, the user is able to change
the backing file of the active layer as part of the block-stream
operation.
This allows the change to be 'safe', in the sense that if the attempt
to write the active image metadata fails, then the block-stream
operation returns failure, without disrupting the guest.
If a backing file string is not specified in the command, the backing
file string to use is determined in the same manner as it was
previously.
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Jeff Cody <jcody@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-26 03:40:11 +08:00
|
|
|
const char *backing_file_str, int64_t speed,
|
2012-09-28 23:22:59 +08:00
|
|
|
BlockdevOnError on_error,
|
2014-10-07 19:59:15 +08:00
|
|
|
BlockCompletionFunc *cb,
|
2012-04-25 23:51:00 +08:00
|
|
|
void *opaque, Error **errp)
|
2012-01-18 22:40:44 +08:00
|
|
|
{
|
|
|
|
StreamBlockJob *s;
|
|
|
|
|
2013-10-08 17:29:38 +08:00
|
|
|
s = block_job_create(&stream_job_driver, bs, speed, cb, opaque, errp);
|
2012-01-18 22:40:44 +08:00
|
|
|
if (!s) {
|
2012-04-25 23:51:00 +08:00
|
|
|
return;
|
2012-01-18 22:40:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
s->base = base;
|
block: add backing-file option to block-stream
On some image chains, QEMU may not always be able to resolve the
filenames properly, when updating the backing file of an image
after a block job.
For instance, certain relative pathnames may fail, or drives may
have been specified originally by file descriptor (e.g. /dev/fd/???),
or a relative protocol pathname may have been used.
In these instances, QEMU may lack the information to be able to make
the correct choice, but the user or management layer most likely does
have that knowledge.
With this extension to the block-stream api, the user is able to change
the backing file of the active layer as part of the block-stream
operation.
This allows the change to be 'safe', in the sense that if the attempt
to write the active image metadata fails, then the block-stream
operation returns failure, without disrupting the guest.
If a backing file string is not specified in the command, the backing
file string to use is determined in the same manner as it was
previously.
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Jeff Cody <jcody@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-26 03:40:11 +08:00
|
|
|
s->backing_file_str = g_strdup(backing_file_str);
|
2012-01-18 22:40:44 +08:00
|
|
|
|
2012-09-28 23:22:59 +08:00
|
|
|
s->on_error = on_error;
|
2012-05-08 22:51:46 +08:00
|
|
|
s->common.co = qemu_coroutine_create(stream_run);
|
|
|
|
trace_stream_start(bs, base, s, s->common.co, opaque);
|
|
|
|
qemu_coroutine_enter(s->common.co, s);
|
2012-01-18 22:40:44 +08:00
|
|
|
}
|