[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] qcow2: preallocate() extands image less enough
From: |
蒙聪 |
Subject: |
[Qemu-devel] [PATCH] qcow2: preallocate() extands image less enough |
Date: |
Tue, 27 May 2014 23:29:01 +0800 (CST) |
cow2_alloc_cluster_offset() sets the host_offset pointing to the first
byte of the cluster referenced by guest_offset other than to the exact
byte referenced by guest_offset. In this case, preallocate() fails to
extend the image large enough.
This bug can be reproduced by following steps:
$ /home/cmeng/work/qemu/qemu-git/qemu-img create -f qcow2 -o
cluster_size=2M,preallocation=metadata t1 25G
Formatting 't1', fmt=qcow2 size=26843545600 encryption=off cluster_size=2097152
preallocation='metadata' lazy_refcounts=off
$ ll t1
-rw-r--r-- 1 cmeng cmeng 26851940352 May 27 21:20 t1
$ ./qcow2.py t1 get-cluster-offset 52428799
l1_size, 1 l1_table_offset, 6291456 cluster_bits, 21 cluster_size, 2097152
l2_entries_per_cluster, 262144
l1_entry (l1_refcount, l2_offset) : (1L, 8388608L)
l2_entry (l2_compressed, l2_refcount_is_one, (cluster_offset, read_as_zero)) :
(0L, 1L, (26851934208L, 0L))
final offset : 26854030848
I modified qcow2.py to get the offset into the host image file of the
last sector of the virutal image. As shown above, the offset is
26854030848, which is a little bigger than 26851940352, the size of t1.
Signed-off-by: Cong Meng <address@hidden>
---
block/qcow2.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/block/qcow2.c b/block/qcow2.c
index a4b97e8..c315fb7 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1538,6 +1538,7 @@ static int preallocate(BlockDriverState *bs)
int num;
int ret;
QCowL2Meta *meta;
+ BDRVQcowState *s = bs->opaque;
nb_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
offset = 0;
@@ -1582,6 +1583,8 @@ static int preallocate(BlockDriverState *bs)
if (host_offset != 0) {
uint8_t buf[BDRV_SECTOR_SIZE];
memset(buf, 0, BDRV_SECTOR_SIZE);
+ host_offset += offset_into_cluster(s,
+ offset - (num << BDRV_SECTOR_BITS));
ret = bdrv_write(bs->file, (host_offset >> BDRV_SECTOR_BITS) + num - 1,
buf, 1);
if (ret < 0) {
--
1.7.9.5