aboutsummaryrefslogtreecommitdiff
path: root/block/qcow2-bitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/qcow2-bitmap.c')
-rw-r--r--block/qcow2-bitmap.c62
1 files changed, 34 insertions, 28 deletions
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index 14f41d0..f45e46c 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -269,15 +269,16 @@ static int free_bitmap_clusters(BlockDriverState *bs, Qcow2BitmapTable *tb)
return 0;
}
-/* This function returns the number of disk sectors covered by a single qcow2
- * cluster of bitmap data. */
-static uint64_t sectors_covered_by_bitmap_cluster(const BDRVQcow2State *s,
- const BdrvDirtyBitmap *bitmap)
+/* Return the disk size covered by a single qcow2 cluster of bitmap data. */
+static uint64_t bytes_covered_by_bitmap_cluster(const BDRVQcow2State *s,
+ const BdrvDirtyBitmap *bitmap)
{
- uint32_t sector_granularity =
- bdrv_dirty_bitmap_granularity(bitmap) >> BDRV_SECTOR_BITS;
+ uint64_t granularity = bdrv_dirty_bitmap_granularity(bitmap);
+ uint64_t limit = granularity * (s->cluster_size << 3);
- return (uint64_t)sector_granularity * (s->cluster_size << 3);
+ assert(QEMU_IS_ALIGNED(limit,
+ bdrv_dirty_bitmap_serialization_align(bitmap)));
+ return limit;
}
/* load_bitmap_data
@@ -290,7 +291,7 @@ static int load_bitmap_data(BlockDriverState *bs,
{
int ret = 0;
BDRVQcow2State *s = bs->opaque;
- uint64_t sector, sbc;
+ uint64_t offset, limit;
uint64_t bm_size = bdrv_dirty_bitmap_size(bitmap);
uint8_t *buf = NULL;
uint64_t i, tab_size =
@@ -302,28 +303,28 @@ static int load_bitmap_data(BlockDriverState *bs,
}
buf = g_malloc(s->cluster_size);
- sbc = sectors_covered_by_bitmap_cluster(s, bitmap);
- for (i = 0, sector = 0; i < tab_size; ++i, sector += sbc) {
- uint64_t count = MIN(bm_size - sector, sbc);
+ limit = bytes_covered_by_bitmap_cluster(s, bitmap);
+ for (i = 0, offset = 0; i < tab_size; ++i, offset += limit) {
+ uint64_t count = MIN(bm_size - offset, limit);
uint64_t entry = bitmap_table[i];
- uint64_t offset = entry & BME_TABLE_ENTRY_OFFSET_MASK;
+ uint64_t data_offset = entry & BME_TABLE_ENTRY_OFFSET_MASK;
assert(check_table_entry(entry, s->cluster_size) == 0);
- if (offset == 0) {
+ if (data_offset == 0) {
if (entry & BME_TABLE_ENTRY_FLAG_ALL_ONES) {
- bdrv_dirty_bitmap_deserialize_ones(bitmap, sector, count,
+ bdrv_dirty_bitmap_deserialize_ones(bitmap, offset, count,
false);
} else {
/* No need to deserialize zeros because the dirty bitmap is
* already cleared */
}
} else {
- ret = bdrv_pread(bs->file, offset, buf, s->cluster_size);
+ ret = bdrv_pread(bs->file, data_offset, buf, s->cluster_size);
if (ret < 0) {
goto finish;
}
- bdrv_dirty_bitmap_deserialize_part(bitmap, buf, sector, count,
+ bdrv_dirty_bitmap_deserialize_part(bitmap, buf, offset, count,
false);
}
}
@@ -1071,8 +1072,8 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
{
int ret;
BDRVQcow2State *s = bs->opaque;
- int64_t sector;
- uint64_t sbc;
+ int64_t offset;
+ uint64_t limit;
uint64_t bm_size = bdrv_dirty_bitmap_size(bitmap);
const char *bm_name = bdrv_dirty_bitmap_name(bitmap);
uint8_t *buf = NULL;
@@ -1095,20 +1096,25 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
return NULL;
}
- dbi = bdrv_dirty_iter_new(bitmap, 0);
+ dbi = bdrv_dirty_iter_new(bitmap);
buf = g_malloc(s->cluster_size);
- sbc = sectors_covered_by_bitmap_cluster(s, bitmap);
- assert(DIV_ROUND_UP(bm_size, sbc) == tb_size);
+ limit = bytes_covered_by_bitmap_cluster(s, bitmap);
+ assert(DIV_ROUND_UP(bm_size, limit) == tb_size);
- while ((sector = bdrv_dirty_iter_next(dbi)) != -1) {
- uint64_t cluster = sector / sbc;
+ while ((offset = bdrv_dirty_iter_next(dbi)) >= 0) {
+ uint64_t cluster = offset / limit;
uint64_t end, write_size;
int64_t off;
- sector = cluster * sbc;
- end = MIN(bm_size, sector + sbc);
- write_size =
- bdrv_dirty_bitmap_serialization_size(bitmap, sector, end - sector);
+ /*
+ * We found the first dirty offset, but want to write out the
+ * entire cluster of the bitmap that includes that offset,
+ * including any leading zero bits.
+ */
+ offset = QEMU_ALIGN_DOWN(offset, limit);
+ end = MIN(bm_size, offset + limit);
+ write_size = bdrv_dirty_bitmap_serialization_size(bitmap, offset,
+ end - offset);
assert(write_size <= s->cluster_size);
off = qcow2_alloc_clusters(bs, s->cluster_size);
@@ -1120,7 +1126,7 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
}
tb[cluster] = off;
- bdrv_dirty_bitmap_serialize_part(bitmap, buf, sector, end - sector);
+ bdrv_dirty_bitmap_serialize_part(bitmap, buf, offset, end - offset);
if (write_size < s->cluster_size) {
memset(buf + write_size, 0, s->cluster_size - write_size);
}