COW: Extend checking allocated bits to beyond one sector

cow_co_is_allocated() only checks one sector's worth of allocated bits
before returning. This is allowed but (slightly) inefficient, so extend
it to check all of the file's metadata sectors.

Signed-off-by: Charlie Shepherd <charlie@ctshepherd.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>

[kwolf: silenced compiler warning (-Wmaybe-uninitialized for changed)]
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Charlie Shepherd 2013-11-15 19:47:02 +01:00 committed by Kevin Wolf
parent 14b98fdaf3
commit 091b1108ca

View File

@ -152,18 +152,34 @@ static int coroutine_fn cow_co_is_allocated(BlockDriverState *bs,
{ {
int64_t bitnum = sector_num + sizeof(struct cow_header_v2) * 8; int64_t bitnum = sector_num + sizeof(struct cow_header_v2) * 8;
uint64_t offset = (bitnum / 8) & -BDRV_SECTOR_SIZE; uint64_t offset = (bitnum / 8) & -BDRV_SECTOR_SIZE;
uint8_t bitmap[BDRV_SECTOR_SIZE]; bool first = true;
int ret; int changed = 0, same = 0;
int changed;
ret = bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap)); do {
if (ret < 0) { int ret;
return ret; uint8_t bitmap[BDRV_SECTOR_SIZE];
}
bitnum &= BITS_PER_BITMAP_SECTOR - 1; bitnum &= BITS_PER_BITMAP_SECTOR - 1;
changed = cow_test_bit(bitnum, bitmap); int sector_bits = MIN(nb_sectors, BITS_PER_BITMAP_SECTOR - bitnum);
*num_same = cow_find_streak(bitmap, changed, bitnum, nb_sectors);
ret = bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap));
if (ret < 0) {
return ret;
}
if (first) {
changed = cow_test_bit(bitnum, bitmap);
first = false;
}
same += cow_find_streak(bitmap, changed, bitnum, nb_sectors);
bitnum += sector_bits;
nb_sectors -= sector_bits;
offset += BDRV_SECTOR_SIZE;
} while (nb_sectors);
*num_same = same;
return changed; return changed;
} }