Message ID | 3bdffb8a85c3563a38f31846f4687b4c435730ab.1384227383.git.hutao@cn.fujitsu.com |
---|---|
State | New |
Headers | show |
Am 12.11.2013 um 08:47 hat Hu Tao geschrieben: > This adds a preallocation=full mode to qcow2 image creation, which > creates a non-sparse image file. > > Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> > --- > block/qcow2.c | 28 ++++++++++++++++++++++------ > 1 file changed, 22 insertions(+), 6 deletions(-) > > diff --git a/block/qcow2.c b/block/qcow2.c > index 359030f..d3ca6cf 100644 > --- a/block/qcow2.c > +++ b/block/qcow2.c > @@ -1385,7 +1385,13 @@ static int qcow2_change_backing_file(BlockDriverState *bs, > return qcow2_update_header(bs); > } > > -static int preallocate(BlockDriverState *bs) > +enum prealloc_mode { > + PREALLOC_OFF = 0, > + PREALLOC_METADATA, > + PREALLOC_FULL, > +}; > + > +static int preallocate(BlockDriverState *bs, enum prealloc_mode mode) > { > uint64_t nb_sectors; > uint64_t offset; > @@ -1394,9 +1400,12 @@ static int preallocate(BlockDriverState *bs) > int ret; > QCowL2Meta *meta; > > + assert(mode != PREALLOC_OFF); > + > nb_sectors = bdrv_getlength(bs) >> 9; > 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, > @@ -1424,6 +1433,11 @@ static int preallocate(BlockDriverState *bs) > offset += num << 9; > } > > + /* Then write zeros to the cluster data, if requested */ > + if (mode == PREALLOC_FULL) { > + bdrv_zero_init(bs->file, offset, bdrv_getlength(bs)); > + } bdrv_zero_init() is completely optional. It is only implemented for raw-posix and errors are not checked. You can't assume that after this point anything is preallocated. Kevin
On Tue, Nov 12, 2013 at 11:31:03AM +0100, Kevin Wolf wrote: > Am 12.11.2013 um 08:47 hat Hu Tao geschrieben: > > This adds a preallocation=full mode to qcow2 image creation, which > > creates a non-sparse image file. > > > > Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> > > --- > > block/qcow2.c | 28 ++++++++++++++++++++++------ > > 1 file changed, 22 insertions(+), 6 deletions(-) > > > > diff --git a/block/qcow2.c b/block/qcow2.c > > index 359030f..d3ca6cf 100644 > > --- a/block/qcow2.c > > +++ b/block/qcow2.c > > @@ -1385,7 +1385,13 @@ static int qcow2_change_backing_file(BlockDriverState *bs, > > return qcow2_update_header(bs); > > } > > > > -static int preallocate(BlockDriverState *bs) > > +enum prealloc_mode { > > + PREALLOC_OFF = 0, > > + PREALLOC_METADATA, > > + PREALLOC_FULL, > > +}; > > + > > +static int preallocate(BlockDriverState *bs, enum prealloc_mode mode) > > { > > uint64_t nb_sectors; > > uint64_t offset; > > @@ -1394,9 +1400,12 @@ static int preallocate(BlockDriverState *bs) > > int ret; > > QCowL2Meta *meta; > > > > + assert(mode != PREALLOC_OFF); > > + > > nb_sectors = bdrv_getlength(bs) >> 9; > > 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, > > @@ -1424,6 +1433,11 @@ static int preallocate(BlockDriverState *bs) > > offset += num << 9; > > } > > > > + /* Then write zeros to the cluster data, if requested */ > > + if (mode == PREALLOC_FULL) { > > + bdrv_zero_init(bs->file, offset, bdrv_getlength(bs)); > > + } > > bdrv_zero_init() is completely optional. It is only implemented for > raw-posix and errors are not checked. You can't assume that after this > point anything is preallocated. Yes, errores should have been checked here.
What is your use case for this seris? QCOW2 creation or converting anything to QCOW2? For the later case you could use "qemu-img convert -S 0 ..." starting in 1.8. Peter Hu Tao wrote: > This adds a preallocation=full mode to qcow2 image creation, which > creates a non-sparse image file. > > Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> > --- > block/qcow2.c | 28 ++++++++++++++++++++++------ > 1 file changed, 22 insertions(+), 6 deletions(-) > > diff --git a/block/qcow2.c b/block/qcow2.c > index 359030f..d3ca6cf 100644 > --- a/block/qcow2.c > +++ b/block/qcow2.c > @@ -1385,7 +1385,13 @@ static int > qcow2_change_backing_file(BlockDriverState *bs, > return qcow2_update_header(bs); > } > > -static int preallocate(BlockDriverState *bs) > +enum prealloc_mode { > + PREALLOC_OFF = 0, > + PREALLOC_METADATA, > + PREALLOC_FULL, > +}; > + > +static int preallocate(BlockDriverState *bs, enum prealloc_mode mode) > { > uint64_t nb_sectors; > uint64_t offset; > @@ -1394,9 +1400,12 @@ static int preallocate(BlockDriverState *bs) > int ret; > QCowL2Meta *meta; > > + assert(mode != PREALLOC_OFF); > + > nb_sectors = bdrv_getlength(bs) >> 9; > 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, > @@ -1424,6 +1433,11 @@ static int preallocate(BlockDriverState *bs) > offset += num << 9; > } > > + /* Then write zeros to the cluster data, if requested */ > + if (mode == PREALLOC_FULL) { > + bdrv_zero_init(bs->file, offset, bdrv_getlength(bs)); > + } > + > /* > * It is expected that the image file is large enough to actually > contain > * all of the allocated clusters (otherwise we get failing reads > after > @@ -1572,11 +1586,11 @@ static int qcow2_create2(const char *filename, > int64_t total_size, > } > } > > - /* And if we're supposed to preallocate metadata, do that now */ > + /* And if we're supposed to preallocate data, do that now */ > if (prealloc) { > BDRVQcowState *
On Wed, Nov 13, 2013 at 07:03:03AM +0100, Peter Lieven wrote: > What is your use case for this seris? QCOW2 creation or converting > anything to QCOW2? For the later case you could use "qemu-img convert -S 0 > ..." > starting in 1.8. The former. Seems "qemu-img convert -S 0" do the same thing but at converting time, maybe we can share some code. But let me dig the code first. > > Peter > > Hu Tao wrote: > > This adds a preallocation=full mode to qcow2 image creation, which > > creates a non-sparse image file. > > > > Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> > > --- > > block/qcow2.c | 28 ++++++++++++++++++++++------ > > 1 file changed, 22 insertions(+), 6 deletions(-) > > > > diff --git a/block/qcow2.c b/block/qcow2.c > > index 359030f..d3ca6cf 100644 > > --- a/block/qcow2.c > > +++ b/block/qcow2.c > > @@ -1385,7 +1385,13 @@ static int > > qcow2_change_backing_file(BlockDriverState *bs, > > return qcow2_update_header(bs); > > } > > > > -static int preallocate(BlockDriverState *bs) > > +enum prealloc_mode { > > + PREALLOC_OFF = 0, > > + PREALLOC_METADATA, > > + PREALLOC_FULL, > > +}; > > + > > +static int preallocate(BlockDriverState *bs, enum prealloc_mode mode) > > { > > uint64_t nb_sectors; > > uint64_t offset; > > @@ -1394,9 +1400,12 @@ static int preallocate(BlockDriverState *bs) > > int ret; > > QCowL2Meta *meta; > > > > + assert(mode != PREALLOC_OFF); > > + > > nb_sectors = bdrv_getlength(bs) >> 9; > > 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, > > @@ -1424,6 +1433,11 @@ static int preallocate(BlockDriverState *bs) > > offset += num << 9; > > } > > > > + /* Then write zeros to the cluster data, if requested */ > > + if (mode == PREALLOC_FULL) { > > + bdrv_zero_init(bs->file, offset, bdrv_getlength(bs)); > > + } > > + > > /* > > * It is expected that the image file is large enough to actually > > contain > > * all of the allocated clusters (otherwise we get failing reads > > after > > @@ -1572,11 +1586,11 @@ static int qcow2_create2(const char *filename, > > int64_t total_size, > > } > > } > > > > - /* And if we're supposed to preallocate metadata, do that now */ > > + /* And if we're supposed to preallocate data, do that now */ > > if (prealloc) { > > BDRVQcowState * >
On Fri, Nov 15, 2013 at 09:29:43AM +0800, Hu Tao wrote: > On Wed, Nov 13, 2013 at 07:03:03AM +0100, Peter Lieven wrote: > > What is your use case for this seris? QCOW2 creation or converting > > anything to QCOW2? For the later case you could use "qemu-img convert -S 0 > > ..." > > starting in 1.8. > > The former. Seems "qemu-img convert -S 0" do the same thing but at > converting time, maybe we can share some code. But let me dig the > code first. The purpose is to using posix_fallocate() to preallocate space, other than writing zeros to do it. Because the latter is pretty slow. > > > > > Peter > > > > Hu Tao wrote: > > > This adds a preallocation=full mode to qcow2 image creation, which > > > creates a non-sparse image file. > > > > > > Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> > > > --- > > > block/qcow2.c | 28 ++++++++++++++++++++++------ > > > 1 file changed, 22 insertions(+), 6 deletions(-) > > > > > > diff --git a/block/qcow2.c b/block/qcow2.c > > > index 359030f..d3ca6cf 100644 > > > --- a/block/qcow2.c > > > +++ b/block/qcow2.c > > > @@ -1385,7 +1385,13 @@ static int > > > qcow2_change_backing_file(BlockDriverState *bs, > > > return qcow2_update_header(bs); > > > } > > > > > > -static int preallocate(BlockDriverState *bs) > > > +enum prealloc_mode { > > > + PREALLOC_OFF = 0, > > > + PREALLOC_METADATA, > > > + PREALLOC_FULL, > > > +}; > > > + > > > +static int preallocate(BlockDriverState *bs, enum prealloc_mode mode) > > > { > > > uint64_t nb_sectors; > > > uint64_t offset; > > > @@ -1394,9 +1400,12 @@ static int preallocate(BlockDriverState *bs) > > > int ret; > > > QCowL2Meta *meta; > > > > > > + assert(mode != PREALLOC_OFF); > > > + > > > nb_sectors = bdrv_getlength(bs) >> 9; > > > 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, > > > @@ -1424,6 +1433,11 @@ static int preallocate(BlockDriverState *bs) > > > offset += num << 9; > > > } > > > > > > + /* Then write zeros to the cluster data, if requested */ > > > + if (mode == PREALLOC_FULL) { > > > + bdrv_zero_init(bs->file, offset, bdrv_getlength(bs)); > > > + } > > > + > > > /* > > > * It is expected that the image file is large enough to actually > > > contain > > > * all of the allocated clusters (otherwise we get failing reads > > > after > > > @@ -1572,11 +1586,11 @@ static int qcow2_create2(const char *filename, > > > int64_t total_size, > > > } > > > } > > > > > > - /* And if we're supposed to preallocate metadata, do that now */ > > > + /* And if we're supposed to preallocate data, do that now */ > > > if (prealloc) { > > > BDRVQcowState * > >
diff --git a/block/qcow2.c b/block/qcow2.c index 359030f..d3ca6cf 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1385,7 +1385,13 @@ static int qcow2_change_backing_file(BlockDriverState *bs, return qcow2_update_header(bs); } -static int preallocate(BlockDriverState *bs) +enum prealloc_mode { + PREALLOC_OFF = 0, + PREALLOC_METADATA, + PREALLOC_FULL, +}; + +static int preallocate(BlockDriverState *bs, enum prealloc_mode mode) { uint64_t nb_sectors; uint64_t offset; @@ -1394,9 +1400,12 @@ static int preallocate(BlockDriverState *bs) int ret; QCowL2Meta *meta; + assert(mode != PREALLOC_OFF); + nb_sectors = bdrv_getlength(bs) >> 9; 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, @@ -1424,6 +1433,11 @@ static int preallocate(BlockDriverState *bs) offset += num << 9; } + /* Then write zeros to the cluster data, if requested */ + if (mode == PREALLOC_FULL) { + bdrv_zero_init(bs->file, offset, bdrv_getlength(bs)); + } + /* * It is expected that the image file is large enough to actually contain * all of the allocated clusters (otherwise we get failing reads after @@ -1572,11 +1586,11 @@ static int qcow2_create2(const char *filename, int64_t total_size, } } - /* And if we're supposed to preallocate metadata, do that now */ + /* And if we're supposed to preallocate data, do that now */ if (prealloc) { BDRVQcowState *s = bs->opaque; qemu_co_mutex_lock(&s->lock); - ret = preallocate(bs); + ret = preallocate(bs, prealloc); qemu_co_mutex_unlock(&s->lock); if (ret < 0) { error_setg_errno(errp, -ret, "Could not preallocate metadata"); @@ -1629,9 +1643,11 @@ static int qcow2_create(const char *filename, QEMUOptionParameter *options, } } else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) { if (!options->value.s || !strcmp(options->value.s, "off")) { - prealloc = 0; + prealloc = PREALLOC_OFF; } else if (!strcmp(options->value.s, "metadata")) { - prealloc = 1; + prealloc = PREALLOC_METADATA; + } else if (!strcmp(options->value.s, "full")) { + prealloc = PREALLOC_FULL; } else { error_setg(errp, "Invalid preallocation mode: '%s'", options->value.s); @@ -2221,7 +2237,7 @@ static QEMUOptionParameter qcow2_create_options[] = { { .name = BLOCK_OPT_PREALLOC, .type = OPT_STRING, - .help = "Preallocation mode (allowed values: off, metadata)" + .help = "Preallocation mode (allowed values: off, metadata, full)" }, { .name = BLOCK_OPT_LAZY_REFCOUNTS,
This adds a preallocation=full mode to qcow2 image creation, which creates a non-sparse image file. Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> --- block/qcow2.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-)