Message ID | f1d8c4bcf7c94e0cedbd96f1d7df9ea9905bddb3.1584468723.git.berto@igalia.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add subcluster allocation to qcow2 | expand |
17.03.2020 21:16, Alberto Garcia wrote: > Setting the QCOW_OFLAG_ZERO bit of the L2 entry is forbidden if an > image has subclusters. Instead, the individual 'all zeroes' bits must > be used. > > Signed-off-by: Alberto Garcia <berto@igalia.com> > Reviewed-by: Max Reitz <mreitz@redhat.com> anyway: Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> still, some comments below > --- > block/qcow2-cluster.c | 14 ++++++++++---- > 1 file changed, 10 insertions(+), 4 deletions(-) > > diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c > index 6f2643ba53..746006a117 100644 > --- a/block/qcow2-cluster.c > +++ b/block/qcow2-cluster.c > @@ -1897,7 +1897,7 @@ static int zero_in_l2_slice(BlockDriverState *bs, uint64_t offset, As I see, function is not prepared to handle unaligned offset. Worth add an assertion while being here? > assert(nb_clusters <= INT_MAX); > > for (i = 0; i < nb_clusters; i++) { > - uint64_t old_offset; > + uint64_t old_offset, l2_entry = 0; I'd rename s/old_offset/old_l2_entry > QCow2ClusterType cluster_type; > > old_offset = get_l2_entry(s, l2_slice, l2_index + i); more context: > /* > * Minimize L2 changes if the cluster already reads back as > * zeroes with correct allocation. > */ > cluster_type = qcow2_get_cluster_type(bs, old_offset); > if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN || > (cluster_type == QCOW2_CLUSTER_ZERO_ALLOC && !unmap)) { Worth assert !has_subclusters(s), or mark image corrupted? > continue; > } > @@ -1914,12 +1914,18 @@ static int zero_in_l2_slice(BlockDriverState *bs, uint64_t offset, > > qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice); > if (cluster_type == QCOW2_CLUSTER_COMPRESSED || unmap) { > - set_l2_entry(s, l2_slice, l2_index + i, QCOW_OFLAG_ZERO); > qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST); > } else { > - uint64_t entry = get_l2_entry(s, l2_slice, l2_index + i); > - set_l2_entry(s, l2_slice, l2_index + i, entry | QCOW_OFLAG_ZERO); > + l2_entry = get_l2_entry(s, l2_slice, l2_index + i); > } > + > + if (has_subclusters(s)) { > + set_l2_bitmap(s, l2_slice, l2_index + i, QCOW_L2_BITMAP_ALL_ZEROES); > + } else { > + l2_entry |= QCOW_OFLAG_ZERO; > + } > + > + set_l2_entry(s, l2_slice, l2_index + i, l2_entry); For subclasters & !unmap case we set the same value.. And we even don't need to get it. may be if (cluster_type == QCOW2_CLUSTER_COMPRESSED || unmap) { qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST); set_l2_entry(s, l2_slice, l2_index + i, has_subclusters(s) ? 0 : QCOW_OFLAG_ZERO); } else if (!has_subclusters(s)) { uint64_t entry = get_l2_entry(s, l2_slice, l2_index + i); set_l2_entry(s, l2_slice, l2_index + i, entry | QCOW_OFLAG_ZERO); } if (has_subclusters(s)) { set_l2_bitmap(s, l2_slice, l2_index + i, QCOW_L2_BITMAP_ALL_ZEROES); } > } > > qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice); >
On Wed 22 Apr 2020 01:06:42 PM CEST, Vladimir Sementsov-Ogievskiy wrote: >> @@ -1897,7 +1897,7 @@ static int zero_in_l2_slice(BlockDriverState *bs, uint64_t offset, > > As I see, function is not prepared to handle unaligned offset. Worth > add an assertion while being here? The only caller already asserts that, and the length parameter is not even the number of bytes but the number of clusters, so I don't think it's so important in this case. >> for (i = 0; i < nb_clusters; i++) { >> - uint64_t old_offset; >> + uint64_t old_offset, l2_entry = 0; > > I'd rename s/old_offset/old_l2_entry I think we can get rid of old_offset altogether. I'll think of a way to restructure the logics along the lines that you suggest. Thanks! Berto
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 6f2643ba53..746006a117 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1897,7 +1897,7 @@ static int zero_in_l2_slice(BlockDriverState *bs, uint64_t offset, assert(nb_clusters <= INT_MAX); for (i = 0; i < nb_clusters; i++) { - uint64_t old_offset; + uint64_t old_offset, l2_entry = 0; QCow2ClusterType cluster_type; old_offset = get_l2_entry(s, l2_slice, l2_index + i); @@ -1914,12 +1914,18 @@ static int zero_in_l2_slice(BlockDriverState *bs, uint64_t offset, qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice); if (cluster_type == QCOW2_CLUSTER_COMPRESSED || unmap) { - set_l2_entry(s, l2_slice, l2_index + i, QCOW_OFLAG_ZERO); qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST); } else { - uint64_t entry = get_l2_entry(s, l2_slice, l2_index + i); - set_l2_entry(s, l2_slice, l2_index + i, entry | QCOW_OFLAG_ZERO); + l2_entry = get_l2_entry(s, l2_slice, l2_index + i); } + + if (has_subclusters(s)) { + set_l2_bitmap(s, l2_slice, l2_index + i, QCOW_L2_BITMAP_ALL_ZEROES); + } else { + l2_entry |= QCOW_OFLAG_ZERO; + } + + set_l2_entry(s, l2_slice, l2_index + i, l2_entry); } qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);