qcow2: Add qcow2_get_subcluster_range_type()
There are situations in which we want to know how many contiguous subclusters of the same type there are in a given cluster. This can be done by simply iterating over the subclusters and repeatedly calling qcow2_get_subcluster_type() for each one of them. However once we determined the type of a subcluster we can check the rest efficiently by counting the number of adjacent ones (or zeroes) in the bitmap. This is what this function does. Signed-off-by: Alberto Garcia <berto@igalia.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Message-Id: <db917263d568ec6ffb4a41cac3c9100f96bf6c18.1594396418.git.berto@igalia.com> Signed-off-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
parent
34905d8eb1
commit
70d1cbae03
@ -375,6 +375,57 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* For a given L2 entry, count the number of contiguous subclusters of
|
||||
* the same type starting from @sc_from. Compressed clusters are
|
||||
* treated as if they were divided into subclusters of size
|
||||
* s->subcluster_size.
|
||||
*
|
||||
* Return the number of contiguous subclusters and set @type to the
|
||||
* subcluster type.
|
||||
*
|
||||
* If the L2 entry is invalid return -errno and set @type to
|
||||
* QCOW2_SUBCLUSTER_INVALID.
|
||||
*/
|
||||
G_GNUC_UNUSED
|
||||
static int qcow2_get_subcluster_range_type(BlockDriverState *bs,
|
||||
uint64_t l2_entry,
|
||||
uint64_t l2_bitmap,
|
||||
unsigned sc_from,
|
||||
QCow2SubclusterType *type)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
uint32_t val;
|
||||
|
||||
*type = qcow2_get_subcluster_type(bs, l2_entry, l2_bitmap, sc_from);
|
||||
|
||||
if (*type == QCOW2_SUBCLUSTER_INVALID) {
|
||||
return -EINVAL;
|
||||
} else if (!has_subclusters(s) || *type == QCOW2_SUBCLUSTER_COMPRESSED) {
|
||||
return s->subclusters_per_cluster - sc_from;
|
||||
}
|
||||
|
||||
switch (*type) {
|
||||
case QCOW2_SUBCLUSTER_NORMAL:
|
||||
val = l2_bitmap | QCOW_OFLAG_SUB_ALLOC_RANGE(0, sc_from);
|
||||
return cto32(val) - sc_from;
|
||||
|
||||
case QCOW2_SUBCLUSTER_ZERO_PLAIN:
|
||||
case QCOW2_SUBCLUSTER_ZERO_ALLOC:
|
||||
val = (l2_bitmap | QCOW_OFLAG_SUB_ZERO_RANGE(0, sc_from)) >> 32;
|
||||
return cto32(val) - sc_from;
|
||||
|
||||
case QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN:
|
||||
case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC:
|
||||
val = ((l2_bitmap >> 32) | l2_bitmap)
|
||||
& ~QCOW_OFLAG_SUB_ALLOC_RANGE(0, sc_from);
|
||||
return ctz32(val) - sc_from;
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks how many clusters in a given L2 slice are contiguous in the image
|
||||
* file. As soon as one of the flags in the bitmask stop_flags changes compared
|
||||
|
Loading…
Reference in New Issue
Block a user