From: Marcelo Tosatti <mtosatti@redhat.com>
To: stefanha@linux.vnet.ibm.com, kwolf@redhat.com, qemu-devel@nongnu.org
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Subject: [Qemu-devel] [patch 4/5] block stream: add support for partial streaming
Date: Fri, 30 Dec 2011 08:03:41 -0200 [thread overview]
Message-ID: <20111230100503.809473621@redhat.com> (raw)
In-Reply-To: 20111230100337.226685961@redhat.com
[-- Attachment #1: block-stream-base --]
[-- Type: text/plain, Size: 6913 bytes --]
Add support for streaming data from an intermediate section of the
image chain (see patch and documentation for details).
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: stefanha/block.c
===================================================================
--- stefanha.orig/block.c
+++ stefanha/block.c
@@ -2229,6 +2229,70 @@ int bdrv_is_allocated(BlockDriverState *
return data.ret;
}
+/*
+ * Given an image chain: [BASE] -> [INTER1] -> [INTER2] -> [TOP]
+ *
+ * Return true if the given sector is allocated in top or base.
+ * Return false if the given sector is allocated in intermediate images.
+ *
+ * 'pnum' is set to the number of sectors (including and immediately following
+ * the specified sector) that are known to be in the same
+ * allocated/unallocated state.
+ *
+ */
+int bdrv_is_allocated_base(BlockDriverState *top,
+ BlockDriverState *base,
+ int64_t sector_num,
+ int nb_sectors, int *pnum)
+{
+ BlockDriverState *intermediate;
+ int ret, n;
+
+ ret = bdrv_co_is_allocated(top, sector_num, nb_sectors, &n);
+ if (ret) {
+ *pnum = n;
+ return ret;
+ }
+
+ /*
+ * Is the unallocated chunk [sector_num, n] also
+ * unallocated between base and top?
+ */
+ intermediate = top->backing_hd;
+
+ while (intermediate) {
+ int pnum_inter;
+
+ /* reached base */
+ if (intermediate == base) {
+ *pnum = n;
+ return 1;
+ }
+ ret = bdrv_co_is_allocated(intermediate, sector_num, nb_sectors,
+ &pnum_inter);
+ if (ret < 0) {
+ return ret;
+ } else if (ret) {
+ *pnum = pnum_inter;
+ return 0;
+ }
+
+ /*
+ * [sector_num, nb_sectors] is unallocated on top but intermediate
+ * might have
+ *
+ * [sector_num+x, nr_sectors] allocated.
+ */
+ if (n > pnum_inter) {
+ n = pnum_inter;
+ }
+
+ intermediate = intermediate->backing_hd;
+ }
+
+ return 1;
+}
+
void bdrv_mon_event(const BlockDriverState *bdrv,
BlockMonEventAction action, int is_read)
{
Index: stefanha/block.h
===================================================================
--- stefanha.orig/block.h
+++ stefanha/block.h
@@ -222,6 +222,8 @@ int bdrv_co_discard(BlockDriverState *bs
int bdrv_has_zero_init(BlockDriverState *bs);
int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
int *pnum);
+int bdrv_is_allocated_base(BlockDriverState *top, BlockDriverState *base,
+ int64_t sector_num, int nb_sectors, int *pnum);
#define BIOS_ATA_TRANSLATION_AUTO 0
#define BIOS_ATA_TRANSLATION_NONE 1
Index: stefanha/block/stream.c
===================================================================
--- stefanha.orig/block/stream.c
+++ stefanha/block/stream.c
@@ -57,6 +57,7 @@ typedef struct StreamBlockJob {
BlockJob common;
RateLimit limit;
BlockDriverState *base;
+ char backing_file_id[1024];
} StreamBlockJob;
static int coroutine_fn stream_populate(BlockDriverState *bs,
@@ -79,6 +80,7 @@ static void coroutine_fn stream_run(void
{
StreamBlockJob *s = opaque;
BlockDriverState *bs = s->common.bs;
+ BlockDriverState *base = s->base;
int64_t sector_num, end;
int ret = 0;
int n;
@@ -97,8 +99,17 @@ retry:
break;
}
- ret = bdrv_co_is_allocated(bs, sector_num,
- STREAM_BUFFER_SIZE / BDRV_SECTOR_SIZE, &n);
+
+ if (base) {
+ ret = bdrv_is_allocated_base(bs, base, sector_num,
+ STREAM_BUFFER_SIZE /
+ BDRV_SECTOR_SIZE,
+ &n);
+ } else {
+ ret = bdrv_co_is_allocated(bs, sector_num,
+ STREAM_BUFFER_SIZE / BDRV_SECTOR_SIZE,
+ &n);
+ }
trace_stream_one_iteration(s, sector_num, n, ret);
if (ret == 0) {
if (s->common.speed) {
@@ -115,6 +126,7 @@ retry:
if (ret < 0) {
break;
}
+ ret = 0;
/* Publish progress */
s->common.offset += n * BDRV_SECTOR_SIZE;
@@ -129,7 +141,10 @@ retry:
bdrv_disable_zero_detection(bs);
if (sector_num == end && ret == 0) {
- bdrv_change_backing_file(bs, NULL, NULL);
+ const char *base_id = NULL;
+ if (base)
+ base_id = s->backing_file_id;
+ bdrv_change_backing_file(bs, base_id, NULL);
}
qemu_vfree(buf);
@@ -155,7 +170,8 @@ static BlockJobType stream_job_type = {
};
int stream_start(BlockDriverState *bs, BlockDriverState *base,
- BlockDriverCompletionFunc *cb, void *opaque)
+ const char *base_id, BlockDriverCompletionFunc *cb,
+ void *opaque)
{
StreamBlockJob *s;
Coroutine *co;
@@ -166,6 +182,8 @@ int stream_start(BlockDriverState *bs, B
s = block_job_create(&stream_job_type, bs, cb, opaque);
s->base = base;
+ if (base_id)
+ strncpy(s->backing_file_id, base_id, sizeof(s->backing_file_id) - 1);
co = qemu_coroutine_create(stream_run);
trace_stream_start(bs, base, s, co, opaque);
Index: stefanha/blockdev.c
===================================================================
--- stefanha.orig/blockdev.c
+++ stefanha/blockdev.c
@@ -931,6 +931,7 @@ void qmp_block_stream(const char *device
const char *base, Error **errp)
{
BlockDriverState *bs;
+ BlockDriverState *base_bs;
int ret;
bs = bdrv_find(device);
@@ -939,13 +940,15 @@ void qmp_block_stream(const char *device
return;
}
- /* Base device not supported */
if (base) {
- error_set(errp, QERR_NOT_SUPPORTED);
- return;
+ base_bs = bdrv_find_backing_image(bs, base);
+ if (base_bs == NULL) {
+ error_set(errp, QERR_BASE_ID_NOT_FOUND, base);
+ return;
+ }
}
- ret = stream_start(bs, NULL, block_stream_cb, bs);
+ ret = stream_start(bs, base_bs, base, block_stream_cb, bs);
if (ret < 0) {
switch (ret) {
case -EBUSY:
Index: stefanha/block_int.h
===================================================================
--- stefanha.orig/block_int.h
+++ stefanha/block_int.h
@@ -380,6 +380,7 @@ static inline bool block_job_is_cancelle
}
int stream_start(BlockDriverState *bs, BlockDriverState *base,
- BlockDriverCompletionFunc *cb, void *opaque);
+ const char *base_id, BlockDriverCompletionFunc *cb,
+ void *opaque);
#endif /* BLOCK_INT_H */
next prev parent reply other threads:[~2011-12-30 10:07 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-12-30 10:03 [Qemu-devel] [patch 0/5] block streaming base support Marcelo Tosatti
2011-12-30 10:03 ` [Qemu-devel] [patch 1/5] block: add bdrv_find_backing_image Marcelo Tosatti
2011-12-30 10:03 ` [Qemu-devel] [patch 2/5] block: implement bdrv_find_backing_image in qcow2 Marcelo Tosatti
2012-01-03 13:44 ` Stefan Hajnoczi
2011-12-30 10:03 ` [Qemu-devel] [patch 3/5] add QERR_BASE_ID_NOT_FOUND Marcelo Tosatti
2011-12-30 10:03 ` Marcelo Tosatti [this message]
2012-01-04 12:39 ` [Qemu-devel] [patch 4/5] block stream: add support for partial streaming Stefan Hajnoczi
2012-01-04 13:52 ` Marcelo Tosatti
2011-12-30 10:03 ` [Qemu-devel] [patch 5/5] add doc to describe live block operations Marcelo Tosatti
2012-01-04 14:08 ` [Qemu-devel] [patch 0/4] block streaming base support (v2) Marcelo Tosatti
2012-01-04 14:08 ` [Qemu-devel] [patch 1/4] block: add bdrv_find_backing_image Marcelo Tosatti
2012-01-04 14:08 ` [Qemu-devel] [patch 2/4] add QERR_BASE_ID_NOT_FOUND Marcelo Tosatti
2012-01-04 14:08 ` [Qemu-devel] [patch 3/4] block stream: add support for partial streaming Marcelo Tosatti
2012-01-04 16:02 ` Eric Blake
2012-01-04 17:47 ` Marcelo Tosatti
2012-01-04 18:03 ` Eric Blake
2012-01-04 19:22 ` Marcelo Tosatti
2012-01-04 22:40 ` Stefan Hajnoczi
2012-01-05 7:46 ` Paolo Bonzini
2012-01-09 10:58 ` Kevin Wolf
2012-01-09 13:14 ` Stefan Hajnoczi
2012-01-04 14:08 ` [Qemu-devel] [patch 4/4] add doc to describe live block operations Marcelo Tosatti
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20111230100503.809473621@redhat.com \
--to=mtosatti@redhat.com \
--cc=kwolf@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@linux.vnet.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.