Skip to content

Commit

Permalink
COW: Extend checking allocated bits to beyond one sector
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
ctshepherd authored and kevmw committed Nov 29, 2013
1 parent 14b98fd commit 091b110
Showing 1 changed file with 26 additions and 10 deletions.
36 changes: 26 additions & 10 deletions block/cow.c
Expand Up @@ -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;
uint64_t offset = (bitnum / 8) & -BDRV_SECTOR_SIZE;
uint8_t bitmap[BDRV_SECTOR_SIZE];
int ret;
int changed;
bool first = true;
int changed = 0, same = 0;

ret = bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap));
if (ret < 0) {
return ret;
}
do {
int ret;
uint8_t bitmap[BDRV_SECTOR_SIZE];

bitnum &= BITS_PER_BITMAP_SECTOR - 1;
int sector_bits = MIN(nb_sectors, BITS_PER_BITMAP_SECTOR - bitnum);

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);

bitnum &= BITS_PER_BITMAP_SECTOR - 1;
changed = cow_test_bit(bitnum, bitmap);
*num_same = cow_find_streak(bitmap, changed, bitnum, nb_sectors);
*num_same = same;
return changed;
}

Expand Down

0 comments on commit 091b110

Please sign in to comment.