Am 27.01.2011 18:50, schrieb Anthony Liguori: > On 01/27/2011 09:58 AM, Daniel P. Berrange wrote: >> On Thu, Jan 27, 2011 at 04:52:14PM +0100, Kevin Wolf wrote: >> >>> This adds a preallocation=full mode to qcow2 image creation, which does not >>> only allocate metadata for the whole image, but also writes zeros to it, >>> creating a non-sparse image file. >>> >>> Signed-off-by: Kevin Wolf<kw...@redhat.com> >>> --- >>> block/qcow2.c | 45 ++++++++++++++++++++++++++++++++++++++++----- >>> 1 files changed, 40 insertions(+), 5 deletions(-) >>> >>> diff --git a/block/qcow2.c b/block/qcow2.c >>> index a1773e4..90cf2ca 100644 >>> --- a/block/qcow2.c >>> +++ b/block/qcow2.c >>> @@ -838,7 +838,15 @@ static int qcow2_change_backing_file(BlockDriverState >>> *bs, >>> return qcow2_update_ext_header(bs, backing_file, backing_fmt); >>> } >>> >>> -static int preallocate(BlockDriverState *bs) >>> +enum prealloc_mode { >>> + PREALLOC_OFF = 0, >>> + PREALLOC_METADATA, >>> + PREALLOC_FULL, >>> +}; >>> + >>> +#define IO_BUF_SIZE (2 * 1024 * 1024) >>> + >>> +static int preallocate(BlockDriverState *bs, enum prealloc_mode mode) >>> { >>> uint64_t nb_sectors; >>> uint64_t offset; >>> @@ -846,11 +854,14 @@ static int preallocate(BlockDriverState *bs) >>> int ret; >>> QCowL2Meta meta; >>> >>> + assert(mode != PREALLOC_OFF); >>> + >>> nb_sectors = bdrv_getlength(bs)>> 9; >>> offset = 0; >>> QLIST_INIT(&meta.dependent_requests); >>> meta.cluster_offset = 0; >>> >>> + /* First allocate metadata in _really_ big chunks */ >>> while (nb_sectors) { >>> num = MIN(nb_sectors, INT_MAX>> 9); >>> ret = qcow2_alloc_cluster_offset(bs, offset, 0, num,&num,&meta); >>> @@ -874,6 +885,28 @@ static int preallocate(BlockDriverState *bs) >>> offset += num<< 9; >>> } >>> >>> + /* Then write zeros to the cluster data, if requested */ >>> + if (mode == PREALLOC_FULL) { >>> + void *buf = qemu_mallocz(IO_BUF_SIZE); >>> + >>> + nb_sectors = bdrv_getlength(bs)>> BDRV_SECTOR_BITS; >>> + offset = 0; >>> + >>> + while (nb_sectors) { >>> + num = MIN(nb_sectors, IO_BUF_SIZE / BDRV_SECTOR_SIZE); >>> + ret = bdrv_write(bs, offset>> BDRV_SECTOR_BITS, buf, num); >>> >> Is there a way you can calculate the total size of the qcow2 >> file upfront, and just use a single posix_fallocate() call to >> do the zero-filled allocation of all the data blocks. It is >> many orders of magnitude faster than truely writing blocks of >> zero'd data on modern filesystems. I guess if you're using >> compression or encryption, we'd really have to go the slow >> path, but for regular usage it'd be better to take a fast >> path. >> > > Hrm, so is the intention here to avoid sparse files or to not assume > zero-fill?
The primary intention (as I understood our feature request ;-)) was to avoid sparse files. In it's current implementation you could also use it to overwrite any left-over data. Maybe that's a point for not having a bdrv_fallocate like Daniel suggested, but rather a bdrv_zero_init, which could fallocate on files and write zeros on a block device. Kevin