aboutsummaryrefslogtreecommitdiff
path: root/block/parallels.c
diff options
context:
space:
mode:
authorDenis V. Lunev <den@openvz.org>2015-04-28 10:46:50 +0300
committerStefan Hajnoczi <stefanha@redhat.com>2015-05-22 09:37:32 +0100
commit9eae9cca95e76afc2f2288a665e08a64953f2820 (patch)
tree71559af242f249ccaf6d58073c61ff9db47ac65c /block/parallels.c
parentdd97cdc064f24484a2ebc141a4ec6bba35f56007 (diff)
block/parallels: read parallels image header and BAT into single buffer
This metadata cache would allow to properly batch BAT updates to disk in next patches. These updates will be properly aligned to avoid read-modify-write transactions on block level. Signed-off-by: Denis V. Lunev <den@openvz.org> Reviewed-by: Roman Kagan <rkagan@parallels.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Roman Kagan <rkagan@parallels.com> Message-id: 1430207220-24458-18-git-send-email-den@openvz.org CC: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'block/parallels.c')
-rw-r--r--block/parallels.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/block/parallels.c b/block/parallels.c
index 431adf1ceb..f8a99810ed 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -61,6 +61,8 @@ typedef struct BDRVParallelsState {
*/
CoMutex lock;
+ ParallelsHeader *header;
+ uint32_t header_size;
uint32_t *bat_bitmap;
unsigned int bat_size;
@@ -91,7 +93,7 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
{
BDRVParallelsState *s = bs->opaque;
ParallelsHeader ph;
- int ret;
+ int ret, size;
ret = bdrv_pread(bs->file, 0, &ph, sizeof(ph));
if (ret < 0) {
@@ -130,17 +132,25 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
ret = -EFBIG;
goto fail;
}
- s->bat_bitmap = g_try_new(uint32_t, s->bat_size);
- if (s->bat_size && s->bat_bitmap == NULL) {
+
+ size = sizeof(ParallelsHeader) + sizeof(uint32_t) * s->bat_size;
+ s->header_size = ROUND_UP(size, bdrv_opt_mem_align(bs->file));
+ s->header = qemu_try_blockalign(bs->file, s->header_size);
+ if (s->header == NULL) {
ret = -ENOMEM;
goto fail;
}
+ if (le32_to_cpu(ph.data_off) < s->header_size) {
+ /* there is not enough unused space to fit to block align between BAT
+ and actual data. We can't avoid read-modify-write... */
+ s->header_size = size;
+ }
- ret = bdrv_pread(bs->file, sizeof(ParallelsHeader),
- s->bat_bitmap, s->bat_size * sizeof(uint32_t));
+ ret = bdrv_pread(bs->file, 0, s->header, s->header_size);
if (ret < 0) {
goto fail;
}
+ s->bat_bitmap = (uint32_t *)(s->header + 1);
s->has_truncate = bdrv_has_zero_init(bs->file) &&
bdrv_truncate(bs->file, bdrv_getlength(bs->file)) == 0;
@@ -152,7 +162,7 @@ fail_format:
error_setg(errp, "Image not in Parallels format");
ret = -EINVAL;
fail:
- g_free(s->bat_bitmap);
+ qemu_vfree(s->header);
return ret;
}
@@ -400,7 +410,7 @@ exit:
static void parallels_close(BlockDriverState *bs)
{
BDRVParallelsState *s = bs->opaque;
- g_free(s->bat_bitmap);
+ qemu_vfree(s->header);
}
static QemuOptsList parallels_create_opts = {