From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40114) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XCTzY-0005eJ-Ov for qemu-devel@nongnu.org; Wed, 30 Jul 2014 09:32:33 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XCTzT-0004gk-UJ for qemu-devel@nongnu.org; Wed, 30 Jul 2014 09:32:28 -0400 Received: from mx1.redhat.com ([209.132.183.28]:26064) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XCTzT-0004gc-Ms for qemu-devel@nongnu.org; Wed, 30 Jul 2014 09:32:23 -0400 Date: Wed, 30 Jul 2014 14:31:43 +0100 From: Stefan Hajnoczi Message-ID: <20140730133143.GG597@stefanha-thinkpad.redhat.com> References: <815878100.1264161.1401202499640.JavaMail.root@meituan.com> <345629775.1268590.1401202679338.JavaMail.root@meituan.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="9Iq5ULCa7nGtWwZS" Content-Disposition: inline In-Reply-To: <345629775.1268590.1401202679338.JavaMail.root@meituan.com> Subject: Re: [Qemu-devel] [PATCH] qcow2: preallocate() extands image less enough List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: =?utf-8?B?6JKZ6IGq?= Cc: Kevin Wolf , qemu-devel@nongnu.org --9Iq5ULCa7nGtWwZS Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Tue, May 27, 2014 at 10:57:59PM +0800, =E8=92=99=E8=81=AA wrote: > 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. >=20 > This bug can be reproduced by following steps: >=20 > $ /home/cmeng/work/qemu/qemu-git/qemu-img create -f qcow2 -o cluster_siz= e=3D2M,preallocation=3Dmetadata t1 25G > Formatting 't1', fmt=3Dqcow2 size=3D26843545600 encryption=3Doff cluster_= size=3D2097152 preallocation=3D'metadata' lazy_refcounts=3Doff=20 >=20 > $ ll t1 > -rw-r--r-- 1 cmeng cmeng 26851940352 May 27 21:20 t1 >=20 > $ ./qcow2.py t1 get-cluster-offset 52428799 > l1_size, 1 l1_table_offset, 6291456 cluster_bits, 21 cluster_size, 209715= 2 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_zer= o)) : (0L, 1L, (26851934208L, 0L)) > final offset : 26854030848 >=20 > 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 =20 > 26854030848, which is a little bigger than 26851940352, the size of t1. > > Signed-off-by: Cong Meng > --- > block/qcow2.c | 3 +++ > 1 file changed, 3 insertions(+) >=20 > 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 =3D bs->opaque; > =20 > nb_sectors =3D bdrv_getlength(bs) >> BDRV_SECTOR_BITS; > offset =3D 0; > @@ -1582,6 +1583,8 @@ static int preallocate(BlockDriverState *bs) > if (host_offset !=3D 0) { > uint8_t buf[BDRV_SECTOR_SIZE]; > memset(buf, 0, BDRV_SECTOR_SIZE); > + host_offset +=3D offset_into_cluster(s, > + offset - (num << BDRV_SECTOR_B= ITS)); > ret =3D bdrv_write(bs->file, (host_offset >> BDRV_SECTOR_BITS) += num - 1, > buf, 1); I don't understand what problem this calculation is supposed to fix. Can you explain the root cause? It seems that the issue stems from: while (nb_sectors) { num =3D MIN(nb_sectors, INT_MAX >> BDRV_SECTOR_BITS); ret =3D qcow2_alloc_cluster_offset(bs, offset, &num, &host_offset, &meta); INT_MAX >> BDRV_SECTOR_BITS is not a multiple of cluster size. That means 'num' will not be a multiple of cluster size, even though full clusters were allocated by qcow2_alloc_cluster_offset(). Try changing it to: (INT_MAX & ~(s->cluster_size - 1)) >> BDRV_SECTOR_BITS Now the loop will allocate full clusters until the last iteration. Stefan --9Iq5ULCa7nGtWwZS Content-Type: application/pgp-signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAEBAgAGBQJT2PO/AAoJEJykq7OBq3PIYDMH/AzcN+bRK48Xfc91TOyNaVBT 8MJOgDv24uvFpN5jG2DXv0P9txNGSOxA2RZ/GbnJGJUB5DIquQ3XCzix3iVZcXYg ETp8ybH9AiPwra4z4FT+QXCq4JqiS0vkqwWZJUsWK5x4Eh1WvArOhTTocrwgs1af irw1P+IE31kr967OIC11mxP7XuE/flUo6kY4UC4oRAt4mudnWD1leQrv3n5q2xtW koCVY8AKEeXcPMcgMp/Og4PUT1PbP/+r726noDuI2HyHR/t7oYRUSFoWvjxg1jlw YRysitGgo5ylA+lI9hn1AziDmS64NTXadUhf6/ahjlL3C6BSzMVd4o4KiArrjCU= =nsjP -----END PGP SIGNATURE----- --9Iq5ULCa7nGtWwZS--