Message ID | bdd6cca475832860905ccc4150af5cf8169c68be.1593342067.git.berto@igalia.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add subcluster allocation to qcow2 | expand |
On 28.06.20 13:02, Alberto Garcia wrote: > The L2 bitmap needs to be updated after each write to indicate what > new subclusters are now allocated. This needs to happen even if the > cluster was already allocated and the L2 entry was otherwise valid. > > In some cases however a write operation doesn't need change the L2 > bitmap (because all affected subclusters were already allocated). This > is detected in calculate_l2_meta(), and qcow2_alloc_cluster_link_l2() > is never called in those cases. > > Signed-off-by: Alberto Garcia <berto@igalia.com> > Reviewed-by: Eric Blake <eblake@redhat.com> > --- > block/qcow2-cluster.c | 18 ++++++++++++++++++ > 1 file changed, 18 insertions(+) Reviewed-by: Max Reitz <mreitz@redhat.com>
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index edfc8ea91c..2276cee6d6 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1061,6 +1061,24 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) assert((offset & L2E_OFFSET_MASK) == offset); set_l2_entry(s, l2_slice, l2_index + i, offset | QCOW_OFLAG_COPIED); + + /* Update bitmap with the subclusters that were just written */ + if (has_subclusters(s)) { + uint64_t l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index + i); + unsigned written_from = m->cow_start.offset; + unsigned written_to = m->cow_end.offset + m->cow_end.nb_bytes ?: + m->nb_clusters << s->cluster_bits; + int first_sc, last_sc; + /* Narrow written_from and written_to down to the current cluster */ + written_from = MAX(written_from, i << s->cluster_bits); + written_to = MIN(written_to, (i + 1) << s->cluster_bits); + assert(written_from < written_to); + first_sc = offset_to_sc_index(s, written_from); + last_sc = offset_to_sc_index(s, written_to - 1); + l2_bitmap |= QCOW_OFLAG_SUB_ALLOC_RANGE(first_sc, last_sc + 1); + l2_bitmap &= ~QCOW_OFLAG_SUB_ZERO_RANGE(first_sc, last_sc + 1); + set_l2_bitmap(s, l2_slice, l2_index + i, l2_bitmap); + } }