summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis V. Lunev <den@openvz.org>2015-04-28 10:47:00 +0300
committerStefan Hajnoczi <stefanha@redhat.com>2015-05-22 09:37:32 +0100
commitddd2ef2ce8d693b6e2635a0c20f65744641ff8df (patch)
treed383c78f18a008dc62217f9785bf2964ae9e41fa
parent19f5dc15912dfb6af06c97e4975023e545e85c72 (diff)
downloadqemu-ddd2ef2ce8d693b6e2635a0c20f65744641ff8df.tar.gz
qemu-ddd2ef2ce8d693b6e2635a0c20f65744641ff8df.tar.bz2
qemu-ddd2ef2ce8d693b6e2635a0c20f65744641ff8df.zip
block/parallels: improve image writing performance further
Try to perform IO for the biggest continuous block possible. All blocks abscent in the image are accounted in the same type and preallocation is made for all of them at once. The performance for sequential write is increased from 200 Mb/sec to 235 Mb/sec on my SSD HDD. Signed-off-by: Denis V. Lunev <den@openvz.org> Reviewed-by: Roman Kagan <rkagan@parallels.com> Signed-off-by: Roman Kagan <rkagan@parallels.com> Message-id: 1430207220-24458-28-git-send-email-den@openvz.org CC: Kevin Wolf <kwolf@redhat.com> CC: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
-rw-r--r--block/parallels.c43
1 files changed, 23 insertions, 20 deletions
diff --git a/block/parallels.c b/block/parallels.c
index e7124d97e7..046b56844c 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -183,43 +183,47 @@ static int64_t block_status(BDRVParallelsState *s, int64_t sector_num,
return start_off;
}
-static int64_t allocate_cluster(BlockDriverState *bs, int64_t sector_num)
+static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
+ int nb_sectors, int *pnum)
{
BDRVParallelsState *s = bs->opaque;
- uint32_t idx, offset;
- int64_t pos;
+ uint32_t idx, to_allocate, i;
+ int64_t pos, space;
- idx = sector_num / s->tracks;
- offset = sector_num % s->tracks;
+ pos = block_status(s, sector_num, nb_sectors, pnum);
+ if (pos > 0) {
+ return pos;
+ }
+ idx = sector_num / s->tracks;
if (idx >= s->bat_size) {
return -EINVAL;
}
- if (s->bat_bitmap[idx] != 0) {
- return bat2sect(s, idx) + offset;
- }
- pos = bdrv_getlength(bs->file) >> BDRV_SECTOR_BITS;
- if (s->data_end + s->tracks > pos) {
+ to_allocate = (sector_num + *pnum + s->tracks - 1) / s->tracks - idx;
+ space = to_allocate * s->tracks;
+ if (s->data_end + space > bdrv_getlength(bs->file) >> BDRV_SECTOR_BITS) {
int ret;
+ space += s->prealloc_size;
if (s->prealloc_mode == PRL_PREALLOC_MODE_FALLOCATE) {
- ret = bdrv_write_zeroes(bs->file, s->data_end,
- s->prealloc_size, 0);
+ ret = bdrv_write_zeroes(bs->file, s->data_end, space, 0);
} else {
ret = bdrv_truncate(bs->file,
- (s->data_end + s->prealloc_size) << BDRV_SECTOR_BITS);
+ (s->data_end + space) << BDRV_SECTOR_BITS);
}
if (ret < 0) {
return ret;
}
}
- pos = s->data_end;
- s->data_end += s->tracks;
- s->bat_bitmap[idx] = cpu_to_le32(pos / s->off_multiplier);
+ for (i = 0; i < to_allocate; i++) {
+ s->bat_bitmap[idx + i] = cpu_to_le32(s->data_end / s->off_multiplier);
+ s->data_end += s->tracks;
+ bitmap_set(s->bat_dirty_bmap,
+ bat_entry_off(idx) / s->bat_dirty_block, 1);
+ }
- bitmap_set(s->bat_dirty_bmap, bat_entry_off(idx) / s->bat_dirty_block, 1);
- return bat2sect(s, idx) + offset;
+ return bat2sect(s, idx) + sector_num % s->tracks;
}
@@ -287,14 +291,13 @@ static coroutine_fn int parallels_co_writev(BlockDriverState *bs,
int n, nbytes;
qemu_co_mutex_lock(&s->lock);
- position = allocate_cluster(bs, sector_num);
+ position = allocate_clusters(bs, sector_num, nb_sectors, &n);
qemu_co_mutex_unlock(&s->lock);
if (position < 0) {
ret = (int)position;
break;
}
- n = cluster_remainder(s, sector_num, nb_sectors);
nbytes = n << BDRV_SECTOR_BITS;
qemu_iovec_reset(&hd_qiov);