* [Qemu-devel] [PATCH v5 0/4] qemu-img: fix bugs when cluster size is larger than the default value
@ 2014-01-26 3:12 Hu Tao
2014-01-26 3:12 ` [Qemu-devel] [PATCH v5 1/4] qcow2: remove n_start and n_end of qcow2_alloc_cluster_offset() Hu Tao
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: Hu Tao @ 2014-01-26 3:12 UTC (permalink / raw)
To: qemu-devel; +Cc: Kevin Wolf, Benoît Canet
This series fixes several bugs of qcow2 when doing preallocation with a
cluster_size larger than the default value.
v5:
- limit cur_nr_sectors for the encrypted case (patch 1)
- fix some grammar problems in commit messages and make commit messages
more understandable
Hu Tao (4):
qcow2: remove n_start and n_end of qcow2_alloc_cluster_offset()
qcow2: fix offset overflow in qcow2_alloc_clusters_at()
qcow2: check for NULL l2meta
qemu-iotests: add test for qcow2 preallocation with different cluster
sizes
block/qcow2-cluster.c | 14 +++++------
block/qcow2-refcount.c | 8 +++++-
block/qcow2.c | 44 ++++++++++++++++----------------
block/qcow2.h | 2 +-
tests/qemu-iotests/079 | 63 ++++++++++++++++++++++++++++++++++++++++++++++
tests/qemu-iotests/079.out | 32 +++++++++++++++++++++++
tests/qemu-iotests/group | 1 +
trace-events | 2 +-
8 files changed, 134 insertions(+), 32 deletions(-)
create mode 100755 tests/qemu-iotests/079
create mode 100644 tests/qemu-iotests/079.out
--
1.8.5.2.229.g4448466
^ permalink raw reply [flat|nested] 9+ messages in thread* [Qemu-devel] [PATCH v5 1/4] qcow2: remove n_start and n_end of qcow2_alloc_cluster_offset() 2014-01-26 3:12 [Qemu-devel] [PATCH v5 0/4] qemu-img: fix bugs when cluster size is larger than the default value Hu Tao @ 2014-01-26 3:12 ` Hu Tao 2014-01-26 4:14 ` Benoît Canet 2014-01-26 3:12 ` [Qemu-devel] [PATCH v5 2/4] qcow2: fix offset overflow in qcow2_alloc_clusters_at() Hu Tao ` (3 subsequent siblings) 4 siblings, 1 reply; 9+ messages in thread From: Hu Tao @ 2014-01-26 3:12 UTC (permalink / raw) To: qemu-devel; +Cc: Kevin Wolf, Benoît Canet n_start can be actually calculated from offset. The number of sectors to be allocated(n_end - n_start) can be passed in in num. By removing n_start and n_end, we can save two parameters. The side effect is there is a bug in qcow2.c:preallocate() that passes incorrect n_start to qcow2_alloc_cluster_offset() is fixed. The bug can be triggerred by a larger cluster size than the default value(65536), for example: ./qemu-img create -f qcow2 \ -o 'cluster_size=131072,preallocation=metadata' file.img 4G Reviewed-by: Max Reitz <mreitz@redhat.com> Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> --- block/qcow2-cluster.c | 14 ++++++-------- block/qcow2.c | 13 +++++++------ block/qcow2.h | 2 +- trace-events | 2 +- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 8534084..c57f39d 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1182,7 +1182,7 @@ fail: * Return 0 on success and -errno in error cases */ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, - int n_start, int n_end, int *num, uint64_t *host_offset, QCowL2Meta **m) + int *num, uint64_t *host_offset, QCowL2Meta **m) { BDRVQcowState *s = bs->opaque; uint64_t start, remaining; @@ -1190,15 +1190,13 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, uint64_t cur_bytes; int ret; - trace_qcow2_alloc_clusters_offset(qemu_coroutine_self(), offset, - n_start, n_end); + trace_qcow2_alloc_clusters_offset(qemu_coroutine_self(), offset, *num); - assert(n_start * BDRV_SECTOR_SIZE == offset_into_cluster(s, offset)); - offset = start_of_cluster(s, offset); + assert((offset & ~BDRV_SECTOR_MASK) == 0); again: - start = offset + (n_start << BDRV_SECTOR_BITS); - remaining = (n_end - n_start) << BDRV_SECTOR_BITS; + start = offset; + remaining = *num << BDRV_SECTOR_BITS; cluster_offset = 0; *host_offset = 0; cur_bytes = 0; @@ -1284,7 +1282,7 @@ again: } } - *num = (n_end - n_start) - (remaining >> BDRV_SECTOR_BITS); + *num -= remaining >> BDRV_SECTOR_BITS; assert(*num > 0); assert(*host_offset != 0); diff --git a/block/qcow2.c b/block/qcow2.c index 8ec9db1..effdd56 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -992,7 +992,6 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs, { BDRVQcowState *s = bs->opaque; int index_in_cluster; - int n_end; int ret; int cur_nr_sectors; /* number of sectors in current iteration */ uint64_t cluster_offset; @@ -1016,14 +1015,16 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs, trace_qcow2_writev_start_part(qemu_coroutine_self()); index_in_cluster = sector_num & (s->cluster_sectors - 1); - n_end = index_in_cluster + remaining_sectors; + cur_nr_sectors = remaining_sectors; if (s->crypt_method && - n_end > QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors) { - n_end = QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors; + cur_nr_sectors > + QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors - index_in_cluster) { + cur_nr_sectors = + QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors - index_in_cluster; } ret = qcow2_alloc_cluster_offset(bs, sector_num << 9, - index_in_cluster, n_end, &cur_nr_sectors, &cluster_offset, &l2meta); + &cur_nr_sectors, &cluster_offset, &l2meta); if (ret < 0) { goto fail; } @@ -1400,7 +1401,7 @@ static int preallocate(BlockDriverState *bs) while (nb_sectors) { num = MIN(nb_sectors, INT_MAX >> 9); - ret = qcow2_alloc_cluster_offset(bs, offset, 0, num, &num, + ret = qcow2_alloc_cluster_offset(bs, offset, &num, &host_offset, &meta); if (ret < 0) { return ret; diff --git a/block/qcow2.h b/block/qcow2.h index 303eb26..84e1344 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -468,7 +468,7 @@ void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num, int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, int *num, uint64_t *cluster_offset); int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, - int n_start, int n_end, int *num, uint64_t *host_offset, QCowL2Meta **m); + int *num, uint64_t *host_offset, QCowL2Meta **m); uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, uint64_t offset, int compressed_size); diff --git a/trace-events b/trace-events index 9f4456a..9b4e586 100644 --- a/trace-events +++ b/trace-events @@ -494,7 +494,7 @@ qcow2_writev_done_part(void *co, int cur_nr_sectors) "co %p cur_nr_sectors %d" qcow2_writev_data(void *co, uint64_t offset) "co %p offset %" PRIx64 # block/qcow2-cluster.c -qcow2_alloc_clusters_offset(void *co, uint64_t offset, int n_start, int n_end) "co %p offet %" PRIx64 " n_start %d n_end %d" +qcow2_alloc_clusters_offset(void *co, uint64_t offset, int num) "co %p offet %" PRIx64 " num %d" qcow2_handle_copied(void *co, uint64_t guest_offset, uint64_t host_offset, uint64_t bytes) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " bytes %" PRIx64 qcow2_handle_alloc(void *co, uint64_t guest_offset, uint64_t host_offset, uint64_t bytes) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " bytes %" PRIx64 qcow2_do_alloc_clusters_offset(void *co, uint64_t guest_offset, uint64_t host_offset, int nb_clusters) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " nb_clusters %d" -- 1.8.5.2.229.g4448466 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v5 1/4] qcow2: remove n_start and n_end of qcow2_alloc_cluster_offset() 2014-01-26 3:12 ` [Qemu-devel] [PATCH v5 1/4] qcow2: remove n_start and n_end of qcow2_alloc_cluster_offset() Hu Tao @ 2014-01-26 4:14 ` Benoît Canet 0 siblings, 0 replies; 9+ messages in thread From: Benoît Canet @ 2014-01-26 4:14 UTC (permalink / raw) To: Hu Tao; +Cc: Kevin Wolf, Benoît Canet, qemu-devel Le Sunday 26 Jan 2014 à 11:12:37 (+0800), Hu Tao a écrit : > n_start can be actually calculated from offset. The number of > sectors to be allocated(n_end - n_start) can be passed in in > num. By removing n_start and n_end, we can save two parameters. > > The side effect is there is a bug in qcow2.c:preallocate() that > passes incorrect n_start to qcow2_alloc_cluster_offset() is > fixed. The bug can be triggerred by a larger cluster size than > the default value(65536), for example: > > ./qemu-img create -f qcow2 \ > -o 'cluster_size=131072,preallocation=metadata' file.img 4G > > Reviewed-by: Max Reitz <mreitz@redhat.com> > Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> > --- > block/qcow2-cluster.c | 14 ++++++-------- > block/qcow2.c | 13 +++++++------ > block/qcow2.h | 2 +- > trace-events | 2 +- > 4 files changed, 15 insertions(+), 16 deletions(-) > > diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c > index 8534084..c57f39d 100644 > --- a/block/qcow2-cluster.c > +++ b/block/qcow2-cluster.c > @@ -1182,7 +1182,7 @@ fail: > * Return 0 on success and -errno in error cases > */ > int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, > - int n_start, int n_end, int *num, uint64_t *host_offset, QCowL2Meta **m) > + int *num, uint64_t *host_offset, QCowL2Meta **m) > { > BDRVQcowState *s = bs->opaque; > uint64_t start, remaining; > @@ -1190,15 +1190,13 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, > uint64_t cur_bytes; > int ret; > > - trace_qcow2_alloc_clusters_offset(qemu_coroutine_self(), offset, > - n_start, n_end); > + trace_qcow2_alloc_clusters_offset(qemu_coroutine_self(), offset, *num); > > - assert(n_start * BDRV_SECTOR_SIZE == offset_into_cluster(s, offset)); > - offset = start_of_cluster(s, offset); > + assert((offset & ~BDRV_SECTOR_MASK) == 0); > > again: > - start = offset + (n_start << BDRV_SECTOR_BITS); > - remaining = (n_end - n_start) << BDRV_SECTOR_BITS; > + start = offset; > + remaining = *num << BDRV_SECTOR_BITS; > cluster_offset = 0; > *host_offset = 0; > cur_bytes = 0; > @@ -1284,7 +1282,7 @@ again: > } > } > > - *num = (n_end - n_start) - (remaining >> BDRV_SECTOR_BITS); > + *num -= remaining >> BDRV_SECTOR_BITS; > assert(*num > 0); > assert(*host_offset != 0); > > diff --git a/block/qcow2.c b/block/qcow2.c > index 8ec9db1..effdd56 100644 > --- a/block/qcow2.c > +++ b/block/qcow2.c > @@ -992,7 +992,6 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs, > { > BDRVQcowState *s = bs->opaque; > int index_in_cluster; > - int n_end; > int ret; > int cur_nr_sectors; /* number of sectors in current iteration */ > uint64_t cluster_offset; > @@ -1016,14 +1015,16 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs, > > trace_qcow2_writev_start_part(qemu_coroutine_self()); > index_in_cluster = sector_num & (s->cluster_sectors - 1); > - n_end = index_in_cluster + remaining_sectors; > + cur_nr_sectors = remaining_sectors; > if (s->crypt_method && > - n_end > QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors) { > - n_end = QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors; > + cur_nr_sectors > > + QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors - index_in_cluster) { > + cur_nr_sectors = > + QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors - index_in_cluster; > } > > ret = qcow2_alloc_cluster_offset(bs, sector_num << 9, > - index_in_cluster, n_end, &cur_nr_sectors, &cluster_offset, &l2meta); > + &cur_nr_sectors, &cluster_offset, &l2meta); > if (ret < 0) { > goto fail; > } > @@ -1400,7 +1401,7 @@ static int preallocate(BlockDriverState *bs) > > while (nb_sectors) { > num = MIN(nb_sectors, INT_MAX >> 9); > - ret = qcow2_alloc_cluster_offset(bs, offset, 0, num, &num, > + ret = qcow2_alloc_cluster_offset(bs, offset, &num, > &host_offset, &meta); > if (ret < 0) { > return ret; > diff --git a/block/qcow2.h b/block/qcow2.h > index 303eb26..84e1344 100644 > --- a/block/qcow2.h > +++ b/block/qcow2.h > @@ -468,7 +468,7 @@ void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num, > int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, > int *num, uint64_t *cluster_offset); > int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, > - int n_start, int n_end, int *num, uint64_t *host_offset, QCowL2Meta **m); > + int *num, uint64_t *host_offset, QCowL2Meta **m); > uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, > uint64_t offset, > int compressed_size); > diff --git a/trace-events b/trace-events > index 9f4456a..9b4e586 100644 > --- a/trace-events > +++ b/trace-events > @@ -494,7 +494,7 @@ qcow2_writev_done_part(void *co, int cur_nr_sectors) "co %p cur_nr_sectors %d" > qcow2_writev_data(void *co, uint64_t offset) "co %p offset %" PRIx64 > > # block/qcow2-cluster.c > -qcow2_alloc_clusters_offset(void *co, uint64_t offset, int n_start, int n_end) "co %p offet %" PRIx64 " n_start %d n_end %d" > +qcow2_alloc_clusters_offset(void *co, uint64_t offset, int num) "co %p offet %" PRIx64 " num %d" > qcow2_handle_copied(void *co, uint64_t guest_offset, uint64_t host_offset, uint64_t bytes) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " bytes %" PRIx64 > qcow2_handle_alloc(void *co, uint64_t guest_offset, uint64_t host_offset, uint64_t bytes) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " bytes %" PRIx64 > qcow2_do_alloc_clusters_offset(void *co, uint64_t guest_offset, uint64_t host_offset, int nb_clusters) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " nb_clusters %d" > -- > 1.8.5.2.229.g4448466 > Reviewed-by: Benoit Canet <benoit@irqsave.net> ^ permalink raw reply [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH v5 2/4] qcow2: fix offset overflow in qcow2_alloc_clusters_at() 2014-01-26 3:12 [Qemu-devel] [PATCH v5 0/4] qemu-img: fix bugs when cluster size is larger than the default value Hu Tao 2014-01-26 3:12 ` [Qemu-devel] [PATCH v5 1/4] qcow2: remove n_start and n_end of qcow2_alloc_cluster_offset() Hu Tao @ 2014-01-26 3:12 ` Hu Tao 2014-01-26 4:15 ` Benoît Canet 2014-01-26 3:12 ` [Qemu-devel] [PATCH v5 3/4] qcow2: check for NULL l2meta Hu Tao ` (2 subsequent siblings) 4 siblings, 1 reply; 9+ messages in thread From: Hu Tao @ 2014-01-26 3:12 UTC (permalink / raw) To: qemu-devel; +Cc: Kevin Wolf, Benoît Canet When cluster size is big enough it can lead to an offset overflow in qcow2_alloc_clusters_at(). This patch fixes it. The allocation is stopped each time at L2 table boundary (see handle_alloc()), so the possible maximum bytes could be 2^(cluster_bits - 3 + cluster_bits) cluster_bits - 3 is used to compute the number of entry by L2 and the additional cluster_bits is to take into account each clusters referenced by the L2 entries. so int is safe for cluster_bits<=17, unsafe otherwise. Reviewed-by: Max Reitz <mreitz@redhat.com> Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> --- block/qcow2-refcount.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index c974abe..8712d8b 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -676,7 +676,13 @@ int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset, BDRVQcowState *s = bs->opaque; uint64_t cluster_index; uint64_t old_free_cluster_index; - int i, refcount, ret; + uint64_t i; + int refcount, ret; + + assert(nb_clusters >= 0); + if (nb_clusters == 0) { + return 0; + } /* Check how many clusters there are free */ cluster_index = offset >> s->cluster_bits; -- 1.8.5.2.229.g4448466 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v5 2/4] qcow2: fix offset overflow in qcow2_alloc_clusters_at() 2014-01-26 3:12 ` [Qemu-devel] [PATCH v5 2/4] qcow2: fix offset overflow in qcow2_alloc_clusters_at() Hu Tao @ 2014-01-26 4:15 ` Benoît Canet 0 siblings, 0 replies; 9+ messages in thread From: Benoît Canet @ 2014-01-26 4:15 UTC (permalink / raw) To: Hu Tao; +Cc: Kevin Wolf, Benoît Canet, qemu-devel Le Sunday 26 Jan 2014 à 11:12:38 (+0800), Hu Tao a écrit : > When cluster size is big enough it can lead to an offset overflow > in qcow2_alloc_clusters_at(). This patch fixes it. > > The allocation is stopped each time at L2 table boundary > (see handle_alloc()), so the possible maximum bytes could be > > 2^(cluster_bits - 3 + cluster_bits) > > cluster_bits - 3 is used to compute the number of entry by L2 > and the additional cluster_bits is to take into account each > clusters referenced by the L2 entries. > > so int is safe for cluster_bits<=17, unsafe otherwise. > > Reviewed-by: Max Reitz <mreitz@redhat.com> > Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> > --- > block/qcow2-refcount.c | 8 +++++++- > 1 file changed, 7 insertions(+), 1 deletion(-) > > diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c > index c974abe..8712d8b 100644 > --- a/block/qcow2-refcount.c > +++ b/block/qcow2-refcount.c > @@ -676,7 +676,13 @@ int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset, > BDRVQcowState *s = bs->opaque; > uint64_t cluster_index; > uint64_t old_free_cluster_index; > - int i, refcount, ret; > + uint64_t i; > + int refcount, ret; > + > + assert(nb_clusters >= 0); > + if (nb_clusters == 0) { > + return 0; > + } > > /* Check how many clusters there are free */ > cluster_index = offset >> s->cluster_bits; > -- > 1.8.5.2.229.g4448466 > Reviewed-by: Benoit Canet <benoit@irqsave.net> ^ permalink raw reply [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH v5 3/4] qcow2: check for NULL l2meta 2014-01-26 3:12 [Qemu-devel] [PATCH v5 0/4] qemu-img: fix bugs when cluster size is larger than the default value Hu Tao 2014-01-26 3:12 ` [Qemu-devel] [PATCH v5 1/4] qcow2: remove n_start and n_end of qcow2_alloc_cluster_offset() Hu Tao 2014-01-26 3:12 ` [Qemu-devel] [PATCH v5 2/4] qcow2: fix offset overflow in qcow2_alloc_clusters_at() Hu Tao @ 2014-01-26 3:12 ` Hu Tao 2014-01-26 4:16 ` Benoît Canet 2014-01-26 3:12 ` [Qemu-devel] [PATCH v5 4/4] qemu-iotests: add test for qcow2 preallocation with different cluster sizes Hu Tao 2014-02-03 16:14 ` [Qemu-devel] [PATCH v5 0/4] qemu-img: fix bugs when cluster size is larger than the default value Kevin Wolf 4 siblings, 1 reply; 9+ messages in thread From: Hu Tao @ 2014-01-26 3:12 UTC (permalink / raw) To: qemu-devel; +Cc: Kevin Wolf, Benoît Canet In the case of a metadata preallocation with a large cluster size, qcow2_alloc_cluster_offset() can allocate nothing and returns a NULL l2meta. This patch checks for it and link2 l2 with only valid l2meta. Replace 9 and 512 with BDRV_SECTOR_BITS, BDRV_SECTOR_SIZE respectively while at the function. Reviewed-by: Max Reitz <mreitz@redhat.com> Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> --- block/qcow2.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index effdd56..bfdbfa1 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1396,34 +1396,34 @@ static int preallocate(BlockDriverState *bs) int ret; QCowL2Meta *meta; - nb_sectors = bdrv_getlength(bs) >> 9; + nb_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS; offset = 0; while (nb_sectors) { - num = MIN(nb_sectors, INT_MAX >> 9); + num = MIN(nb_sectors, INT_MAX >> BDRV_SECTOR_BITS); ret = qcow2_alloc_cluster_offset(bs, offset, &num, &host_offset, &meta); if (ret < 0) { return ret; } - ret = qcow2_alloc_cluster_link_l2(bs, meta); - if (ret < 0) { - qcow2_free_any_clusters(bs, meta->alloc_offset, meta->nb_clusters, - QCOW2_DISCARD_NEVER); - return ret; - } - - /* There are no dependent requests, but we need to remove our request - * from the list of in-flight requests */ if (meta != NULL) { + ret = qcow2_alloc_cluster_link_l2(bs, meta); + if (ret < 0) { + qcow2_free_any_clusters(bs, meta->alloc_offset, + meta->nb_clusters, QCOW2_DISCARD_NEVER); + return ret; + } + + /* There are no dependent requests, but we need to remove our + * request from the list of in-flight requests */ QLIST_REMOVE(meta, next_in_flight); } /* TODO Preallocate data if requested */ nb_sectors -= num; - offset += num << 9; + offset += num << BDRV_SECTOR_BITS; } /* @@ -1432,9 +1432,10 @@ static int preallocate(BlockDriverState *bs) * EOF). Extend the image to the last allocated sector. */ if (host_offset != 0) { - uint8_t buf[512]; - memset(buf, 0, 512); - ret = bdrv_write(bs->file, (host_offset >> 9) + num - 1, buf, 1); + uint8_t buf[BDRV_SECTOR_SIZE]; + memset(buf, 0, BDRV_SECTOR_SIZE); + ret = bdrv_write(bs->file, (host_offset >> BDRV_SECTOR_BITS) + num - 1, + buf, 1); if (ret < 0) { return ret; } -- 1.8.5.2.229.g4448466 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v5 3/4] qcow2: check for NULL l2meta 2014-01-26 3:12 ` [Qemu-devel] [PATCH v5 3/4] qcow2: check for NULL l2meta Hu Tao @ 2014-01-26 4:16 ` Benoît Canet 0 siblings, 0 replies; 9+ messages in thread From: Benoît Canet @ 2014-01-26 4:16 UTC (permalink / raw) To: Hu Tao; +Cc: Kevin Wolf, Benoît Canet, qemu-devel Le Sunday 26 Jan 2014 à 11:12:39 (+0800), Hu Tao a écrit : > In the case of a metadata preallocation with a large cluster size, > qcow2_alloc_cluster_offset() can allocate nothing and returns a > NULL l2meta. This patch checks for it and link2 l2 with only valid > l2meta. > > Replace 9 and 512 with BDRV_SECTOR_BITS, BDRV_SECTOR_SIZE > respectively while at the function. > > Reviewed-by: Max Reitz <mreitz@redhat.com> > Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> > --- > block/qcow2.c | 31 ++++++++++++++++--------------- > 1 file changed, 16 insertions(+), 15 deletions(-) > > diff --git a/block/qcow2.c b/block/qcow2.c > index effdd56..bfdbfa1 100644 > --- a/block/qcow2.c > +++ b/block/qcow2.c > @@ -1396,34 +1396,34 @@ static int preallocate(BlockDriverState *bs) > int ret; > QCowL2Meta *meta; > > - nb_sectors = bdrv_getlength(bs) >> 9; > + nb_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS; > offset = 0; > > while (nb_sectors) { > - num = MIN(nb_sectors, INT_MAX >> 9); > + num = MIN(nb_sectors, INT_MAX >> BDRV_SECTOR_BITS); > ret = qcow2_alloc_cluster_offset(bs, offset, &num, > &host_offset, &meta); > if (ret < 0) { > return ret; > } > > - ret = qcow2_alloc_cluster_link_l2(bs, meta); > - if (ret < 0) { > - qcow2_free_any_clusters(bs, meta->alloc_offset, meta->nb_clusters, > - QCOW2_DISCARD_NEVER); > - return ret; > - } > - > - /* There are no dependent requests, but we need to remove our request > - * from the list of in-flight requests */ > if (meta != NULL) { > + ret = qcow2_alloc_cluster_link_l2(bs, meta); > + if (ret < 0) { > + qcow2_free_any_clusters(bs, meta->alloc_offset, > + meta->nb_clusters, QCOW2_DISCARD_NEVER); > + return ret; > + } > + > + /* There are no dependent requests, but we need to remove our > + * request from the list of in-flight requests */ > QLIST_REMOVE(meta, next_in_flight); > } > > /* TODO Preallocate data if requested */ > > nb_sectors -= num; > - offset += num << 9; > + offset += num << BDRV_SECTOR_BITS; > } > > /* > @@ -1432,9 +1432,10 @@ static int preallocate(BlockDriverState *bs) > * EOF). Extend the image to the last allocated sector. > */ > if (host_offset != 0) { > - uint8_t buf[512]; > - memset(buf, 0, 512); > - ret = bdrv_write(bs->file, (host_offset >> 9) + num - 1, buf, 1); > + uint8_t buf[BDRV_SECTOR_SIZE]; > + memset(buf, 0, BDRV_SECTOR_SIZE); > + ret = bdrv_write(bs->file, (host_offset >> BDRV_SECTOR_BITS) + num - 1, > + buf, 1); > if (ret < 0) { > return ret; > } > -- > 1.8.5.2.229.g4448466 > > Reviewed-by: Benoit Canet <benoit@irqsave.net> ^ permalink raw reply [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH v5 4/4] qemu-iotests: add test for qcow2 preallocation with different cluster sizes 2014-01-26 3:12 [Qemu-devel] [PATCH v5 0/4] qemu-img: fix bugs when cluster size is larger than the default value Hu Tao ` (2 preceding siblings ...) 2014-01-26 3:12 ` [Qemu-devel] [PATCH v5 3/4] qcow2: check for NULL l2meta Hu Tao @ 2014-01-26 3:12 ` Hu Tao 2014-02-03 16:14 ` [Qemu-devel] [PATCH v5 0/4] qemu-img: fix bugs when cluster size is larger than the default value Kevin Wolf 4 siblings, 0 replies; 9+ messages in thread From: Hu Tao @ 2014-01-26 3:12 UTC (permalink / raw) To: qemu-devel; +Cc: Kevin Wolf, Benoît Canet Reviewed-by: Max Reitz <mreitz@redhat.com> Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> --- tests/qemu-iotests/079 | 63 ++++++++++++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/079.out | 32 +++++++++++++++++++++++ tests/qemu-iotests/group | 1 + 3 files changed, 96 insertions(+) create mode 100755 tests/qemu-iotests/079 create mode 100644 tests/qemu-iotests/079.out diff --git a/tests/qemu-iotests/079 b/tests/qemu-iotests/079 new file mode 100755 index 0000000..2142bbb --- /dev/null +++ b/tests/qemu-iotests/079 @@ -0,0 +1,63 @@ +#!/bin/bash +# +# Test qcow2 preallocation with different cluster_sizes +# +# Copyright (C) 2014 Fujitsu. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=hutao@cn.fujitsu.com + +seq=`basename $0` +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto file +_supported_os Linux + +function test_qemu_img() +{ + echo qemu-img "$@" | _filter_testdir + $QEMU_IMG "$@" 2>&1 | _filter_testdir + echo +} + +echo "=== Check option preallocation and cluster_size ===" +echo +cluster_sizes="16384 32768 65536 131072 262144 524288 1048576 2097152 4194304" + +for s in $cluster_sizes; do + test_qemu_img create -f $IMGFMT -o preallocation=metadata,cluster_size=$s "$TEST_IMG" 4G +done + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/079.out b/tests/qemu-iotests/079.out new file mode 100644 index 0000000..ef4b8c9 --- /dev/null +++ b/tests/qemu-iotests/079.out @@ -0,0 +1,32 @@ +QA output created by 079 +=== Check option preallocation and cluster_size === + +qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=16384 TEST_DIR/t.qcow2 4G +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=16384 preallocation='metadata' lazy_refcounts=off + +qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=32768 TEST_DIR/t.qcow2 4G +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=32768 preallocation='metadata' lazy_refcounts=off + +qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=65536 TEST_DIR/t.qcow2 4G +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=65536 preallocation='metadata' lazy_refcounts=off + +qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=131072 TEST_DIR/t.qcow2 4G +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=131072 preallocation='metadata' lazy_refcounts=off + +qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=262144 TEST_DIR/t.qcow2 4G +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=262144 preallocation='metadata' lazy_refcounts=off + +qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=524288 TEST_DIR/t.qcow2 4G +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=524288 preallocation='metadata' lazy_refcounts=off + +qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=1048576 TEST_DIR/t.qcow2 4G +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=1048576 preallocation='metadata' lazy_refcounts=off + +qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=2097152 TEST_DIR/t.qcow2 4G +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=2097152 preallocation='metadata' lazy_refcounts=off + +qemu-img create -f qcow2 -o preallocation=metadata,cluster_size=4194304 TEST_DIR/t.qcow2 4G +qemu-img: TEST_DIR/t.qcow2: Cluster size must be a power of two between 512 and 2048k +Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=4194304 preallocation='metadata' lazy_refcounts=off + +*** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index cc750c9..3bb22c2 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -79,3 +79,4 @@ 070 rw auto 073 rw auto 074 rw auto +079 rw auto -- 1.8.5.2.229.g4448466 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH v5 0/4] qemu-img: fix bugs when cluster size is larger than the default value 2014-01-26 3:12 [Qemu-devel] [PATCH v5 0/4] qemu-img: fix bugs when cluster size is larger than the default value Hu Tao ` (3 preceding siblings ...) 2014-01-26 3:12 ` [Qemu-devel] [PATCH v5 4/4] qemu-iotests: add test for qcow2 preallocation with different cluster sizes Hu Tao @ 2014-02-03 16:14 ` Kevin Wolf 4 siblings, 0 replies; 9+ messages in thread From: Kevin Wolf @ 2014-02-03 16:14 UTC (permalink / raw) To: Hu Tao; +Cc: Benoît Canet, qemu-devel Am 26.01.2014 um 04:12 hat Hu Tao geschrieben: > This series fixes several bugs of qcow2 when doing preallocation with a > cluster_size larger than the default value. > > v5: > - limit cur_nr_sectors for the encrypted case (patch 1) > - fix some grammar problems in commit messages and make commit messages > more understandable Thanks, applied to the block branch. Kevin ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2014-02-03 16:14 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-01-26 3:12 [Qemu-devel] [PATCH v5 0/4] qemu-img: fix bugs when cluster size is larger than the default value Hu Tao 2014-01-26 3:12 ` [Qemu-devel] [PATCH v5 1/4] qcow2: remove n_start and n_end of qcow2_alloc_cluster_offset() Hu Tao 2014-01-26 4:14 ` Benoît Canet 2014-01-26 3:12 ` [Qemu-devel] [PATCH v5 2/4] qcow2: fix offset overflow in qcow2_alloc_clusters_at() Hu Tao 2014-01-26 4:15 ` Benoît Canet 2014-01-26 3:12 ` [Qemu-devel] [PATCH v5 3/4] qcow2: check for NULL l2meta Hu Tao 2014-01-26 4:16 ` Benoît Canet 2014-01-26 3:12 ` [Qemu-devel] [PATCH v5 4/4] qemu-iotests: add test for qcow2 preallocation with different cluster sizes Hu Tao 2014-02-03 16:14 ` [Qemu-devel] [PATCH v5 0/4] qemu-img: fix bugs when cluster size is larger than the default value Kevin Wolf
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.