summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--block/qcow2-bitmap.c31
-rwxr-xr-xtests/qemu-iotests/1652
2 files changed, 17 insertions, 16 deletions
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index 02512a21f2..f45e46cfbd 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -1072,10 +1072,9 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
 {
     int ret;
     BDRVQcow2State *s = bs->opaque;
-    int64_t sector;
-    uint64_t limit, sbc;
+    int64_t offset;
+    uint64_t limit;
     uint64_t bm_size = bdrv_dirty_bitmap_size(bitmap);
-    uint64_t bm_sectors = DIV_ROUND_UP(bm_size, BDRV_SECTOR_SIZE);
     const char *bm_name = bdrv_dirty_bitmap_name(bitmap);
     uint8_t *buf = NULL;
     BdrvDirtyBitmapIter *dbi;
@@ -1100,18 +1099,22 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
     dbi = bdrv_dirty_iter_new(bitmap);
     buf = g_malloc(s->cluster_size);
     limit = bytes_covered_by_bitmap_cluster(s, bitmap);
-    sbc = limit >> BDRV_SECTOR_BITS;
     assert(DIV_ROUND_UP(bm_size, limit) == tb_size);
 
-    while ((sector = bdrv_dirty_iter_next(dbi) >> BDRV_SECTOR_BITS) >= 0) {
-        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_sectors, sector + sbc);
-        write_size = bdrv_dirty_bitmap_serialization_size(bitmap,
-            sector * BDRV_SECTOR_SIZE, (end - sector) * BDRV_SECTOR_SIZE);
+        /*
+         * 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);
@@ -1123,9 +1126,7 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
         }
         tb[cluster] = off;
 
-        bdrv_dirty_bitmap_serialize_part(bitmap, buf,
-                                         sector * BDRV_SECTOR_SIZE,
-                                         (end - sector) * BDRV_SECTOR_SIZE);
+        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);
         }
@@ -1143,11 +1144,11 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
             goto fail;
         }
 
-        if (end >= bm_sectors) {
+        if (end >= bm_size) {
             break;
         }
 
-        bdrv_set_dirty_iter(dbi, end * BDRV_SECTOR_SIZE);
+        bdrv_set_dirty_iter(dbi, end);
     }
 
     *bitmap_table_size = tb_size;
diff --git a/tests/qemu-iotests/165 b/tests/qemu-iotests/165
index 74d7b79a0b..a3932db3de 100755
--- a/tests/qemu-iotests/165
+++ b/tests/qemu-iotests/165
@@ -27,7 +27,7 @@ disk = os.path.join(iotests.test_dir, 'disk')
 disk_size = 0x40000000 # 1G
 
 # regions for qemu_io: (start, count) in bytes
-regions1 = ((0,        0x100000),
+regions1 = ((0x0fff00, 0x10000),
             (0x200000, 0x100000))
 
 regions2 = ((0x10000000, 0x20000),