All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v4 00/17] make dirty-bitmap byte-based
@ 2017-07-03 15:10 Eric Blake
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 01/17] dirty-bitmap: Report BlockDirtyInfo.count in bytes, as documented Eric Blake
                   ` (16 more replies)
  0 siblings, 17 replies; 38+ messages in thread
From: Eric Blake @ 2017-07-03 15:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, kwolf, jsnow

There are patches floating around to add NBD_CMD_BLOCK_STATUS,
but NBD wants to report status on byte granularity (even if the
reporting will probably be naturally aligned to sectors or even
much higher levels).  I've therefore started the task of
converting our block status code to report at a byte granularity
rather than sectors.

This is part two of that conversion: dirty-bitmap. Other parts
include bdrv_is_allocated (at v3 [1]) and replacing
bdrv_get_block_status with a byte based callback in all the
drivers (at v1, needs a rebase [3]).

Available as a tag at:
git fetch git://repo.or.cz/qemu/ericb.git nbd-byte-dirty-v4

Depends on Max's block branch and my v3 bdrv_is_allocated [1]

v4 is a major rebase: now that persistent dirty bitmaps have
landed, I had more client code to convert. As part of the
rebase, I also discovered that v3 did not correctly convert
the functions used for serializing a dirty bitmap (which
really didn't matter until qcow2-bitmap.c landed, anyways).
So the intra-version diffstat is huge, and a lot of patches
need re-review.

[1] https://lists.gnu.org/archive/html/qemu-devel/2017-06/msg06077.html
[2] https://lists.gnu.org/archive/html/qemu-devel/2017-05/msg03859.html
[3] https://lists.gnu.org/archive/html/qemu-devel/2017-04/msg02642.html

(git backport-diff doesn't like the rename in 5/17)

001/17:[----] [--] 'dirty-bitmap: Report BlockDirtyInfo.count in bytes, as documented'
002/17:[down] 'hbitmap: Rename serialization_granularity to serialization_align'
003/17:[down] 'qcow2: Ensure bitmap serialization is aligned'
004/17:[0006] [FC] 'dirty-bitmap: Drop unused functions'
005/17:[down] 'dirty-bitmap: Change bdrv_dirty_bitmap_size() to report bytes'
006/17:[down] 'dirty-bitmap: Change bdrv_dirty_bitmap_*serialize*() to take bytes'
007/17:[down] 'qcow2: Switch sectors_covered_by_bitmap_cluster() to byte-based'
008/17:[0004] [FC] 'dirty-bitmap: Set iterator start by offset, not sector'
009/17:[0002] [FC] 'dirty-bitmap: Change bdrv_dirty_iter_next() to report byte offset'
010/17:[----] [--] 'dirty-bitmap: Change bdrv_get_dirty_count() to report bytes'
011/17:[----] [-C] 'dirty-bitmap: Change bdrv_get_dirty_locked() to take bytes'
012/17:[----] [-C] 'dirty-bitmap: Change bdrv_[re]set_dirty_bitmap() to use bytes'
013/17:[----] [--] 'mirror: Switch mirror_dirty_init() to byte-based iteration'
014/17:[down] 'qcow2: Switch load_bitmap_data() to byte-based iteration'
015/17:[down] 'qcow2: Switch store_bitmap_data() to byte-based iteration'
016/17:[----] [-C] 'dirty-bitmap: Switch bdrv_set_dirty() to bytes'
017/17:[0031] [FC] 'dirty-bitmap: Convert internal hbitmap size/granularity'

Eric Blake (17):
  dirty-bitmap: Report BlockDirtyInfo.count in bytes, as documented
  hbitmap: Rename serialization_granularity to serialization_align
  qcow2: Ensure bitmap serialization is aligned
  dirty-bitmap: Drop unused functions
  dirty-bitmap: Change bdrv_dirty_bitmap_size() to report bytes
  dirty-bitmap: Change bdrv_dirty_bitmap_*serialize*() to take bytes
  qcow2: Switch sectors_covered_by_bitmap_cluster() to byte-based
  dirty-bitmap: Set iterator start by offset, not sector
  dirty-bitmap: Change bdrv_dirty_iter_next() to report byte offset
  dirty-bitmap: Change bdrv_get_dirty_count() to report bytes
  dirty-bitmap: Change bdrv_get_dirty_locked() to take bytes
  dirty-bitmap: Change bdrv_[re]set_dirty_bitmap() to use bytes
  mirror: Switch mirror_dirty_init() to byte-based iteration
  qcow2: Switch load_bitmap_data() to byte-based iteration
  qcow2: Switch store_bitmap_data() to byte-based iteration
  dirty-bitmap: Switch bdrv_set_dirty() to bytes
  dirty-bitmap: Convert internal hbitmap size/granularity

 include/block/block_int.h    |   2 +-
 include/block/dirty-bitmap.h |  41 +++++---------
 include/qemu/hbitmap.h       |   8 +--
 block/backup.c               |   7 +--
 block/dirty-bitmap.c         | 128 ++++++++++++++-----------------------------
 block/io.c                   |   6 +-
 block/mirror.c               |  73 +++++++++++-------------
 block/qcow2-bitmap.c         |  57 +++++++++----------
 migration/block.c            |  12 ++--
 tests/test-hbitmap.c         |  10 ++--
 util/hbitmap.c               |   8 +--
 11 files changed, 142 insertions(+), 210 deletions(-)

-- 
2.9.4

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 01/17] dirty-bitmap: Report BlockDirtyInfo.count in bytes, as documented
  2017-07-03 15:10 [Qemu-devel] [PATCH v4 00/17] make dirty-bitmap byte-based Eric Blake
@ 2017-07-03 15:10 ` Eric Blake
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 02/17] hbitmap: Rename serialization_granularity to serialization_align Eric Blake
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 38+ messages in thread
From: Eric Blake @ 2017-07-03 15:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, kwolf, jsnow, qemu-stable, Fam Zheng, Max Reitz

We've been documenting the value in bytes since its introduction
in commit b9a9b3a4 (v1.3), where it was actually reported in bytes.

Commit e4654d2 (v2.0) then removed things from block/qapi.c, in
preparation for a rewrite to a list of dirty sectors in the next
commit 21b5683 in block.c, but the new code mistakenly started
reporting in sectors.

Fixes: https://bugzilla.redhat.com/1441460

CC: qemu-stable@nongnu.org
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>

---
Too late for 2.9, since the regression has been unnoticed for
nine releases. But worth putting in 2.9.1.

v2-v4: no change
---
 block/dirty-bitmap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index 543bddb..30462d4 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -461,7 +461,7 @@ BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs)
     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
         BlockDirtyInfo *info = g_new0(BlockDirtyInfo, 1);
         BlockDirtyInfoList *entry = g_new0(BlockDirtyInfoList, 1);
-        info->count = bdrv_get_dirty_count(bm);
+        info->count = bdrv_get_dirty_count(bm) << BDRV_SECTOR_BITS;
         info->granularity = bdrv_dirty_bitmap_granularity(bm);
         info->has_name = !!bm->name;
         info->name = g_strdup(bm->name);
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 02/17] hbitmap: Rename serialization_granularity to serialization_align
  2017-07-03 15:10 [Qemu-devel] [PATCH v4 00/17] make dirty-bitmap byte-based Eric Blake
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 01/17] dirty-bitmap: Report BlockDirtyInfo.count in bytes, as documented Eric Blake
@ 2017-07-03 15:10 ` Eric Blake
  2017-07-06 23:03   ` John Snow
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 03/17] qcow2: Ensure bitmap serialization is aligned Eric Blake
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: Eric Blake @ 2017-07-03 15:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, kwolf, jsnow, Fam Zheng, Max Reitz

The only client of hbitmap_serialization_granularity() is dirty-bitmap's
bdrv_dirty_bitmap_serialization_align().  Keeping the two names consistent
is worthwhile, and the shorter name is more representative of what the
function returns (the required alignment to be used for start/count of
other serialization functions, where violating the alignment causes
assertion failures).

Signed-off-by: Eric Blake <eblake@redhat.com>

---
v4: new patch
---
 include/qemu/hbitmap.h |  8 ++++----
 block/dirty-bitmap.c   |  2 +-
 tests/test-hbitmap.c   | 10 +++++-----
 util/hbitmap.c         |  8 ++++----
 4 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/include/qemu/hbitmap.h b/include/qemu/hbitmap.h
index d3a74a2..81e7804 100644
--- a/include/qemu/hbitmap.h
+++ b/include/qemu/hbitmap.h
@@ -159,16 +159,16 @@ bool hbitmap_get(const HBitmap *hb, uint64_t item);
 bool hbitmap_is_serializable(const HBitmap *hb);

 /**
- * hbitmap_serialization_granularity:
+ * hbitmap_serialization_align:
  * @hb: HBitmap to operate on.
  *
- * Granularity of serialization chunks, used by other serialization functions.
- * For every chunk:
+ * Required alignment of serialization chunks, used by other serialization
+ * functions. For every chunk:
  * 1. Chunk start should be aligned to this granularity.
  * 2. Chunk size should be aligned too, except for last chunk (for which
  *      start + count == hb->size)
  */
-uint64_t hbitmap_serialization_granularity(const HBitmap *hb);
+uint64_t hbitmap_serialization_align(const HBitmap *hb);

 /**
  * hbitmap_serialization_size:
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index 30462d4..0490ca3 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -617,7 +617,7 @@ uint64_t bdrv_dirty_bitmap_serialization_size(const BdrvDirtyBitmap *bitmap,

 uint64_t bdrv_dirty_bitmap_serialization_align(const BdrvDirtyBitmap *bitmap)
 {
-    return hbitmap_serialization_granularity(bitmap->bitmap);
+    return hbitmap_serialization_align(bitmap->bitmap);
 }

 void bdrv_dirty_bitmap_serialize_part(const BdrvDirtyBitmap *bitmap,
diff --git a/tests/test-hbitmap.c b/tests/test-hbitmap.c
index 1acb353..af41642 100644
--- a/tests/test-hbitmap.c
+++ b/tests/test-hbitmap.c
@@ -738,15 +738,15 @@ static void test_hbitmap_meta_one(TestHBitmapData *data, const void *unused)
     }
 }

-static void test_hbitmap_serialize_granularity(TestHBitmapData *data,
-                                               const void *unused)
+static void test_hbitmap_serialize_align(TestHBitmapData *data,
+                                         const void *unused)
 {
     int r;

     hbitmap_test_init(data, L3 * 2, 3);
     g_assert(hbitmap_is_serializable(data->hb));

-    r = hbitmap_serialization_granularity(data->hb);
+    r = hbitmap_serialization_align(data->hb);
     g_assert_cmpint(r, ==, 64 << 3);
 }

@@ -974,8 +974,8 @@ int main(int argc, char **argv)
     hbitmap_test_add("/hbitmap/meta/word", test_hbitmap_meta_word);
     hbitmap_test_add("/hbitmap/meta/sector", test_hbitmap_meta_sector);

-    hbitmap_test_add("/hbitmap/serialize/granularity",
-                     test_hbitmap_serialize_granularity);
+    hbitmap_test_add("/hbitmap/serialize/align",
+                     test_hbitmap_serialize_align);
     hbitmap_test_add("/hbitmap/serialize/basic",
                      test_hbitmap_serialize_basic);
     hbitmap_test_add("/hbitmap/serialize/part",
diff --git a/util/hbitmap.c b/util/hbitmap.c
index 21535cc..2f9d0fd 100644
--- a/util/hbitmap.c
+++ b/util/hbitmap.c
@@ -413,14 +413,14 @@ bool hbitmap_is_serializable(const HBitmap *hb)
 {
     /* Every serialized chunk must be aligned to 64 bits so that endianness
      * requirements can be fulfilled on both 64 bit and 32 bit hosts.
-     * We have hbitmap_serialization_granularity() which converts this
+     * We have hbitmap_serialization_align() which converts this
      * alignment requirement from bitmap bits to items covered (e.g. sectors).
      * That value is:
      *    64 << hb->granularity
      * Since this value must not exceed UINT64_MAX, hb->granularity must be
      * less than 58 (== 64 - 6, where 6 is ld(64), i.e. 1 << 6 == 64).
      *
-     * In order for hbitmap_serialization_granularity() to always return a
+     * In order for hbitmap_serialization_align() to always return a
      * meaningful value, bitmaps that are to be serialized must have a
      * granularity of less than 58. */

@@ -437,7 +437,7 @@ bool hbitmap_get(const HBitmap *hb, uint64_t item)
     return (hb->levels[HBITMAP_LEVELS - 1][pos >> BITS_PER_LEVEL] & bit) != 0;
 }

-uint64_t hbitmap_serialization_granularity(const HBitmap *hb)
+uint64_t hbitmap_serialization_align(const HBitmap *hb)
 {
     assert(hbitmap_is_serializable(hb));

@@ -454,7 +454,7 @@ static void serialization_chunk(const HBitmap *hb,
                                 unsigned long **first_el, uint64_t *el_count)
 {
     uint64_t last = start + count - 1;
-    uint64_t gran = hbitmap_serialization_granularity(hb);
+    uint64_t gran = hbitmap_serialization_align(hb);

     assert((start & (gran - 1)) == 0);
     assert((last >> hb->granularity) < hb->size);
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 03/17] qcow2: Ensure bitmap serialization is aligned
  2017-07-03 15:10 [Qemu-devel] [PATCH v4 00/17] make dirty-bitmap byte-based Eric Blake
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 01/17] dirty-bitmap: Report BlockDirtyInfo.count in bytes, as documented Eric Blake
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 02/17] hbitmap: Rename serialization_granularity to serialization_align Eric Blake
@ 2017-07-03 15:10 ` Eric Blake
  2017-07-06 23:14   ` John Snow
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 04/17] dirty-bitmap: Drop unused functions Eric Blake
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: Eric Blake @ 2017-07-03 15:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, kwolf, jsnow, Max Reitz

When subdividing a bitmap serialization, the code in hbitmap.c
enforces that start/count parameters are aligned (except that
count can end early at end-of-bitmap).  We exposed this required
alignment through bdrv_dirty_bitmap_serialization_align(), but
forgot to actually check that we comply with it.

Fortunately, qcow2 is never dividing bitmap serialization smaller
than one cluster (which is a minimum of 512 bytes); so we are
always compliant with the serialization alignment (which insists
that we partition at least 64 bits per chunk) because we are doing
at least 4k bits per chunk.

Still, it's safer to add an assertion (for the unlikely case that
we'd ever support a cluster smaller than 512 bytes, or if the
hbitmap implementation changes what it considers to be aligned),
rather than leaving bdrv_dirty_bitmap_serialization_align()
without a caller.

Signed-off-by: Eric Blake <eblake@redhat.com>

---
v4: new patch
---
 block/qcow2-bitmap.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index 8448bec..75ee238 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -274,10 +274,13 @@ static int free_bitmap_clusters(BlockDriverState *bs, Qcow2BitmapTable *tb)
 static uint64_t sectors_covered_by_bitmap_cluster(const BDRVQcow2State *s,
                                                   const BdrvDirtyBitmap *bitmap)
 {
-    uint32_t sector_granularity =
+    uint64_t sector_granularity =
             bdrv_dirty_bitmap_granularity(bitmap) >> BDRV_SECTOR_BITS;
+    uint64_t sbc = sector_granularity * (s->cluster_size << 3);

-    return (uint64_t)sector_granularity * (s->cluster_size << 3);
+    assert(QEMU_IS_ALIGNED(sbc,
+                           bdrv_dirty_bitmap_serialization_align(bitmap)));
+    return sbc;
 }

 /* load_bitmap_data
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 04/17] dirty-bitmap: Drop unused functions
  2017-07-03 15:10 [Qemu-devel] [PATCH v4 00/17] make dirty-bitmap byte-based Eric Blake
                   ` (2 preceding siblings ...)
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 03/17] qcow2: Ensure bitmap serialization is aligned Eric Blake
@ 2017-07-03 15:10 ` Eric Blake
  2017-07-06 23:43   ` John Snow
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 05/17] dirty-bitmap: Change bdrv_dirty_bitmap_size() to report bytes Eric Blake
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: Eric Blake @ 2017-07-03 15:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, kwolf, jsnow, Fam Zheng, Max Reitz

We had several functions that no one is currently using, and which
use sector-based interfaces.  I'm trying to convert towards byte-based
interfaces, so it's easier to just drop the unused functions:

bdrv_dirty_bitmap_get_meta
bdrv_dirty_bitmap_get_meta_locked
bdrv_dirty_bitmap_reset_meta
bdrv_dirty_bitmap_meta_granularity

Signed-off-by: Eric Blake <eblake@redhat.com>

---
v4: rebase to Vladimir's persistent bitmaps (bdrv_dirty_bitmap_size now
in use), dropped R-b
v3: rebase to upstream changes (bdrv_dirty_bitmap_get_meta_locked was
added in b64bd51e with no clients), kept R-b
v2: tweak commit message based on review, no code change
---
 include/block/dirty-bitmap.h | 10 ----------
 block/dirty-bitmap.c         | 44 --------------------------------------------
 2 files changed, 54 deletions(-)

diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
index a79a58d..8fd842e 100644
--- a/include/block/dirty-bitmap.h
+++ b/include/block/dirty-bitmap.h
@@ -34,7 +34,6 @@ void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap);
 BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs);
 uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs);
 uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap);
-uint32_t bdrv_dirty_bitmap_meta_granularity(BdrvDirtyBitmap *bitmap);
 bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap);
 bool bdrv_dirty_bitmap_frozen(BdrvDirtyBitmap *bitmap);
 const char *bdrv_dirty_bitmap_name(const BdrvDirtyBitmap *bitmap);
@@ -44,15 +43,6 @@ void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap,
                            int64_t cur_sector, int64_t nr_sectors);
 void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap,
                              int64_t cur_sector, int64_t nr_sectors);
-int bdrv_dirty_bitmap_get_meta(BlockDriverState *bs,
-                               BdrvDirtyBitmap *bitmap, int64_t sector,
-                               int nb_sectors);
-int bdrv_dirty_bitmap_get_meta_locked(BlockDriverState *bs,
-                                      BdrvDirtyBitmap *bitmap, int64_t sector,
-                                      int nb_sectors);
-void bdrv_dirty_bitmap_reset_meta(BlockDriverState *bs,
-                                  BdrvDirtyBitmap *bitmap, int64_t sector,
-                                  int nb_sectors);
 BdrvDirtyBitmapIter *bdrv_dirty_meta_iter_new(BdrvDirtyBitmap *bitmap);
 BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap,
                                          uint64_t first_sector);
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index 0490ca3..42a55e4 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -173,45 +173,6 @@ void bdrv_release_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap)
     qemu_mutex_unlock(bitmap->mutex);
 }

-int bdrv_dirty_bitmap_get_meta_locked(BlockDriverState *bs,
-                                      BdrvDirtyBitmap *bitmap, int64_t sector,
-                                      int nb_sectors)
-{
-    uint64_t i;
-    int sectors_per_bit = 1 << hbitmap_granularity(bitmap->meta);
-
-    /* To optimize: we can make hbitmap to internally check the range in a
-     * coarse level, or at least do it word by word. */
-    for (i = sector; i < sector + nb_sectors; i += sectors_per_bit) {
-        if (hbitmap_get(bitmap->meta, i)) {
-            return true;
-        }
-    }
-    return false;
-}
-
-int bdrv_dirty_bitmap_get_meta(BlockDriverState *bs,
-                               BdrvDirtyBitmap *bitmap, int64_t sector,
-                               int nb_sectors)
-{
-    bool dirty;
-
-    qemu_mutex_lock(bitmap->mutex);
-    dirty = bdrv_dirty_bitmap_get_meta_locked(bs, bitmap, sector, nb_sectors);
-    qemu_mutex_unlock(bitmap->mutex);
-
-    return dirty;
-}
-
-void bdrv_dirty_bitmap_reset_meta(BlockDriverState *bs,
-                                  BdrvDirtyBitmap *bitmap, int64_t sector,
-                                  int nb_sectors)
-{
-    qemu_mutex_lock(bitmap->mutex);
-    hbitmap_reset(bitmap->meta, sector, nb_sectors);
-    qemu_mutex_unlock(bitmap->mutex);
-}
-
 int64_t bdrv_dirty_bitmap_size(const BdrvDirtyBitmap *bitmap)
 {
     return bitmap->size;
@@ -511,11 +472,6 @@ uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap)
     return BDRV_SECTOR_SIZE << hbitmap_granularity(bitmap->bitmap);
 }

-uint32_t bdrv_dirty_bitmap_meta_granularity(BdrvDirtyBitmap *bitmap)
-{
-    return BDRV_SECTOR_SIZE << hbitmap_granularity(bitmap->meta);
-}
-
 BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap,
                                          uint64_t first_sector)
 {
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 05/17] dirty-bitmap: Change bdrv_dirty_bitmap_size() to report bytes
  2017-07-03 15:10 [Qemu-devel] [PATCH v4 00/17] make dirty-bitmap byte-based Eric Blake
                   ` (3 preceding siblings ...)
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 04/17] dirty-bitmap: Drop unused functions Eric Blake
@ 2017-07-03 15:10 ` Eric Blake
  2017-07-10 21:09   ` John Snow
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 06/17] dirty-bitmap: Change bdrv_dirty_bitmap_*serialize*() to take bytes Eric Blake
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: Eric Blake @ 2017-07-03 15:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, kwolf, jsnow, Fam Zheng, Max Reitz

We are still using an internal hbitmap that tracks a size in sectors,
with the granularity scaled down accordingly, because it lets us
use a shortcut for our iterators which are currently sector-based.
But there's no reason we can't track the dirty bitmap size in bytes,
since it is (mostly) an internal-only variable (remember, the size
is how many bytes are covered by the bitmap, not how many bytes the
bitmap occupies).  Furthermore, we're already reporting bytes for
bdrv_dirty_bitmap_granularity(); mixing bytes and sectors in our
return values is a recipe for confusion.

The only external caller in qcow2-bitmap.c is temporarily more verbose
(because it is still using sector-based math), but will later be
switched to track progress by bytes instead of sectors.

Use is_power_of_2() while at it, instead of open-coding that.

Signed-off-by: Eric Blake <eblake@redhat.com>

---
v4: retitle from "Track size in bytes", rebase to persistent bitmaps,
round up when converting bytes to sectors
v3: no change
v2: tweak commit message, no code change
---
 block/dirty-bitmap.c | 25 +++++++++++++++----------
 block/qcow2-bitmap.c | 14 ++++++++------
 2 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index 42a55e4..3d8cfe6 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -1,7 +1,7 @@
 /*
  * Block Dirty Bitmap
  *
- * Copyright (c) 2016 Red Hat. Inc
+ * Copyright (c) 2016-2017 Red Hat. Inc
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -42,7 +42,7 @@ struct BdrvDirtyBitmap {
     HBitmap *meta;              /* Meta dirty bitmap */
     BdrvDirtyBitmap *successor; /* Anonymous child; implies frozen status */
     char *name;                 /* Optional non-empty unique ID */
-    int64_t size;               /* Size of the bitmap (Number of sectors) */
+    int64_t size;               /* Size of the bitmap, in bytes */
     bool disabled;              /* Bitmap is disabled. It ignores all writes to
                                    the device */
     int active_iterators;       /* How many iterators are active */
@@ -115,17 +115,14 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
 {
     int64_t bitmap_size;
     BdrvDirtyBitmap *bitmap;
-    uint32_t sector_granularity;

-    assert((granularity & (granularity - 1)) == 0);
+    assert(is_power_of_2(granularity) && granularity >= BDRV_SECTOR_SIZE);

     if (name && bdrv_find_dirty_bitmap(bs, name)) {
         error_setg(errp, "Bitmap already exists: %s", name);
         return NULL;
     }
-    sector_granularity = granularity >> BDRV_SECTOR_BITS;
-    assert(sector_granularity);
-    bitmap_size = bdrv_nb_sectors(bs);
+    bitmap_size = bdrv_getlength(bs);
     if (bitmap_size < 0) {
         error_setg_errno(errp, -bitmap_size, "could not get length of device");
         errno = -bitmap_size;
@@ -133,7 +130,12 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
     }
     bitmap = g_new0(BdrvDirtyBitmap, 1);
     bitmap->mutex = &bs->dirty_bitmap_mutex;
-    bitmap->bitmap = hbitmap_alloc(bitmap_size, ctz32(sector_granularity));
+    /*
+     * TODO - let hbitmap track full granularity. For now, it is tracking
+     * only sector granularity, as a shortcut for our iterators.
+     */
+    bitmap->bitmap = hbitmap_alloc(DIV_ROUND_UP(bitmap_size, BDRV_SECTOR_SIZE),
+                                   ctz32(granularity) - BDRV_SECTOR_BITS);
     bitmap->size = bitmap_size;
     bitmap->name = g_strdup(name);
     bitmap->disabled = false;
@@ -305,8 +307,10 @@ BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs,
 void bdrv_dirty_bitmap_truncate(BlockDriverState *bs)
 {
     BdrvDirtyBitmap *bitmap;
-    uint64_t size = bdrv_nb_sectors(bs);
+    int64_t size = bdrv_getlength(bs);

+    assert(size >= 0);
+    size = DIV_ROUND_UP(size, BDRV_SECTOR_SIZE);
     bdrv_dirty_bitmaps_lock(bs);
     QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
         assert(!bdrv_dirty_bitmap_frozen(bitmap));
@@ -549,7 +553,8 @@ void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out)
         hbitmap_reset_all(bitmap->bitmap);
     } else {
         HBitmap *backup = bitmap->bitmap;
-        bitmap->bitmap = hbitmap_alloc(bitmap->size,
+        bitmap->bitmap = hbitmap_alloc(DIV_ROUND_UP(bitmap->size,
+                                                    BDRV_SECTOR_SIZE),
                                        hbitmap_granularity(backup));
         *out = backup;
     }
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index 75ee238..f6f7770 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -295,10 +295,11 @@ static int load_bitmap_data(BlockDriverState *bs,
     BDRVQcow2State *s = bs->opaque;
     uint64_t sector, sbc;
     uint64_t bm_size = bdrv_dirty_bitmap_size(bitmap);
+    uint64_t bm_sectors = DIV_ROUND_UP(bm_size, BDRV_SECTOR_SIZE);
     uint8_t *buf = NULL;
     uint64_t i, tab_size =
             size_to_clusters(s,
-                bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_size));
+                bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_sectors));

     if (tab_size != bitmap_table_size || tab_size > BME_MAX_TABLE_SIZE) {
         return -EINVAL;
@@ -307,7 +308,7 @@ 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);
+        uint64_t count = MIN(bm_sectors - sector, sbc);
         uint64_t entry = bitmap_table[i];
         uint64_t offset = entry & BME_TABLE_ENTRY_OFFSET_MASK;

@@ -1073,13 +1074,14 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
     int64_t sector;
     uint64_t sbc;
     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;
     uint64_t *tb;
     uint64_t tb_size =
             size_to_clusters(s,
-                bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_size));
+                bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_sectors));

     if (tb_size > BME_MAX_TABLE_SIZE ||
         tb_size * s->cluster_size > BME_MAX_PHYS_SIZE)
@@ -1097,7 +1099,7 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
     dbi = bdrv_dirty_iter_new(bitmap, 0);
     buf = g_malloc(s->cluster_size);
     sbc = sectors_covered_by_bitmap_cluster(s, bitmap);
-    assert(DIV_ROUND_UP(bm_size, sbc) == tb_size);
+    assert(DIV_ROUND_UP(bm_sectors, sbc) == tb_size);

     while ((sector = bdrv_dirty_iter_next(dbi)) != -1) {
         uint64_t cluster = sector / sbc;
@@ -1105,7 +1107,7 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
         int64_t off;

         sector = cluster * sbc;
-        end = MIN(bm_size, sector + sbc);
+        end = MIN(bm_sectors, sector + sbc);
         write_size =
             bdrv_dirty_bitmap_serialization_size(bitmap, sector, end - sector);
         assert(write_size <= s->cluster_size);
@@ -1137,7 +1139,7 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
             goto fail;
         }

-        if (end >= bm_size) {
+        if (end >= bm_sectors) {
             break;
         }

-- 
2.9.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 06/17] dirty-bitmap: Change bdrv_dirty_bitmap_*serialize*() to take bytes
  2017-07-03 15:10 [Qemu-devel] [PATCH v4 00/17] make dirty-bitmap byte-based Eric Blake
                   ` (4 preceding siblings ...)
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 05/17] dirty-bitmap: Change bdrv_dirty_bitmap_size() to report bytes Eric Blake
@ 2017-07-03 15:10 ` Eric Blake
  2017-07-10 21:46   ` John Snow
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 07/17] qcow2: Switch sectors_covered_by_bitmap_cluster() to byte-based Eric Blake
                   ` (10 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: Eric Blake @ 2017-07-03 15:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, kwolf, jsnow, Fam Zheng, Max Reitz

Right now, the dirty-bitmap code exposes the fact that we use
a scale of sector granularity in the underlying hbitmap to anything
that wants to serialize a dirty bitmap.  It's nicer to uniformly
expose bytes as our dirty-bitmap interface, matching the previous
change to bitmap size.  The only caller to serialization is currently
qcow2-cluster.c, which becomes a bit more verbose because it is still
tracking sectors for other reasons, but a later patch will fix that
to more uniformly use byte offsets everywhere.  Likewise, within
dirty-bitmap, we have to add more assertions that we are not
truncating incorrectly, which can go away once the internal hbitmap
is byte-based rather than sector-based.

Signed-off-by: Eric Blake <eblake@redhat.com>

---
v4: new patch
---
 include/block/dirty-bitmap.h | 14 +++++++-------
 block/dirty-bitmap.c         | 37 ++++++++++++++++++++++++-------------
 block/qcow2-bitmap.c         | 22 ++++++++++++++--------
 3 files changed, 45 insertions(+), 28 deletions(-)

diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
index 8fd842e..f4ccd3f 100644
--- a/include/block/dirty-bitmap.h
+++ b/include/block/dirty-bitmap.h
@@ -49,19 +49,19 @@ BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap,
 void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter);

 uint64_t bdrv_dirty_bitmap_serialization_size(const BdrvDirtyBitmap *bitmap,
-                                              uint64_t start, uint64_t count);
+                                              uint64_t offset, uint64_t bytes);
 uint64_t bdrv_dirty_bitmap_serialization_align(const BdrvDirtyBitmap *bitmap);
 void bdrv_dirty_bitmap_serialize_part(const BdrvDirtyBitmap *bitmap,
-                                      uint8_t *buf, uint64_t start,
-                                      uint64_t count);
+                                      uint8_t *buf, uint64_t offset,
+                                      uint64_t bytes);
 void bdrv_dirty_bitmap_deserialize_part(BdrvDirtyBitmap *bitmap,
-                                        uint8_t *buf, uint64_t start,
-                                        uint64_t count, bool finish);
+                                        uint8_t *buf, uint64_t offset,
+                                        uint64_t bytes, bool finish);
 void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap *bitmap,
-                                          uint64_t start, uint64_t count,
+                                          uint64_t offset, uint64_t bytes,
                                           bool finish);
 void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap,
-                                        uint64_t start, uint64_t count,
+                                        uint64_t offset, uint64_t bytes,
                                         bool finish);
 void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap);

diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index 3d8cfe6..dc5c205 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -571,42 +571,53 @@ void bdrv_undo_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *in)
 }

 uint64_t bdrv_dirty_bitmap_serialization_size(const BdrvDirtyBitmap *bitmap,
-                                              uint64_t start, uint64_t count)
+                                              uint64_t offset, uint64_t bytes)
 {
-    return hbitmap_serialization_size(bitmap->bitmap, start, count);
+    assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
+    return hbitmap_serialization_size(bitmap->bitmap,
+                                      offset >> BDRV_SECTOR_BITS,
+                                      bytes >> BDRV_SECTOR_BITS);
 }

 uint64_t bdrv_dirty_bitmap_serialization_align(const BdrvDirtyBitmap *bitmap)
 {
-    return hbitmap_serialization_align(bitmap->bitmap);
+    return hbitmap_serialization_align(bitmap->bitmap) * BDRV_SECTOR_SIZE;
 }

 void bdrv_dirty_bitmap_serialize_part(const BdrvDirtyBitmap *bitmap,
-                                      uint8_t *buf, uint64_t start,
-                                      uint64_t count)
+                                      uint8_t *buf, uint64_t offset,
+                                      uint64_t bytes)
 {
-    hbitmap_serialize_part(bitmap->bitmap, buf, start, count);
+    assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
+    hbitmap_serialize_part(bitmap->bitmap, buf, offset >> BDRV_SECTOR_BITS,
+                           bytes >> BDRV_SECTOR_BITS);
 }

 void bdrv_dirty_bitmap_deserialize_part(BdrvDirtyBitmap *bitmap,
-                                        uint8_t *buf, uint64_t start,
-                                        uint64_t count, bool finish)
+                                        uint8_t *buf, uint64_t offset,
+                                        uint64_t bytes, bool finish)
 {
-    hbitmap_deserialize_part(bitmap->bitmap, buf, start, count, finish);
+    assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
+    hbitmap_deserialize_part(bitmap->bitmap, buf, offset >> BDRV_SECTOR_BITS,
+                             bytes >> BDRV_SECTOR_BITS, finish);
 }

 void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap *bitmap,
-                                          uint64_t start, uint64_t count,
+                                          uint64_t offset, uint64_t bytes,
                                           bool finish)
 {
-    hbitmap_deserialize_zeroes(bitmap->bitmap, start, count, finish);
+    assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
+    hbitmap_deserialize_zeroes(bitmap->bitmap, offset >> BDRV_SECTOR_BITS,
+                               bytes >> BDRV_SECTOR_BITS, finish);
 }

 void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap,
-                                        uint64_t start, uint64_t count,
+                                        uint64_t offset, uint64_t bytes,
                                         bool finish)
 {
-    hbitmap_deserialize_ones(bitmap->bitmap, start, count, finish);
+    assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
+    hbitmap_deserialize_ones(bitmap->bitmap, offset >> BDRV_SECTOR_BITS,
+                             bytes >> BDRV_SECTOR_BITS, finish);
 }

 void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap)
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index f6f7770..8fd2598 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -278,7 +278,7 @@ static uint64_t sectors_covered_by_bitmap_cluster(const BDRVQcow2State *s,
             bdrv_dirty_bitmap_granularity(bitmap) >> BDRV_SECTOR_BITS;
     uint64_t sbc = sector_granularity * (s->cluster_size << 3);

-    assert(QEMU_IS_ALIGNED(sbc,
+    assert(QEMU_IS_ALIGNED(sbc << BDRV_SECTOR_BITS,
                            bdrv_dirty_bitmap_serialization_align(bitmap)));
     return sbc;
 }
@@ -299,7 +299,7 @@ static int load_bitmap_data(BlockDriverState *bs,
     uint8_t *buf = NULL;
     uint64_t i, tab_size =
             size_to_clusters(s,
-                bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_sectors));
+                bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_size));

     if (tab_size != bitmap_table_size || tab_size > BME_MAX_TABLE_SIZE) {
         return -EINVAL;
@@ -316,7 +316,9 @@ static int load_bitmap_data(BlockDriverState *bs,

         if (offset == 0) {
             if (entry & BME_TABLE_ENTRY_FLAG_ALL_ONES) {
-                bdrv_dirty_bitmap_deserialize_ones(bitmap, sector, count,
+                bdrv_dirty_bitmap_deserialize_ones(bitmap,
+                                                   sector * BDRV_SECTOR_SIZE,
+                                                   count * BDRV_SECTOR_SIZE,
                                                    false);
             } else {
                 /* No need to deserialize zeros because the dirty bitmap is
@@ -327,7 +329,9 @@ static int load_bitmap_data(BlockDriverState *bs,
             if (ret < 0) {
                 goto finish;
             }
-            bdrv_dirty_bitmap_deserialize_part(bitmap, buf, sector, count,
+            bdrv_dirty_bitmap_deserialize_part(bitmap, buf,
+                                               sector * BDRV_SECTOR_SIZE,
+                                               count * BDRV_SECTOR_SIZE,
                                                false);
         }
     }
@@ -1081,7 +1085,7 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
     uint64_t *tb;
     uint64_t tb_size =
             size_to_clusters(s,
-                bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_sectors));
+                bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_size));

     if (tb_size > BME_MAX_TABLE_SIZE ||
         tb_size * s->cluster_size > BME_MAX_PHYS_SIZE)
@@ -1108,8 +1112,8 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,

         sector = cluster * sbc;
         end = MIN(bm_sectors, sector + sbc);
-        write_size =
-            bdrv_dirty_bitmap_serialization_size(bitmap, sector, end - sector);
+        write_size = bdrv_dirty_bitmap_serialization_size(bitmap,
+            sector * BDRV_SECTOR_SIZE, (end - sector) * BDRV_SECTOR_SIZE);
         assert(write_size <= s->cluster_size);

         off = qcow2_alloc_clusters(bs, s->cluster_size);
@@ -1121,7 +1125,9 @@ 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,
+                                         sector * BDRV_SECTOR_SIZE,
+                                         (end - sector) * BDRV_SECTOR_SIZE);
         if (write_size < s->cluster_size) {
             memset(buf + write_size, 0, s->cluster_size - write_size);
         }
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 07/17] qcow2: Switch sectors_covered_by_bitmap_cluster() to byte-based
  2017-07-03 15:10 [Qemu-devel] [PATCH v4 00/17] make dirty-bitmap byte-based Eric Blake
                   ` (5 preceding siblings ...)
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 06/17] dirty-bitmap: Change bdrv_dirty_bitmap_*serialize*() to take bytes Eric Blake
@ 2017-07-03 15:10 ` Eric Blake
  2017-07-10 22:54   ` John Snow
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 08/17] dirty-bitmap: Set iterator start by offset, not sector Eric Blake
                   ` (9 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: Eric Blake @ 2017-07-03 15:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, kwolf, jsnow, Max Reitz

We are gradually converting to byte-based interfaces, as they are
easier to reason about than sector-based.  Change the qcow2 bitmap
helper function sectors_covered_by_bitmap_cluster(), renaming it
in the process.

Signed-off-by: Eric Blake <eblake@redhat.com>

---
v4: new patch
---
 block/qcow2-bitmap.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index 8fd2598..7fce226 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -269,18 +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)
 {
-    uint64_t sector_granularity =
-            bdrv_dirty_bitmap_granularity(bitmap) >> BDRV_SECTOR_BITS;
-    uint64_t sbc = sector_granularity * (s->cluster_size << 3);
+    uint64_t granularity = bdrv_dirty_bitmap_granularity(bitmap);
+    uint64_t limit = granularity * (s->cluster_size << 3);

-    assert(QEMU_IS_ALIGNED(sbc << BDRV_SECTOR_BITS,
+    assert(QEMU_IS_ALIGNED(limit,
                            bdrv_dirty_bitmap_serialization_align(bitmap)));
-    return sbc;
+    return limit;
 }

 /* load_bitmap_data
@@ -293,7 +291,7 @@ static int load_bitmap_data(BlockDriverState *bs,
 {
     int ret = 0;
     BDRVQcow2State *s = bs->opaque;
-    uint64_t sector, sbc;
+    uint64_t sector, limit, sbc;
     uint64_t bm_size = bdrv_dirty_bitmap_size(bitmap);
     uint64_t bm_sectors = DIV_ROUND_UP(bm_size, BDRV_SECTOR_SIZE);
     uint8_t *buf = NULL;
@@ -306,7 +304,8 @@ static int load_bitmap_data(BlockDriverState *bs,
     }

     buf = g_malloc(s->cluster_size);
-    sbc = sectors_covered_by_bitmap_cluster(s, bitmap);
+    limit = bytes_covered_by_bitmap_cluster(s, bitmap);
+    sbc = limit >> BDRV_SECTOR_BITS;
     for (i = 0, sector = 0; i < tab_size; ++i, sector += sbc) {
         uint64_t count = MIN(bm_sectors - sector, sbc);
         uint64_t entry = bitmap_table[i];
@@ -1076,7 +1075,7 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
     int ret;
     BDRVQcow2State *s = bs->opaque;
     int64_t sector;
-    uint64_t sbc;
+    uint64_t limit, sbc;
     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);
@@ -1102,8 +1101,9 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,

     dbi = bdrv_dirty_iter_new(bitmap, 0);
     buf = g_malloc(s->cluster_size);
-    sbc = sectors_covered_by_bitmap_cluster(s, bitmap);
-    assert(DIV_ROUND_UP(bm_sectors, sbc) == tb_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)) != -1) {
         uint64_t cluster = sector / sbc;
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 08/17] dirty-bitmap: Set iterator start by offset, not sector
  2017-07-03 15:10 [Qemu-devel] [PATCH v4 00/17] make dirty-bitmap byte-based Eric Blake
                   ` (6 preceding siblings ...)
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 07/17] qcow2: Switch sectors_covered_by_bitmap_cluster() to byte-based Eric Blake
@ 2017-07-03 15:10 ` Eric Blake
  2017-07-10 23:02   ` John Snow
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 09/17] dirty-bitmap: Change bdrv_dirty_iter_next() to report byte offset Eric Blake
                   ` (8 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: Eric Blake @ 2017-07-03 15:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, kwolf, jsnow, Jeff Cody, Max Reitz, Fam Zheng

All callers to bdrv_dirty_iter_new() passed 0 for their initial
starting point, drop that parameter.

Most callers to bdrv_set_dirty_iter() were scaling a byte offset to
a sector number; the exception qcow2-bitmap will be converted later
to use byte rather than sector iteration.  Move the scaling to occur
internally to dirty bitmap code instead, so that callers now pass
in bytes.

Signed-off-by: Eric Blake <eblake@redhat.com>

---
v4: rebase to persistent bitmaps
v3: no change
v2: no change
---
 include/block/dirty-bitmap.h | 5 ++---
 block/backup.c               | 5 ++---
 block/dirty-bitmap.c         | 9 ++++-----
 block/mirror.c               | 4 ++--
 block/qcow2-bitmap.c         | 4 ++--
 5 files changed, 12 insertions(+), 15 deletions(-)

diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
index f4ccd3f..ece28e1 100644
--- a/include/block/dirty-bitmap.h
+++ b/include/block/dirty-bitmap.h
@@ -44,8 +44,7 @@ void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap,
 void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap,
                              int64_t cur_sector, int64_t nr_sectors);
 BdrvDirtyBitmapIter *bdrv_dirty_meta_iter_new(BdrvDirtyBitmap *bitmap);
-BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap,
-                                         uint64_t first_sector);
+BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap);
 void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter);

 uint64_t bdrv_dirty_bitmap_serialization_size(const BdrvDirtyBitmap *bitmap,
@@ -80,7 +79,7 @@ void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
 void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
                                     int64_t cur_sector, int64_t nr_sectors);
 int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter);
-void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *hbi, int64_t sector_num);
+void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *hbi, int64_t offset);
 int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap);
 int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap);
 void bdrv_dirty_bitmap_truncate(BlockDriverState *bs);
diff --git a/block/backup.c b/block/backup.c
index b2048bf..2a94e8b 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -372,7 +372,7 @@ static int coroutine_fn backup_run_incremental(BackupBlockJob *job)

     granularity = bdrv_dirty_bitmap_granularity(job->sync_bitmap);
     clusters_per_iter = MAX((granularity / job->cluster_size), 1);
-    dbi = bdrv_dirty_iter_new(job->sync_bitmap, 0);
+    dbi = bdrv_dirty_iter_new(job->sync_bitmap);

     /* Find the next dirty sector(s) */
     while ((offset = bdrv_dirty_iter_next(dbi) * BDRV_SECTOR_SIZE) >= 0) {
@@ -403,8 +403,7 @@ static int coroutine_fn backup_run_incremental(BackupBlockJob *job)
         /* If the bitmap granularity is smaller than the backup granularity,
          * we need to advance the iterator pointer to the next cluster. */
         if (granularity < job->cluster_size) {
-            bdrv_set_dirty_iter(dbi,
-                                cluster * job->cluster_size / BDRV_SECTOR_SIZE);
+            bdrv_set_dirty_iter(dbi, cluster * job->cluster_size);
         }

         last_cluster = cluster - 1;
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index dc5c205..83049f4 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -476,11 +476,10 @@ uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap)
     return BDRV_SECTOR_SIZE << hbitmap_granularity(bitmap->bitmap);
 }

-BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap,
-                                         uint64_t first_sector)
+BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap)
 {
     BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1);
-    hbitmap_iter_init(&iter->hbi, bitmap->bitmap, first_sector);
+    hbitmap_iter_init(&iter->hbi, bitmap->bitmap, 0);
     iter->bitmap = bitmap;
     bitmap->active_iterators++;
     return iter;
@@ -648,9 +647,9 @@ void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector,
 /**
  * Advance a BdrvDirtyBitmapIter to an arbitrary offset.
  */
-void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *iter, int64_t sector_num)
+void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *iter, int64_t offset)
 {
-    hbitmap_iter_init(&iter->hbi, iter->hbi.hb, sector_num);
+    hbitmap_iter_init(&iter->hbi, iter->hbi.hb, offset >> BDRV_SECTOR_BITS);
 }

 int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap)
diff --git a/block/mirror.c b/block/mirror.c
index 8c3752b..3869450 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -373,7 +373,7 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
         next_dirty = bdrv_dirty_iter_next(s->dbi) * BDRV_SECTOR_SIZE;
         if (next_dirty > next_offset || next_dirty < 0) {
             /* The bitmap iterator's cache is stale, refresh it */
-            bdrv_set_dirty_iter(s->dbi, next_offset >> BDRV_SECTOR_BITS);
+            bdrv_set_dirty_iter(s->dbi, next_offset);
             next_dirty = bdrv_dirty_iter_next(s->dbi) * BDRV_SECTOR_SIZE;
         }
         assert(next_dirty == next_offset);
@@ -791,7 +791,7 @@ static void coroutine_fn mirror_run(void *opaque)
     }

     assert(!s->dbi);
-    s->dbi = bdrv_dirty_iter_new(s->dirty_bitmap, 0);
+    s->dbi = bdrv_dirty_iter_new(s->dirty_bitmap);
     for (;;) {
         uint64_t delay_ns = 0;
         int64_t cnt, delta;
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index 7fce226..533e9fd 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -1099,7 +1099,7 @@ 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);
     limit = bytes_covered_by_bitmap_cluster(s, bitmap);
     sbc = limit >> BDRV_SECTOR_BITS;
@@ -1149,7 +1149,7 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
             break;
         }

-        bdrv_set_dirty_iter(dbi, end);
+        bdrv_set_dirty_iter(dbi, end * BDRV_SECTOR_SIZE);
     }

     *bitmap_table_size = tb_size;
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 09/17] dirty-bitmap: Change bdrv_dirty_iter_next() to report byte offset
  2017-07-03 15:10 [Qemu-devel] [PATCH v4 00/17] make dirty-bitmap byte-based Eric Blake
                   ` (7 preceding siblings ...)
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 08/17] dirty-bitmap: Set iterator start by offset, not sector Eric Blake
@ 2017-07-03 15:10 ` Eric Blake
  2017-07-10 23:20   ` John Snow
  2017-07-11 16:50   ` Eric Blake
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 10/17] dirty-bitmap: Change bdrv_get_dirty_count() to report bytes Eric Blake
                   ` (7 subsequent siblings)
  16 siblings, 2 replies; 38+ messages in thread
From: Eric Blake @ 2017-07-03 15:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, kwolf, jsnow, Jeff Cody, Max Reitz, Fam Zheng

Thanks to recent cleanups, most callers were scaling a return value
of sectors into bytes (the exception, in qcow2-bitmap, will be
converted to byte-based iteration later).  Update the interface to
do the scaling internally instead.

Signed-off-by: Eric Blake <eblake@redhat.com>

---
v4: rebase to persistent bitmap
v3: no change
v2: no change
---
 block/backup.c       | 2 +-
 block/dirty-bitmap.c | 2 +-
 block/mirror.c       | 8 ++++----
 block/qcow2-bitmap.c | 2 +-
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/block/backup.c b/block/backup.c
index 2a94e8b..18389cd 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -375,7 +375,7 @@ static int coroutine_fn backup_run_incremental(BackupBlockJob *job)
     dbi = bdrv_dirty_iter_new(job->sync_bitmap);

     /* Find the next dirty sector(s) */
-    while ((offset = bdrv_dirty_iter_next(dbi) * BDRV_SECTOR_SIZE) >= 0) {
+    while ((offset = bdrv_dirty_iter_next(dbi)) >= 0) {
         cluster = offset / job->cluster_size;

         /* Fake progress updates for any clusters we skipped */
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index 83049f4..3cf7f39 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -506,7 +506,7 @@ void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter)

 int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter)
 {
-    return hbitmap_iter_next(&iter->hbi);
+    return hbitmap_iter_next(&iter->hbi) * BDRV_SECTOR_SIZE;
 }

 /* Called within bdrv_dirty_bitmap_lock..unlock */
diff --git a/block/mirror.c b/block/mirror.c
index 3869450..0cde201 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -336,10 +336,10 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
     int max_io_bytes = MAX(s->buf_size / MAX_IN_FLIGHT, MAX_IO_BYTES);

     bdrv_dirty_bitmap_lock(s->dirty_bitmap);
-    offset = bdrv_dirty_iter_next(s->dbi) * BDRV_SECTOR_SIZE;
+    offset = bdrv_dirty_iter_next(s->dbi);
     if (offset < 0) {
         bdrv_set_dirty_iter(s->dbi, 0);
-        offset = bdrv_dirty_iter_next(s->dbi) * BDRV_SECTOR_SIZE;
+        offset = bdrv_dirty_iter_next(s->dbi);
         trace_mirror_restart_iter(s, bdrv_get_dirty_count(s->dirty_bitmap) *
                                   BDRV_SECTOR_SIZE);
         assert(offset >= 0);
@@ -370,11 +370,11 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
             break;
         }

-        next_dirty = bdrv_dirty_iter_next(s->dbi) * BDRV_SECTOR_SIZE;
+        next_dirty = bdrv_dirty_iter_next(s->dbi);
         if (next_dirty > next_offset || next_dirty < 0) {
             /* The bitmap iterator's cache is stale, refresh it */
             bdrv_set_dirty_iter(s->dbi, next_offset);
-            next_dirty = bdrv_dirty_iter_next(s->dbi) * BDRV_SECTOR_SIZE;
+            next_dirty = bdrv_dirty_iter_next(s->dbi);
         }
         assert(next_dirty == next_offset);
         nb_chunks++;
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index 533e9fd..280960a 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -1105,7 +1105,7 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
     sbc = limit >> BDRV_SECTOR_BITS;
     assert(DIV_ROUND_UP(bm_size, limit) == tb_size);

-    while ((sector = bdrv_dirty_iter_next(dbi)) != -1) {
+    while ((sector = bdrv_dirty_iter_next(dbi) >> BDRV_SECTOR_BITS) != -1) {
         uint64_t cluster = sector / sbc;
         uint64_t end, write_size;
         int64_t off;
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 10/17] dirty-bitmap: Change bdrv_get_dirty_count() to report bytes
  2017-07-03 15:10 [Qemu-devel] [PATCH v4 00/17] make dirty-bitmap byte-based Eric Blake
                   ` (8 preceding siblings ...)
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 09/17] dirty-bitmap: Change bdrv_dirty_iter_next() to report byte offset Eric Blake
@ 2017-07-03 15:10 ` Eric Blake
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 11/17] dirty-bitmap: Change bdrv_get_dirty_locked() to take bytes Eric Blake
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 38+ messages in thread
From: Eric Blake @ 2017-07-03 15:10 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, kwolf, jsnow, Fam Zheng, Max Reitz, Jeff Cody,
	Stefan Hajnoczi, Juan Quintela, Dr. David Alan Gilbert

Thanks to recent cleanups, all callers were scaling a return value
of sectors into bytes; do the scaling internally instead.

Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>

---
v4: no change
v3: no change, add R-b
v2: no change
---
 block/dirty-bitmap.c |  4 ++--
 block/mirror.c       | 13 +++++--------
 migration/block.c    |  2 +-
 3 files changed, 8 insertions(+), 11 deletions(-)

diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index 3cf7f39..3b94f74 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -426,7 +426,7 @@ BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs)
     QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
         BlockDirtyInfo *info = g_new0(BlockDirtyInfo, 1);
         BlockDirtyInfoList *entry = g_new0(BlockDirtyInfoList, 1);
-        info->count = bdrv_get_dirty_count(bm) << BDRV_SECTOR_BITS;
+        info->count = bdrv_get_dirty_count(bm);
         info->granularity = bdrv_dirty_bitmap_granularity(bm);
         info->has_name = !!bm->name;
         info->name = g_strdup(bm->name);
@@ -654,7 +654,7 @@ void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *iter, int64_t offset)

 int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap)
 {
-    return hbitmap_count(bitmap->bitmap);
+    return hbitmap_count(bitmap->bitmap) << BDRV_SECTOR_BITS;
 }

 int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap)
diff --git a/block/mirror.c b/block/mirror.c
index 0cde201..6ea6a27 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -806,11 +806,10 @@ static void coroutine_fn mirror_run(void *opaque)

         cnt = bdrv_get_dirty_count(s->dirty_bitmap);
         /* s->common.offset contains the number of bytes already processed so
-         * far, cnt is the number of dirty sectors remaining and
+         * far, cnt is the number of dirty bytes remaining and
          * s->bytes_in_flight is the number of bytes currently being
          * processed; together those are the current total operation length */
-        s->common.len = s->common.offset + s->bytes_in_flight +
-            cnt * BDRV_SECTOR_SIZE;
+        s->common.len = s->common.offset + s->bytes_in_flight + cnt;

         /* Note that even when no rate limit is applied we need to yield
          * periodically with no pending I/O so that bdrv_drain_all() returns.
@@ -822,8 +821,7 @@ static void coroutine_fn mirror_run(void *opaque)
             s->common.iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
             if (s->in_flight >= MAX_IN_FLIGHT || s->buf_free_count == 0 ||
                 (cnt == 0 && s->in_flight > 0)) {
-                trace_mirror_yield(s, cnt * BDRV_SECTOR_SIZE,
-                                   s->buf_free_count, s->in_flight);
+                trace_mirror_yield(s, cnt, s->buf_free_count, s->in_flight);
                 mirror_wait_for_io(s);
                 continue;
             } else if (cnt != 0) {
@@ -864,7 +862,7 @@ static void coroutine_fn mirror_run(void *opaque)
              * whether to switch to target check one last time if I/O has
              * come in the meanwhile, and if not flush the data to disk.
              */
-            trace_mirror_before_drain(s, cnt * BDRV_SECTOR_SIZE);
+            trace_mirror_before_drain(s, cnt);

             bdrv_drained_begin(bs);
             cnt = bdrv_get_dirty_count(s->dirty_bitmap);
@@ -883,8 +881,7 @@ static void coroutine_fn mirror_run(void *opaque)
         }

         ret = 0;
-        trace_mirror_before_sleep(s, cnt * BDRV_SECTOR_SIZE,
-                                  s->synced, delay_ns);
+        trace_mirror_before_sleep(s, cnt, s->synced, delay_ns);
         if (!s->synced) {
             block_job_sleep_ns(&s->common, QEMU_CLOCK_REALTIME, delay_ns);
             if (block_job_is_cancelled(&s->common)) {
diff --git a/migration/block.c b/migration/block.c
index 4a48e5c..d14f745 100644
--- a/migration/block.c
+++ b/migration/block.c
@@ -664,7 +664,7 @@ static int64_t get_remaining_dirty(void)
         aio_context_release(blk_get_aio_context(bmds->blk));
     }

-    return dirty << BDRV_SECTOR_BITS;
+    return dirty;
 }


-- 
2.9.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 11/17] dirty-bitmap: Change bdrv_get_dirty_locked() to take bytes
  2017-07-03 15:10 [Qemu-devel] [PATCH v4 00/17] make dirty-bitmap byte-based Eric Blake
                   ` (9 preceding siblings ...)
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 10/17] dirty-bitmap: Change bdrv_get_dirty_count() to report bytes Eric Blake
@ 2017-07-03 15:10 ` Eric Blake
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 12/17] dirty-bitmap: Change bdrv_[re]set_dirty_bitmap() to use bytes Eric Blake
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 38+ messages in thread
From: Eric Blake @ 2017-07-03 15:10 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, kwolf, jsnow, Fam Zheng, Max Reitz, Jeff Cody,
	Stefan Hajnoczi, Juan Quintela, Dr. David Alan Gilbert

Half the callers were already scaling bytes to sectors; the other
half can eventually be simplified to use byte iteration.  Both
callers were already using the result as a bool, so make that
explicit.  Making the change also makes it easier for a future
dirty-bitmap patch to offload scaling over to the internal hbitmap.

Remember, asking whether a byte is dirty is effectively asking
whether the entire granularity containing the byte is dirty, since
we only track dirtiness by granularity.

Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>

---
v4: only context change
v3: rebase to _locked rename was straightforward enough that R-b kept
v2: tweak commit message, no code change
---
 include/block/dirty-bitmap.h | 4 ++--
 block/dirty-bitmap.c         | 8 ++++----
 block/mirror.c               | 3 +--
 migration/block.c            | 3 ++-
 4 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
index ece28e1..1dddcd3 100644
--- a/include/block/dirty-bitmap.h
+++ b/include/block/dirty-bitmap.h
@@ -72,8 +72,8 @@ void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap,
 /* Functions that require manual locking.  */
 void bdrv_dirty_bitmap_lock(BdrvDirtyBitmap *bitmap);
 void bdrv_dirty_bitmap_unlock(BdrvDirtyBitmap *bitmap);
-int bdrv_get_dirty_locked(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
-                          int64_t sector);
+bool bdrv_get_dirty_locked(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
+                           int64_t offset);
 void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
                                   int64_t cur_sector, int64_t nr_sectors);
 void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index 3b94f74..03ed2f6 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -441,13 +441,13 @@ BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs)
 }

 /* Called within bdrv_dirty_bitmap_lock..unlock */
-int bdrv_get_dirty_locked(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
-                          int64_t sector)
+bool bdrv_get_dirty_locked(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
+                           int64_t offset)
 {
     if (bitmap) {
-        return hbitmap_get(bitmap->bitmap, sector);
+        return hbitmap_get(bitmap->bitmap, offset >> BDRV_SECTOR_BITS);
     } else {
-        return 0;
+        return false;
     }
 }

diff --git a/block/mirror.c b/block/mirror.c
index 6ea6a27..19331c0 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -362,8 +362,7 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
         int64_t next_offset = offset + nb_chunks * s->granularity;
         int64_t next_chunk = next_offset / s->granularity;
         if (next_offset >= s->bdev_length ||
-            !bdrv_get_dirty_locked(source, s->dirty_bitmap,
-                                   next_offset >> BDRV_SECTOR_BITS)) {
+            !bdrv_get_dirty_locked(source, s->dirty_bitmap, next_offset)) {
             break;
         }
         if (test_bit(next_chunk, s->in_flight_bitmap)) {
diff --git a/migration/block.c b/migration/block.c
index d14f745..d6557a1 100644
--- a/migration/block.c
+++ b/migration/block.c
@@ -527,7 +527,8 @@ static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
             blk_mig_unlock();
         }
         bdrv_dirty_bitmap_lock(bmds->dirty_bitmap);
-        if (bdrv_get_dirty_locked(bs, bmds->dirty_bitmap, sector)) {
+        if (bdrv_get_dirty_locked(bs, bmds->dirty_bitmap,
+                                  sector * BDRV_SECTOR_SIZE)) {
             if (total_sectors - sector < BDRV_SECTORS_PER_DIRTY_CHUNK) {
                 nr_sectors = total_sectors - sector;
             } else {
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 12/17] dirty-bitmap: Change bdrv_[re]set_dirty_bitmap() to use bytes
  2017-07-03 15:10 [Qemu-devel] [PATCH v4 00/17] make dirty-bitmap byte-based Eric Blake
                   ` (10 preceding siblings ...)
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 11/17] dirty-bitmap: Change bdrv_get_dirty_locked() to take bytes Eric Blake
@ 2017-07-03 15:10 ` Eric Blake
  2017-07-12 19:25   ` John Snow
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 13/17] mirror: Switch mirror_dirty_init() to byte-based iteration Eric Blake
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 38+ messages in thread
From: Eric Blake @ 2017-07-03 15:10 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, kwolf, jsnow, Fam Zheng, Max Reitz, Jeff Cody,
	Stefan Hajnoczi, Juan Quintela, Dr. David Alan Gilbert

Some of the callers were already scaling bytes to sectors; others
can be easily converted to pass byte offsets, all in our shift
towards a consistent byte interface everywhere.  Making the change
will also make it easier to write the hold-out callers to use byte
rather than sectors for their iterations; it also makes it easier
for a future dirty-bitmap patch to offload scaling over to the
internal hbitmap.  Although all callers happen to pass
sector-aligned values, make the internal scaling robust to any
sub-sector requests.

Signed-off-by: Eric Blake <eblake@redhat.com>

---
v4: only context change, due to rebasing to persistent bitmaps
v3: rebase to addition of _locked interfaces; complex enough that I
dropped R-b
v2: no change
---
 include/block/dirty-bitmap.h |  8 ++++----
 block/dirty-bitmap.c         | 22 ++++++++++++++--------
 block/mirror.c               | 16 ++++++++--------
 migration/block.c            |  7 +++++--
 4 files changed, 31 insertions(+), 22 deletions(-)

diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
index 1dddcd3..0341a60 100644
--- a/include/block/dirty-bitmap.h
+++ b/include/block/dirty-bitmap.h
@@ -40,9 +40,9 @@ const char *bdrv_dirty_bitmap_name(const BdrvDirtyBitmap *bitmap);
 int64_t bdrv_dirty_bitmap_size(const BdrvDirtyBitmap *bitmap);
 DirtyBitmapStatus bdrv_dirty_bitmap_status(BdrvDirtyBitmap *bitmap);
 void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap,
-                           int64_t cur_sector, int64_t nr_sectors);
+                           int64_t offset, int64_t bytes);
 void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap,
-                             int64_t cur_sector, int64_t nr_sectors);
+                             int64_t offset, int64_t bytes);
 BdrvDirtyBitmapIter *bdrv_dirty_meta_iter_new(BdrvDirtyBitmap *bitmap);
 BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap);
 void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter);
@@ -75,9 +75,9 @@ void bdrv_dirty_bitmap_unlock(BdrvDirtyBitmap *bitmap);
 bool bdrv_get_dirty_locked(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
                            int64_t offset);
 void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
-                                  int64_t cur_sector, int64_t nr_sectors);
+                                  int64_t offset, int64_t bytes);
 void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
-                                    int64_t cur_sector, int64_t nr_sectors);
+                                    int64_t offset, int64_t bytes);
 int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter);
 void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *hbi, int64_t offset);
 int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap);
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index 03ed2f6..7c79da4 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -511,35 +511,41 @@ int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter)

 /* Called within bdrv_dirty_bitmap_lock..unlock */
 void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
-                                  int64_t cur_sector, int64_t nr_sectors)
+                                  int64_t offset, int64_t bytes)
 {
+    int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);
+
     assert(bdrv_dirty_bitmap_enabled(bitmap));
     assert(!bdrv_dirty_bitmap_readonly(bitmap));
-    hbitmap_set(bitmap->bitmap, cur_sector, nr_sectors);
+    hbitmap_set(bitmap->bitmap, offset >> BDRV_SECTOR_BITS,
+                end_sector - (offset >> BDRV_SECTOR_BITS));
 }

 void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap,
-                           int64_t cur_sector, int64_t nr_sectors)
+                           int64_t offset, int64_t bytes)
 {
     bdrv_dirty_bitmap_lock(bitmap);
-    bdrv_set_dirty_bitmap_locked(bitmap, cur_sector, nr_sectors);
+    bdrv_set_dirty_bitmap_locked(bitmap, offset, bytes);
     bdrv_dirty_bitmap_unlock(bitmap);
 }

 /* Called within bdrv_dirty_bitmap_lock..unlock */
 void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
-                                    int64_t cur_sector, int64_t nr_sectors)
+                                    int64_t offset, int64_t bytes)
 {
+    int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);
+
     assert(bdrv_dirty_bitmap_enabled(bitmap));
     assert(!bdrv_dirty_bitmap_readonly(bitmap));
-    hbitmap_reset(bitmap->bitmap, cur_sector, nr_sectors);
+    hbitmap_reset(bitmap->bitmap, offset >> BDRV_SECTOR_BITS,
+                  end_sector - (offset >> BDRV_SECTOR_BITS));
 }

 void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap,
-                             int64_t cur_sector, int64_t nr_sectors)
+                             int64_t offset, int64_t bytes)
 {
     bdrv_dirty_bitmap_lock(bitmap);
-    bdrv_reset_dirty_bitmap_locked(bitmap, cur_sector, nr_sectors);
+    bdrv_reset_dirty_bitmap_locked(bitmap, offset, bytes);
     bdrv_dirty_bitmap_unlock(bitmap);
 }

diff --git a/block/mirror.c b/block/mirror.c
index 19331c0..b74d6e0 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -141,8 +141,7 @@ static void mirror_write_complete(void *opaque, int ret)
     if (ret < 0) {
         BlockErrorAction action;

-        bdrv_set_dirty_bitmap(s->dirty_bitmap, op->offset >> BDRV_SECTOR_BITS,
-                              op->bytes >> BDRV_SECTOR_BITS);
+        bdrv_set_dirty_bitmap(s->dirty_bitmap, op->offset, op->bytes);
         action = mirror_error_action(s, false, -ret);
         if (action == BLOCK_ERROR_ACTION_REPORT && s->ret >= 0) {
             s->ret = ret;
@@ -161,8 +160,7 @@ static void mirror_read_complete(void *opaque, int ret)
     if (ret < 0) {
         BlockErrorAction action;

-        bdrv_set_dirty_bitmap(s->dirty_bitmap, op->offset >> BDRV_SECTOR_BITS,
-                              op->bytes >> BDRV_SECTOR_BITS);
+        bdrv_set_dirty_bitmap(s->dirty_bitmap, op->offset, op->bytes);
         action = mirror_error_action(s, true, -ret);
         if (action == BLOCK_ERROR_ACTION_REPORT && s->ret >= 0) {
             s->ret = ret;
@@ -383,8 +381,8 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
      * calling bdrv_get_block_status_above could yield - if some blocks are
      * marked dirty in this window, we need to know.
      */
-    bdrv_reset_dirty_bitmap_locked(s->dirty_bitmap, offset >> BDRV_SECTOR_BITS,
-                                   nb_chunks * sectors_per_chunk);
+    bdrv_reset_dirty_bitmap_locked(s->dirty_bitmap, offset,
+                                   nb_chunks * s->granularity);
     bdrv_dirty_bitmap_unlock(s->dirty_bitmap);

     bitmap_set(s->in_flight_bitmap, offset / s->granularity, nb_chunks);
@@ -626,7 +624,7 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)

     if (base == NULL && !bdrv_has_zero_init(target_bs)) {
         if (!bdrv_can_write_zeroes_with_unmap(target_bs)) {
-            bdrv_set_dirty_bitmap(s->dirty_bitmap, 0, end);
+            bdrv_set_dirty_bitmap(s->dirty_bitmap, 0, s->bdev_length);
             return 0;
         }

@@ -679,7 +677,9 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
         n = DIV_ROUND_UP(count, BDRV_SECTOR_SIZE);
         assert(n > 0);
         if (ret == 1) {
-            bdrv_set_dirty_bitmap(s->dirty_bitmap, sector_num, n);
+            bdrv_set_dirty_bitmap(s->dirty_bitmap,
+                                  sector_num * BDRV_SECTOR_SIZE,
+                                  n * BDRV_SECTOR_SIZE);
         }
         sector_num += n;
     }
diff --git a/migration/block.c b/migration/block.c
index d6557a1..2844149 100644
--- a/migration/block.c
+++ b/migration/block.c
@@ -326,7 +326,8 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
     blk->aiocb = blk_aio_preadv(bb, cur_sector * BDRV_SECTOR_SIZE, &blk->qiov,
                                 0, blk_mig_read_cb, blk);

-    bdrv_reset_dirty_bitmap(bmds->dirty_bitmap, cur_sector, nr_sectors);
+    bdrv_reset_dirty_bitmap(bmds->dirty_bitmap, cur_sector * BDRV_SECTOR_SIZE,
+                            nr_sectors * BDRV_SECTOR_SIZE);
     aio_context_release(blk_get_aio_context(bmds->blk));
     qemu_mutex_unlock_iothread();

@@ -534,7 +535,9 @@ static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
             } else {
                 nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK;
             }
-            bdrv_reset_dirty_bitmap_locked(bmds->dirty_bitmap, sector, nr_sectors);
+            bdrv_reset_dirty_bitmap_locked(bmds->dirty_bitmap,
+                                           sector * BDRV_SECTOR_SIZE,
+                                           nr_sectors * BDRV_SECTOR_SIZE);
             bdrv_dirty_bitmap_unlock(bmds->dirty_bitmap);

             blk = g_new(BlkMigBlock, 1);
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 13/17] mirror: Switch mirror_dirty_init() to byte-based iteration
  2017-07-03 15:10 [Qemu-devel] [PATCH v4 00/17] make dirty-bitmap byte-based Eric Blake
                   ` (11 preceding siblings ...)
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 12/17] dirty-bitmap: Change bdrv_[re]set_dirty_bitmap() to use bytes Eric Blake
@ 2017-07-03 15:10 ` Eric Blake
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 14/17] qcow2: Switch load_bitmap_data() " Eric Blake
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 38+ messages in thread
From: Eric Blake @ 2017-07-03 15:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, kwolf, jsnow, Jeff Cody, Max Reitz

Now that we have adjusted the majority of the calls this function
makes to be byte-based, it is easier to read the code if it makes
passes over the image using bytes rather than sectors.

Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>

---
v2-v4: no change
---
 block/mirror.c | 35 ++++++++++++++---------------------
 1 file changed, 14 insertions(+), 21 deletions(-)

diff --git a/block/mirror.c b/block/mirror.c
index b74d6e0..6f54dcc 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -613,15 +613,13 @@ static void mirror_throttle(MirrorBlockJob *s)

 static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
 {
-    int64_t sector_num, end;
+    int64_t offset;
     BlockDriverState *base = s->base;
     BlockDriverState *bs = s->source;
     BlockDriverState *target_bs = blk_bs(s->target);
-    int ret, n;
+    int ret;
     int64_t count;

-    end = s->bdev_length / BDRV_SECTOR_SIZE;
-
     if (base == NULL && !bdrv_has_zero_init(target_bs)) {
         if (!bdrv_can_write_zeroes_with_unmap(target_bs)) {
             bdrv_set_dirty_bitmap(s->dirty_bitmap, 0, s->bdev_length);
@@ -629,9 +627,9 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
         }

         s->initial_zeroing_ongoing = true;
-        for (sector_num = 0; sector_num < end; ) {
-            int nb_sectors = MIN(end - sector_num,
-                QEMU_ALIGN_DOWN(INT_MAX, s->granularity) >> BDRV_SECTOR_BITS);
+        for (offset = 0; offset < s->bdev_length; ) {
+            int bytes = MIN(s->bdev_length - offset,
+                            QEMU_ALIGN_DOWN(INT_MAX, s->granularity));

             mirror_throttle(s);

@@ -647,9 +645,8 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
                 continue;
             }

-            mirror_do_zero_or_discard(s, sector_num * BDRV_SECTOR_SIZE,
-                                      nb_sectors * BDRV_SECTOR_SIZE, false);
-            sector_num += nb_sectors;
+            mirror_do_zero_or_discard(s, offset, bytes, false);
+            offset += bytes;
         }

         mirror_wait_for_all_io(s);
@@ -657,10 +654,10 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
     }

     /* First part, loop on the sectors and initialize the dirty bitmap.  */
-    for (sector_num = 0; sector_num < end; ) {
+    for (offset = 0; offset < s->bdev_length; ) {
         /* Just to make sure we are not exceeding int limit. */
-        int nb_sectors = MIN(INT_MAX >> BDRV_SECTOR_BITS,
-                             end - sector_num);
+        int bytes = MIN(s->bdev_length - offset,
+                        QEMU_ALIGN_DOWN(INT_MAX, s->granularity));

         mirror_throttle(s);

@@ -668,20 +665,16 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
             return 0;
         }

-        ret = bdrv_is_allocated_above(bs, base, sector_num * BDRV_SECTOR_SIZE,
-                                      nb_sectors * BDRV_SECTOR_SIZE, &count);
+        ret = bdrv_is_allocated_above(bs, base, offset, bytes, &count);
         if (ret < 0) {
             return ret;
         }

-        n = DIV_ROUND_UP(count, BDRV_SECTOR_SIZE);
-        assert(n > 0);
+        count = QEMU_ALIGN_UP(count, BDRV_SECTOR_SIZE);
         if (ret == 1) {
-            bdrv_set_dirty_bitmap(s->dirty_bitmap,
-                                  sector_num * BDRV_SECTOR_SIZE,
-                                  n * BDRV_SECTOR_SIZE);
+            bdrv_set_dirty_bitmap(s->dirty_bitmap, offset, count);
         }
-        sector_num += n;
+        offset += count;
     }
     return 0;
 }
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 14/17] qcow2: Switch load_bitmap_data() to byte-based iteration
  2017-07-03 15:10 [Qemu-devel] [PATCH v4 00/17] make dirty-bitmap byte-based Eric Blake
                   ` (12 preceding siblings ...)
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 13/17] mirror: Switch mirror_dirty_init() to byte-based iteration Eric Blake
@ 2017-07-03 15:10 ` Eric Blake
  2017-07-12 20:15   ` John Snow
  2017-07-13  9:16   ` Vladimir Sementsov-Ogievskiy
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 15/17] qcow2: Switch store_bitmap_data() " Eric Blake
                   ` (2 subsequent siblings)
  16 siblings, 2 replies; 38+ messages in thread
From: Eric Blake @ 2017-07-03 15:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, kwolf, jsnow, Max Reitz

Now that we have adjusted the majority of the calls this function
makes to be byte-based, it is easier to read the code if it makes
passes over the image using bytes rather than sectors.

Signed-off-by: Eric Blake <eblake@redhat.com>

---
v4: new patch
---
 block/qcow2-bitmap.c | 22 ++++++++--------------
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index 280960a..1de2ab5 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -291,9 +291,8 @@ static int load_bitmap_data(BlockDriverState *bs,
 {
     int ret = 0;
     BDRVQcow2State *s = bs->opaque;
-    uint64_t sector, limit, sbc;
+    uint64_t offset, limit;
     uint64_t bm_size = bdrv_dirty_bitmap_size(bitmap);
-    uint64_t bm_sectors = DIV_ROUND_UP(bm_size, BDRV_SECTOR_SIZE);
     uint8_t *buf = NULL;
     uint64_t i, tab_size =
             size_to_clusters(s,
@@ -305,32 +304,27 @@ static int load_bitmap_data(BlockDriverState *bs,

     buf = g_malloc(s->cluster_size);
     limit = bytes_covered_by_bitmap_cluster(s, bitmap);
-    sbc = limit >> BDRV_SECTOR_BITS;
-    for (i = 0, sector = 0; i < tab_size; ++i, sector += sbc) {
-        uint64_t count = MIN(bm_sectors - sector, sbc);
+    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 * BDRV_SECTOR_SIZE,
-                                                   count * BDRV_SECTOR_SIZE,
+                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 * BDRV_SECTOR_SIZE,
-                                               count * BDRV_SECTOR_SIZE,
+            bdrv_dirty_bitmap_deserialize_part(bitmap, buf, offset, count,
                                                false);
         }
     }
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 15/17] qcow2: Switch store_bitmap_data() to byte-based iteration
  2017-07-03 15:10 [Qemu-devel] [PATCH v4 00/17] make dirty-bitmap byte-based Eric Blake
                   ` (13 preceding siblings ...)
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 14/17] qcow2: Switch load_bitmap_data() " Eric Blake
@ 2017-07-03 15:10 ` Eric Blake
  2017-07-12 20:28   ` John Snow
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 16/17] dirty-bitmap: Switch bdrv_set_dirty() to bytes Eric Blake
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 17/17] dirty-bitmap: Convert internal hbitmap size/granularity Eric Blake
  16 siblings, 1 reply; 38+ messages in thread
From: Eric Blake @ 2017-07-03 15:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, kwolf, jsnow, Max Reitz

Now that we have adjusted the majority of the calls this function
makes to be byte-based, it is easier to read the code if it makes
passes over the image using bytes rather than sectors.

Signed-off-by: Eric Blake <eblake@redhat.com>

---
v4: new patch
---
 block/qcow2-bitmap.c | 26 +++++++++++---------------
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index 1de2ab5..04624da 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -1068,10 +1068,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;
@@ -1096,18 +1095,17 @@ 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) != -1) {
-        uint64_t cluster = sector / sbc;
+    while ((offset = bdrv_dirty_iter_next(dbi)) != -1) {
+        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);
+        offset = cluster * 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);
@@ -1119,9 +1117,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);
         }
@@ -1139,11 +1135,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;
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 16/17] dirty-bitmap: Switch bdrv_set_dirty() to bytes
  2017-07-03 15:10 [Qemu-devel] [PATCH v4 00/17] make dirty-bitmap byte-based Eric Blake
                   ` (14 preceding siblings ...)
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 15/17] qcow2: Switch store_bitmap_data() " Eric Blake
@ 2017-07-03 15:10 ` Eric Blake
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 17/17] dirty-bitmap: Convert internal hbitmap size/granularity Eric Blake
  16 siblings, 0 replies; 38+ messages in thread
From: Eric Blake @ 2017-07-03 15:10 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-block, kwolf, jsnow, Fam Zheng, Max Reitz, Stefan Hajnoczi

Both callers already had bytes available, but were scaling to
sectors.  Move the scaling to internal code.  In the case of
bdrv_aligned_pwritev(), we are now passing the exact offset
rather than a rounded sector-aligned value, but that's okay
as long as dirty bitmap widens start/bytes to granularity
boundaries.

Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>

---
v4: only context changes
v3: rebase to lock context changes, R-b kept
v2: no change
---
 include/block/block_int.h | 2 +-
 block/dirty-bitmap.c      | 7 ++++---
 block/io.c                | 6 ++----
 3 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/include/block/block_int.h b/include/block/block_int.h
index 58d4ffd..226232d 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -966,7 +966,7 @@ void blk_dev_eject_request(BlockBackend *blk, bool force);
 bool blk_dev_is_tray_open(BlockBackend *blk);
 bool blk_dev_is_medium_locked(BlockBackend *blk);

-void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector, int64_t nr_sect);
+void bdrv_set_dirty(BlockDriverState *bs, int64_t offset, int64_t bytes);
 bool bdrv_requests_pending(BlockDriverState *bs);

 void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out);
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index 7c79da4..5bfc7bc 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -630,10 +630,10 @@ void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap)
     hbitmap_deserialize_finish(bitmap->bitmap);
 }

-void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector,
-                    int64_t nr_sectors)
+void bdrv_set_dirty(BlockDriverState *bs, int64_t offset, int64_t bytes)
 {
     BdrvDirtyBitmap *bitmap;
+    int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);

     if (QLIST_EMPTY(&bs->dirty_bitmaps)) {
         return;
@@ -645,7 +645,8 @@ void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector,
             continue;
         }
         assert(!bdrv_dirty_bitmap_readonly(bitmap));
-        hbitmap_set(bitmap->bitmap, cur_sector, nr_sectors);
+        hbitmap_set(bitmap->bitmap, offset >> BDRV_SECTOR_BITS,
+                    end_sector - (offset >> BDRV_SECTOR_BITS));
     }
     bdrv_dirty_bitmaps_unlock(bs);
 }
diff --git a/block/io.c b/block/io.c
index 569c503..53c01cf 100644
--- a/block/io.c
+++ b/block/io.c
@@ -1310,7 +1310,6 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
     bool waited;
     int ret;

-    int64_t start_sector = offset >> BDRV_SECTOR_BITS;
     int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);
     uint64_t bytes_remaining = bytes;
     int max_transfer;
@@ -1385,7 +1384,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
     bdrv_debug_event(bs, BLKDBG_PWRITEV_DONE);

     atomic_inc(&bs->write_gen);
-    bdrv_set_dirty(bs, start_sector, end_sector - start_sector);
+    bdrv_set_dirty(bs, offset, bytes);

     stat64_max(&bs->wr_highest_offset, offset + bytes);

@@ -2394,8 +2393,7 @@ int coroutine_fn bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset,
     ret = 0;
 out:
     atomic_inc(&bs->write_gen);
-    bdrv_set_dirty(bs, req.offset >> BDRV_SECTOR_BITS,
-                   req.bytes >> BDRV_SECTOR_BITS);
+    bdrv_set_dirty(bs, req.offset, req.bytes);
     tracked_request_end(&req);
     bdrv_dec_in_flight(bs);
     return ret;
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [Qemu-devel] [PATCH v4 17/17] dirty-bitmap: Convert internal hbitmap size/granularity
  2017-07-03 15:10 [Qemu-devel] [PATCH v4 00/17] make dirty-bitmap byte-based Eric Blake
                   ` (15 preceding siblings ...)
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 16/17] dirty-bitmap: Switch bdrv_set_dirty() to bytes Eric Blake
@ 2017-07-03 15:10 ` Eric Blake
  2017-07-12 21:00   ` John Snow
  16 siblings, 1 reply; 38+ messages in thread
From: Eric Blake @ 2017-07-03 15:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-block, kwolf, jsnow, Fam Zheng, Max Reitz

Now that all callers are using byte-based interfaces, there's no
reason for our internal hbitmap to remain with sector-based
granularity.  It also simplifies our internal scaling, since we
already know that hbitmap widens requests out to granularity
boundaries.

Signed-off-by: Eric Blake <eblake@redhat.com>

---
v4: rebase to earlier changes, include serialization, R-b dropped
v3: no change
v2: no change
---
 block/dirty-bitmap.c | 60 +++++++++++++++-------------------------------------
 1 file changed, 17 insertions(+), 43 deletions(-)

diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index 5bfc7bc..0b349f0 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -38,7 +38,7 @@
  */
 struct BdrvDirtyBitmap {
     QemuMutex *mutex;
-    HBitmap *bitmap;            /* Dirty sector bitmap implementation */
+    HBitmap *bitmap;            /* Dirty bitmap implementation */
     HBitmap *meta;              /* Meta dirty bitmap */
     BdrvDirtyBitmap *successor; /* Anonymous child; implies frozen status */
     char *name;                 /* Optional non-empty unique ID */
@@ -130,12 +130,7 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
     }
     bitmap = g_new0(BdrvDirtyBitmap, 1);
     bitmap->mutex = &bs->dirty_bitmap_mutex;
-    /*
-     * TODO - let hbitmap track full granularity. For now, it is tracking
-     * only sector granularity, as a shortcut for our iterators.
-     */
-    bitmap->bitmap = hbitmap_alloc(DIV_ROUND_UP(bitmap_size, BDRV_SECTOR_SIZE),
-                                   ctz32(granularity) - BDRV_SECTOR_BITS);
+    bitmap->bitmap = hbitmap_alloc(bitmap_size, ctz32(granularity));
     bitmap->size = bitmap_size;
     bitmap->name = g_strdup(name);
     bitmap->disabled = false;
@@ -310,7 +305,6 @@ void bdrv_dirty_bitmap_truncate(BlockDriverState *bs)
     int64_t size = bdrv_getlength(bs);

     assert(size >= 0);
-    size = DIV_ROUND_UP(size, BDRV_SECTOR_SIZE);
     bdrv_dirty_bitmaps_lock(bs);
     QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
         assert(!bdrv_dirty_bitmap_frozen(bitmap));
@@ -445,7 +439,7 @@ bool bdrv_get_dirty_locked(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
                            int64_t offset)
 {
     if (bitmap) {
-        return hbitmap_get(bitmap->bitmap, offset >> BDRV_SECTOR_BITS);
+        return hbitmap_get(bitmap->bitmap, offset);
     } else {
         return false;
     }
@@ -473,7 +467,7 @@ uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs)

 uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap)
 {
-    return BDRV_SECTOR_SIZE << hbitmap_granularity(bitmap->bitmap);
+    return 1U << hbitmap_granularity(bitmap->bitmap);
 }

 BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap)
@@ -506,19 +500,16 @@ void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter)

 int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter)
 {
-    return hbitmap_iter_next(&iter->hbi) * BDRV_SECTOR_SIZE;
+    return hbitmap_iter_next(&iter->hbi);
 }

 /* Called within bdrv_dirty_bitmap_lock..unlock */
 void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
                                   int64_t offset, int64_t bytes)
 {
-    int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);
-
     assert(bdrv_dirty_bitmap_enabled(bitmap));
     assert(!bdrv_dirty_bitmap_readonly(bitmap));
-    hbitmap_set(bitmap->bitmap, offset >> BDRV_SECTOR_BITS,
-                end_sector - (offset >> BDRV_SECTOR_BITS));
+    hbitmap_set(bitmap->bitmap, offset, bytes);
 }

 void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap,
@@ -533,12 +524,9 @@ void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap,
 void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
                                     int64_t offset, int64_t bytes)
 {
-    int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);
-
     assert(bdrv_dirty_bitmap_enabled(bitmap));
     assert(!bdrv_dirty_bitmap_readonly(bitmap));
-    hbitmap_reset(bitmap->bitmap, offset >> BDRV_SECTOR_BITS,
-                  end_sector - (offset >> BDRV_SECTOR_BITS));
+    hbitmap_reset(bitmap->bitmap, offset, bytes);
 }

 void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap,
@@ -558,8 +546,7 @@ void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out)
         hbitmap_reset_all(bitmap->bitmap);
     } else {
         HBitmap *backup = bitmap->bitmap;
-        bitmap->bitmap = hbitmap_alloc(DIV_ROUND_UP(bitmap->size,
-                                                    BDRV_SECTOR_SIZE),
+        bitmap->bitmap = hbitmap_alloc(bitmap->size,
                                        hbitmap_granularity(backup));
         *out = backup;
     }
@@ -578,51 +565,40 @@ void bdrv_undo_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *in)
 uint64_t bdrv_dirty_bitmap_serialization_size(const BdrvDirtyBitmap *bitmap,
                                               uint64_t offset, uint64_t bytes)
 {
-    assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
-    return hbitmap_serialization_size(bitmap->bitmap,
-                                      offset >> BDRV_SECTOR_BITS,
-                                      bytes >> BDRV_SECTOR_BITS);
+    return hbitmap_serialization_size(bitmap->bitmap, offset, bytes);
 }

 uint64_t bdrv_dirty_bitmap_serialization_align(const BdrvDirtyBitmap *bitmap)
 {
-    return hbitmap_serialization_align(bitmap->bitmap) * BDRV_SECTOR_SIZE;
+    return hbitmap_serialization_align(bitmap->bitmap);
 }

 void bdrv_dirty_bitmap_serialize_part(const BdrvDirtyBitmap *bitmap,
                                       uint8_t *buf, uint64_t offset,
                                       uint64_t bytes)
 {
-    assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
-    hbitmap_serialize_part(bitmap->bitmap, buf, offset >> BDRV_SECTOR_BITS,
-                           bytes >> BDRV_SECTOR_BITS);
+    hbitmap_serialize_part(bitmap->bitmap, buf, offset, bytes);
 }

 void bdrv_dirty_bitmap_deserialize_part(BdrvDirtyBitmap *bitmap,
                                         uint8_t *buf, uint64_t offset,
                                         uint64_t bytes, bool finish)
 {
-    assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
-    hbitmap_deserialize_part(bitmap->bitmap, buf, offset >> BDRV_SECTOR_BITS,
-                             bytes >> BDRV_SECTOR_BITS, finish);
+    hbitmap_deserialize_part(bitmap->bitmap, buf, offset, bytes, finish);
 }

 void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap *bitmap,
                                           uint64_t offset, uint64_t bytes,
                                           bool finish)
 {
-    assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
-    hbitmap_deserialize_zeroes(bitmap->bitmap, offset >> BDRV_SECTOR_BITS,
-                               bytes >> BDRV_SECTOR_BITS, finish);
+    hbitmap_deserialize_zeroes(bitmap->bitmap, offset, bytes, finish);
 }

 void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap,
                                         uint64_t offset, uint64_t bytes,
                                         bool finish)
 {
-    assert(QEMU_IS_ALIGNED(offset | bytes, BDRV_SECTOR_SIZE));
-    hbitmap_deserialize_ones(bitmap->bitmap, offset >> BDRV_SECTOR_BITS,
-                             bytes >> BDRV_SECTOR_BITS, finish);
+    hbitmap_deserialize_ones(bitmap->bitmap, offset, bytes, finish);
 }

 void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap)
@@ -633,7 +609,6 @@ void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap)
 void bdrv_set_dirty(BlockDriverState *bs, int64_t offset, int64_t bytes)
 {
     BdrvDirtyBitmap *bitmap;
-    int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);

     if (QLIST_EMPTY(&bs->dirty_bitmaps)) {
         return;
@@ -645,8 +620,7 @@ void bdrv_set_dirty(BlockDriverState *bs, int64_t offset, int64_t bytes)
             continue;
         }
         assert(!bdrv_dirty_bitmap_readonly(bitmap));
-        hbitmap_set(bitmap->bitmap, offset >> BDRV_SECTOR_BITS,
-                    end_sector - (offset >> BDRV_SECTOR_BITS));
+        hbitmap_set(bitmap->bitmap, offset, bytes);
     }
     bdrv_dirty_bitmaps_unlock(bs);
 }
@@ -656,12 +630,12 @@ void bdrv_set_dirty(BlockDriverState *bs, int64_t offset, int64_t bytes)
  */
 void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *iter, int64_t offset)
 {
-    hbitmap_iter_init(&iter->hbi, iter->hbi.hb, offset >> BDRV_SECTOR_BITS);
+    hbitmap_iter_init(&iter->hbi, iter->hbi.hb, offset);
 }

 int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap)
 {
-    return hbitmap_count(bitmap->bitmap) << BDRV_SECTOR_BITS;
+    return hbitmap_count(bitmap->bitmap);
 }

 int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap)
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 02/17] hbitmap: Rename serialization_granularity to serialization_align
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 02/17] hbitmap: Rename serialization_granularity to serialization_align Eric Blake
@ 2017-07-06 23:03   ` John Snow
  0 siblings, 0 replies; 38+ messages in thread
From: John Snow @ 2017-07-06 23:03 UTC (permalink / raw)
  To: Eric Blake, qemu-devel; +Cc: kwolf, Fam Zheng, qemu-block, Max Reitz



On 07/03/2017 11:10 AM, Eric Blake wrote:
> The only client of hbitmap_serialization_granularity() is dirty-bitmap's
> bdrv_dirty_bitmap_serialization_align().  Keeping the two names consistent
> is worthwhile, and the shorter name is more representative of what the
> function returns (the required alignment to be used for start/count of
> other serialization functions, where violating the alignment causes
> assertion failures).
> 
> Signed-off-by: Eric Blake <eblake@redhat.com>

One of the two hard problems in computer science.

Reviewed-by: John Snow <jsnow@redhat.com>

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 03/17] qcow2: Ensure bitmap serialization is aligned
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 03/17] qcow2: Ensure bitmap serialization is aligned Eric Blake
@ 2017-07-06 23:14   ` John Snow
  0 siblings, 0 replies; 38+ messages in thread
From: John Snow @ 2017-07-06 23:14 UTC (permalink / raw)
  To: Eric Blake, qemu-devel; +Cc: kwolf, qemu-block, Max Reitz



On 07/03/2017 11:10 AM, Eric Blake wrote:
> When subdividing a bitmap serialization, the code in hbitmap.c
> enforces that start/count parameters are aligned (except that
> count can end early at end-of-bitmap).  We exposed this required
> alignment through bdrv_dirty_bitmap_serialization_align(), but
> forgot to actually check that we comply with it.
> 
> Fortunately, qcow2 is never dividing bitmap serialization smaller
> than one cluster (which is a minimum of 512 bytes); so we are
> always compliant with the serialization alignment (which insists
> that we partition at least 64 bits per chunk) because we are doing
> at least 4k bits per chunk.
> 
> Still, it's safer to add an assertion (for the unlikely case that
> we'd ever support a cluster smaller than 512 bytes, or if the
> hbitmap implementation changes what it considers to be aligned),
> rather than leaving bdrv_dirty_bitmap_serialization_align()
> without a caller.
> 
> Signed-off-by: Eric Blake <eblake@redhat.com>

Reviewed-by: John Snow <jsnow@redhat.com>

> 
> ---
> v4: new patch
> ---
>  block/qcow2-bitmap.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
> index 8448bec..75ee238 100644
> --- a/block/qcow2-bitmap.c
> +++ b/block/qcow2-bitmap.c
> @@ -274,10 +274,13 @@ static int free_bitmap_clusters(BlockDriverState *bs, Qcow2BitmapTable *tb)
>  static uint64_t sectors_covered_by_bitmap_cluster(const BDRVQcow2State *s,
>                                                    const BdrvDirtyBitmap *bitmap)
>  {
> -    uint32_t sector_granularity =
> +    uint64_t sector_granularity =
>              bdrv_dirty_bitmap_granularity(bitmap) >> BDRV_SECTOR_BITS;
> +    uint64_t sbc = sector_granularity * (s->cluster_size << 3);
> 
> -    return (uint64_t)sector_granularity * (s->cluster_size << 3);
> +    assert(QEMU_IS_ALIGNED(sbc,
> +                           bdrv_dirty_bitmap_serialization_align(bitmap)));
> +    return sbc;
>  }
> 
>  /* load_bitmap_data
> 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 04/17] dirty-bitmap: Drop unused functions
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 04/17] dirty-bitmap: Drop unused functions Eric Blake
@ 2017-07-06 23:43   ` John Snow
  2017-07-07  8:44     ` Vladimir Sementsov-Ogievskiy
  0 siblings, 1 reply; 38+ messages in thread
From: John Snow @ 2017-07-06 23:43 UTC (permalink / raw)
  To: Eric Blake, qemu-devel
  Cc: kwolf, Fam Zheng, qemu-block, Max Reitz, Vladimir Sementsov-Ogievskiy



On 07/03/2017 11:10 AM, Eric Blake wrote:
> We had several functions that no one is currently using, and which
> use sector-based interfaces.  I'm trying to convert towards byte-based
> interfaces, so it's easier to just drop the unused functions:
> 
> bdrv_dirty_bitmap_get_meta
> bdrv_dirty_bitmap_get_meta_locked
> bdrv_dirty_bitmap_reset_meta
> bdrv_dirty_bitmap_meta_granularity
> 
> Signed-off-by: Eric Blake <eblake@redhat.com>
> 

Admittedly I forget entirely why some of these are here, or to be more
precise I forget entirely why they are unused as I remember exactly why
we needed them -- but I forget why we merged them without a caller.

Oh well. If they're unused, they're unused, and can be re-added,
especially if we're changing the underpinnings.

I bet my last review on this email used nearly identical wordings.

I'm CCing Vladimir so he has a chance to see that we're removing
functions that he may have wanted to use for his migration series.

Reviewed-by: John Snow <jsnow@redhat.com>

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 04/17] dirty-bitmap: Drop unused functions
  2017-07-06 23:43   ` John Snow
@ 2017-07-07  8:44     ` Vladimir Sementsov-Ogievskiy
  2017-07-07 13:05       ` Vladimir Sementsov-Ogievskiy
  0 siblings, 1 reply; 38+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2017-07-07  8:44 UTC (permalink / raw)
  To: John Snow, Eric Blake, qemu-devel; +Cc: kwolf, Fam Zheng, qemu-block, Max Reitz

07.07.2017 02:43, John Snow wrote:
>
> On 07/03/2017 11:10 AM, Eric Blake wrote:
>> We had several functions that no one is currently using, and which
>> use sector-based interfaces.  I'm trying to convert towards byte-based
>> interfaces, so it's easier to just drop the unused functions:
>>
>> bdrv_dirty_bitmap_get_meta
>> bdrv_dirty_bitmap_get_meta_locked
>> bdrv_dirty_bitmap_reset_meta
>> bdrv_dirty_bitmap_meta_granularity
>>
>> Signed-off-by: Eric Blake <eblake@redhat.com>
>>
> Admittedly I forget entirely why some of these are here, or to be more
> precise I forget entirely why they are unused as I remember exactly why
> we needed them -- but I forget why we merged them without a caller.
>
> Oh well. If they're unused, they're unused, and can be re-added,
> especially if we're changing the underpinnings.
>
> I bet my last review on this email used nearly identical wordings.
>
> I'm CCing Vladimir so he has a chance to see that we're removing
> functions that he may have wanted to use for his migration series.
>
> Reviewed-by: John Snow <jsnow@redhat.com>
>

Meta bitmaps was first approach of my dirty-bitmap migration 
realization, and their first realization was in early bitmap-migration 
series. However, now my series are based on postcopy approach and meta 
bitmaps are not needed.

Current realization of meta bitmaps was started by Fam, he wanted to use 
them not only for my migration, but also for persistent bitmap 
optimization (to reduce amount of dirt-bitmap data to be saved, to save 
only changed parts).

This is still true: we can try to make persistent bitmaps storing more 
efficient, using meta bitmaps, but I'm not sure that it is worth doing 
and I have no plans on it for now.



-- 
Best regards,
Vladimir

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 04/17] dirty-bitmap: Drop unused functions
  2017-07-07  8:44     ` Vladimir Sementsov-Ogievskiy
@ 2017-07-07 13:05       ` Vladimir Sementsov-Ogievskiy
  0 siblings, 0 replies; 38+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2017-07-07 13:05 UTC (permalink / raw)
  To: John Snow, Eric Blake, qemu-devel; +Cc: kwolf, Fam Zheng, qemu-block, Max Reitz

07.07.2017 11:44, Vladimir Sementsov-Ogievskiy wrote:
> 07.07.2017 02:43, John Snow wrote:
>>
>> On 07/03/2017 11:10 AM, Eric Blake wrote:
>>> We had several functions that no one is currently using, and which
>>> use sector-based interfaces.  I'm trying to convert towards byte-based
>>> interfaces, so it's easier to just drop the unused functions:
>>>
>>> bdrv_dirty_bitmap_get_meta
>>> bdrv_dirty_bitmap_get_meta_locked
>>> bdrv_dirty_bitmap_reset_meta
>>> bdrv_dirty_bitmap_meta_granularity
>>>
>>> Signed-off-by: Eric Blake <eblake@redhat.com>
>>>
>> Admittedly I forget entirely why some of these are here, or to be more
>> precise I forget entirely why they are unused as I remember exactly why
>> we needed them -- but I forget why we merged them without a caller.
>>
>> Oh well. If they're unused, they're unused, and can be re-added,
>> especially if we're changing the underpinnings.
>>
>> I bet my last review on this email used nearly identical wordings.
>>
>> I'm CCing Vladimir so he has a chance to see that we're removing
>> functions that he may have wanted to use for his migration series.
>>
>> Reviewed-by: John Snow <jsnow@redhat.com>
>>
>
> Meta bitmaps was first approach of my dirty-bitmap migration 
> realization, and their first realization was in early bitmap-migration 
> series. However, now my series are based on postcopy approach and meta 
> bitmaps are not needed.
>
> Current realization of meta bitmaps was started by Fam, he wanted to 
> use them not only for my migration, but also for persistent bitmap 
> optimization (to reduce amount of dirt-bitmap data to be saved, to 
> save only changed parts).
>
> This is still true: we can try to make persistent bitmaps storing more 
> efficient, using meta bitmaps, but I'm not sure that it is worth doing 
> and I have no plans on it for now.
>
>
>

Also, I think true way of optimization would be move from hbitmap to 
some kind of sparse bitmap, where bitamp is devided into several blocks, 
and for each block we can store additional info like

- offset (link to data block in ram)

- present (offset is valid link to corresponding data block, otherwise, 
block is not allocated in ram)

- all zeros (data block is not needed, offset is ignored)

- all ones

- not loaded (for lazy persistent bitmap loading, we can load bitmap 
blocks on demand)

- changed (for persistent bitmaps - this block should be saved)

- etc..


-- 
Best regards,
Vladimir

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 05/17] dirty-bitmap: Change bdrv_dirty_bitmap_size() to report bytes
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 05/17] dirty-bitmap: Change bdrv_dirty_bitmap_size() to report bytes Eric Blake
@ 2017-07-10 21:09   ` John Snow
  2017-07-10 21:19     ` Eric Blake
  0 siblings, 1 reply; 38+ messages in thread
From: John Snow @ 2017-07-10 21:09 UTC (permalink / raw)
  To: Eric Blake, qemu-devel; +Cc: kwolf, Fam Zheng, qemu-block, Max Reitz



On 07/03/2017 11:10 AM, Eric Blake wrote:
> We are still using an internal hbitmap that tracks a size in sectors,
> with the granularity scaled down accordingly, because it lets us
> use a shortcut for our iterators which are currently sector-based.
> But there's no reason we can't track the dirty bitmap size in bytes,
> since it is (mostly) an internal-only variable (remember, the size
> is how many bytes are covered by the bitmap, not how many bytes the
> bitmap occupies).  Furthermore, we're already reporting bytes for
> bdrv_dirty_bitmap_granularity(); mixing bytes and sectors in our
> return values is a recipe for confusion.
> 
> The only external caller in qcow2-bitmap.c is temporarily more verbose
> (because it is still using sector-based math), but will later be
> switched to track progress by bytes instead of sectors.
> 
> Use is_power_of_2() while at it, instead of open-coding that.
> 
> Signed-off-by: Eric Blake <eblake@redhat.com>
> 
> ---
> v4: retitle from "Track size in bytes", rebase to persistent bitmaps,
> round up when converting bytes to sectors
> v3: no change
> v2: tweak commit message, no code change
> ---
>   block/dirty-bitmap.c | 25 +++++++++++++++----------
>   block/qcow2-bitmap.c | 14 ++++++++------
>   2 files changed, 23 insertions(+), 16 deletions(-)
> 
> diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
> index 42a55e4..3d8cfe6 100644
> --- a/block/dirty-bitmap.c
> +++ b/block/dirty-bitmap.c
> @@ -1,7 +1,7 @@
>   /*
>    * Block Dirty Bitmap
>    *
> - * Copyright (c) 2016 Red Hat. Inc
> + * Copyright (c) 2016-2017 Red Hat. Inc
>    *
>    * Permission is hereby granted, free of charge, to any person obtaining a copy
>    * of this software and associated documentation files (the "Software"), to deal
> @@ -42,7 +42,7 @@ struct BdrvDirtyBitmap {
>       HBitmap *meta;              /* Meta dirty bitmap */
>       BdrvDirtyBitmap *successor; /* Anonymous child; implies frozen status */
>       char *name;                 /* Optional non-empty unique ID */
> -    int64_t size;               /* Size of the bitmap (Number of sectors) */
> +    int64_t size;               /* Size of the bitmap, in bytes */
>       bool disabled;              /* Bitmap is disabled. It ignores all writes to
>                                      the device */
>       int active_iterators;       /* How many iterators are active */
> @@ -115,17 +115,14 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
>   {
>       int64_t bitmap_size;
>       BdrvDirtyBitmap *bitmap;
> -    uint32_t sector_granularity;
> 
> -    assert((granularity & (granularity - 1)) == 0);
> +    assert(is_power_of_2(granularity) && granularity >= BDRV_SECTOR_SIZE);
> 
>       if (name && bdrv_find_dirty_bitmap(bs, name)) {
>           error_setg(errp, "Bitmap already exists: %s", name);
>           return NULL;
>       }
> -    sector_granularity = granularity >> BDRV_SECTOR_BITS;
> -    assert(sector_granularity);
> -    bitmap_size = bdrv_nb_sectors(bs);
> +    bitmap_size = bdrv_getlength(bs);
>       if (bitmap_size < 0) {
>           error_setg_errno(errp, -bitmap_size, "could not get length of device");
>           errno = -bitmap_size;
> @@ -133,7 +130,12 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
>       }
>       bitmap = g_new0(BdrvDirtyBitmap, 1);
>       bitmap->mutex = &bs->dirty_bitmap_mutex;
> -    bitmap->bitmap = hbitmap_alloc(bitmap_size, ctz32(sector_granularity));
> +    /*
> +     * TODO - let hbitmap track full granularity. For now, it is tracking
> +     * only sector granularity, as a shortcut for our iterators.
> +     */
> +    bitmap->bitmap = hbitmap_alloc(DIV_ROUND_UP(bitmap_size, BDRV_SECTOR_SIZE),
> +                                   ctz32(granularity) - BDRV_SECTOR_BITS);
>       bitmap->size = bitmap_size;
>       bitmap->name = g_strdup(name);
>       bitmap->disabled = false;
> @@ -305,8 +307,10 @@ BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs,
>   void bdrv_dirty_bitmap_truncate(BlockDriverState *bs)
>   {
>       BdrvDirtyBitmap *bitmap;
> -    uint64_t size = bdrv_nb_sectors(bs);
> +    int64_t size = bdrv_getlength(bs);
> 
> +    assert(size >= 0);
> +    size = DIV_ROUND_UP(size, BDRV_SECTOR_SIZE);

Do we need a TODO here as well, or are we going to track these in terms 
of "sectors" permanently?

>       bdrv_dirty_bitmaps_lock(bs);
>       QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
>           assert(!bdrv_dirty_bitmap_frozen(bitmap));
> @@ -549,7 +553,8 @@ void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out)
>           hbitmap_reset_all(bitmap->bitmap);
>       } else {
>           HBitmap *backup = bitmap->bitmap;
> -        bitmap->bitmap = hbitmap_alloc(bitmap->size,
> +        bitmap->bitmap = hbitmap_alloc(DIV_ROUND_UP(bitmap->size,
> +                                                    BDRV_SECTOR_SIZE),
>                                          hbitmap_granularity(backup));
>           *out = backup;
>       }
> diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
> index 75ee238..f6f7770 100644
> --- a/block/qcow2-bitmap.c
> +++ b/block/qcow2-bitmap.c
> @@ -295,10 +295,11 @@ static int load_bitmap_data(BlockDriverState *bs,
>       BDRVQcow2State *s = bs->opaque;
>       uint64_t sector, sbc;
>       uint64_t bm_size = bdrv_dirty_bitmap_size(bitmap);
> +    uint64_t bm_sectors = DIV_ROUND_UP(bm_size, BDRV_SECTOR_SIZE);
>       uint8_t *buf = NULL;
>       uint64_t i, tab_size =
>               size_to_clusters(s,
> -                bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_size));
> +                bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_sectors));
> 
>       if (tab_size != bitmap_table_size || tab_size > BME_MAX_TABLE_SIZE) {
>           return -EINVAL;
> @@ -307,7 +308,7 @@ 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);
> +        uint64_t count = MIN(bm_sectors - sector, sbc);
>           uint64_t entry = bitmap_table[i];
>           uint64_t offset = entry & BME_TABLE_ENTRY_OFFSET_MASK;
> 
> @@ -1073,13 +1074,14 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
>       int64_t sector;
>       uint64_t sbc;
>       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;
>       uint64_t *tb;
>       uint64_t tb_size =
>               size_to_clusters(s,
> -                bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_size));
> +                bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_sectors));
> 
>       if (tb_size > BME_MAX_TABLE_SIZE ||
>           tb_size * s->cluster_size > BME_MAX_PHYS_SIZE)
> @@ -1097,7 +1099,7 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
>       dbi = bdrv_dirty_iter_new(bitmap, 0);
>       buf = g_malloc(s->cluster_size);
>       sbc = sectors_covered_by_bitmap_cluster(s, bitmap);
> -    assert(DIV_ROUND_UP(bm_size, sbc) == tb_size);
> +    assert(DIV_ROUND_UP(bm_sectors, sbc) == tb_size);
> 
>       while ((sector = bdrv_dirty_iter_next(dbi)) != -1) {
>           uint64_t cluster = sector / sbc;
> @@ -1105,7 +1107,7 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
>           int64_t off;
> 
>           sector = cluster * sbc;
> -        end = MIN(bm_size, sector + sbc);
> +        end = MIN(bm_sectors, sector + sbc);
>           write_size =
>               bdrv_dirty_bitmap_serialization_size(bitmap, sector, end - sector);
>           assert(write_size <= s->cluster_size);
> @@ -1137,7 +1139,7 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
>               goto fail;
>           }
> 
> -        if (end >= bm_size) {
> +        if (end >= bm_sectors) {
>               break;
>           }
> 

Reviewed-by: John Snow <jsnow@redhat.com>

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 05/17] dirty-bitmap: Change bdrv_dirty_bitmap_size() to report bytes
  2017-07-10 21:09   ` John Snow
@ 2017-07-10 21:19     ` Eric Blake
  2017-07-10 21:20       ` John Snow
  0 siblings, 1 reply; 38+ messages in thread
From: Eric Blake @ 2017-07-10 21:19 UTC (permalink / raw)
  To: John Snow, qemu-devel; +Cc: kwolf, Fam Zheng, qemu-block, Max Reitz

[-- Attachment #1: Type: text/plain, Size: 1834 bytes --]

On 07/10/2017 04:09 PM, John Snow wrote:
> 
> 
> On 07/03/2017 11:10 AM, Eric Blake wrote:
>> We are still using an internal hbitmap that tracks a size in sectors,
>> with the granularity scaled down accordingly, because it lets us
>> use a shortcut for our iterators which are currently sector-based.
>> But there's no reason we can't track the dirty bitmap size in bytes,
>> since it is (mostly) an internal-only variable (remember, the size
>> is how many bytes are covered by the bitmap, not how many bytes the
>> bitmap occupies).  Furthermore, we're already reporting bytes for
>> bdrv_dirty_bitmap_granularity(); mixing bytes and sectors in our
>> return values is a recipe for confusion.
>>
>> The only external caller in qcow2-bitmap.c is temporarily more verbose
>> (because it is still using sector-based math), but will later be
>> switched to track progress by bytes instead of sectors.
>>
>> Use is_power_of_2() while at it, instead of open-coding that.
>>
>> Signed-off-by: Eric Blake <eblake@redhat.com>
>>

>> @@ -305,8 +307,10 @@ BdrvDirtyBitmap
>> *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs,
>>   void bdrv_dirty_bitmap_truncate(BlockDriverState *bs)
>>   {
>>       BdrvDirtyBitmap *bitmap;
>> -    uint64_t size = bdrv_nb_sectors(bs);
>> +    int64_t size = bdrv_getlength(bs);
>>
>> +    assert(size >= 0);
>> +    size = DIV_ROUND_UP(size, BDRV_SECTOR_SIZE);
> 
> Do we need a TODO here as well, or are we going to track these in terms
> of "sectors" permanently?

The rounding goes away in patch 17/17 when I flip the internals to
byte-based.  If a TODO comment here (that goes away in patch 17) makes
review easier, I can add that.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 05/17] dirty-bitmap: Change bdrv_dirty_bitmap_size() to report bytes
  2017-07-10 21:19     ` Eric Blake
@ 2017-07-10 21:20       ` John Snow
  0 siblings, 0 replies; 38+ messages in thread
From: John Snow @ 2017-07-10 21:20 UTC (permalink / raw)
  To: Eric Blake, qemu-devel; +Cc: kwolf, Fam Zheng, qemu-block, Max Reitz



On 07/10/2017 05:19 PM, Eric Blake wrote:
> On 07/10/2017 04:09 PM, John Snow wrote:
>>
>>
>> On 07/03/2017 11:10 AM, Eric Blake wrote:
>>> We are still using an internal hbitmap that tracks a size in sectors,
>>> with the granularity scaled down accordingly, because it lets us
>>> use a shortcut for our iterators which are currently sector-based.
>>> But there's no reason we can't track the dirty bitmap size in bytes,
>>> since it is (mostly) an internal-only variable (remember, the size
>>> is how many bytes are covered by the bitmap, not how many bytes the
>>> bitmap occupies).  Furthermore, we're already reporting bytes for
>>> bdrv_dirty_bitmap_granularity(); mixing bytes and sectors in our
>>> return values is a recipe for confusion.
>>>
>>> The only external caller in qcow2-bitmap.c is temporarily more verbose
>>> (because it is still using sector-based math), but will later be
>>> switched to track progress by bytes instead of sectors.
>>>
>>> Use is_power_of_2() while at it, instead of open-coding that.
>>>
>>> Signed-off-by: Eric Blake <eblake@redhat.com>
>>>
> 
>>> @@ -305,8 +307,10 @@ BdrvDirtyBitmap
>>> *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs,
>>>    void bdrv_dirty_bitmap_truncate(BlockDriverState *bs)
>>>    {
>>>        BdrvDirtyBitmap *bitmap;
>>> -    uint64_t size = bdrv_nb_sectors(bs);
>>> +    int64_t size = bdrv_getlength(bs);
>>>
>>> +    assert(size >= 0);
>>> +    size = DIV_ROUND_UP(size, BDRV_SECTOR_SIZE);
>>
>> Do we need a TODO here as well, or are we going to track these in terms
>> of "sectors" permanently?
> 
> The rounding goes away in patch 17/17 when I flip the internals to
> byte-based.  If a TODO comment here (that goes away in patch 17) makes
> review easier, I can add that.
> 

Email confirmation is enough for me, personally.

--js

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 06/17] dirty-bitmap: Change bdrv_dirty_bitmap_*serialize*() to take bytes
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 06/17] dirty-bitmap: Change bdrv_dirty_bitmap_*serialize*() to take bytes Eric Blake
@ 2017-07-10 21:46   ` John Snow
  0 siblings, 0 replies; 38+ messages in thread
From: John Snow @ 2017-07-10 21:46 UTC (permalink / raw)
  To: Eric Blake, qemu-devel; +Cc: kwolf, Fam Zheng, qemu-block, Max Reitz



On 07/03/2017 11:10 AM, Eric Blake wrote:
> Right now, the dirty-bitmap code exposes the fact that we use
> a scale of sector granularity in the underlying hbitmap to anything
> that wants to serialize a dirty bitmap.  It's nicer to uniformly
> expose bytes as our dirty-bitmap interface, matching the previous
> change to bitmap size.  The only caller to serialization is currently
> qcow2-cluster.c, which becomes a bit more verbose because it is still
> tracking sectors for other reasons, but a later patch will fix that
> to more uniformly use byte offsets everywhere.  Likewise, within
> dirty-bitmap, we have to add more assertions that we are not
> truncating incorrectly, which can go away once the internal hbitmap
> is byte-based rather than sector-based.
> 
> Signed-off-by: Eric Blake <eblake@redhat.com>
> 

Reviewed-by: John Snow <jsnow@redhat.com>

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 07/17] qcow2: Switch sectors_covered_by_bitmap_cluster() to byte-based
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 07/17] qcow2: Switch sectors_covered_by_bitmap_cluster() to byte-based Eric Blake
@ 2017-07-10 22:54   ` John Snow
  0 siblings, 0 replies; 38+ messages in thread
From: John Snow @ 2017-07-10 22:54 UTC (permalink / raw)
  To: Eric Blake, qemu-devel; +Cc: kwolf, qemu-block, Max Reitz



On 07/03/2017 11:10 AM, Eric Blake wrote:
> We are gradually converting to byte-based interfaces, as they are
> easier to reason about than sector-based.  Change the qcow2 bitmap
> helper function sectors_covered_by_bitmap_cluster(), renaming it
> in the process.
> 
> Signed-off-by: Eric Blake <eblake@redhat.com>
> 

It really will be nice to not have multiple layers of scaling for 
bitmaps anymore.

Reviewed-by: John Snow <jsnow@redhat.com>

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 08/17] dirty-bitmap: Set iterator start by offset, not sector
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 08/17] dirty-bitmap: Set iterator start by offset, not sector Eric Blake
@ 2017-07-10 23:02   ` John Snow
  0 siblings, 0 replies; 38+ messages in thread
From: John Snow @ 2017-07-10 23:02 UTC (permalink / raw)
  To: Eric Blake, qemu-devel; +Cc: kwolf, Fam Zheng, qemu-block, Jeff Cody, Max Reitz



On 07/03/2017 11:10 AM, Eric Blake wrote:
> All callers to bdrv_dirty_iter_new() passed 0 for their initial
> starting point, drop that parameter.
> 
> Most callers to bdrv_set_dirty_iter() were scaling a byte offset to
> a sector number; the exception qcow2-bitmap will be converted later
> to use byte rather than sector iteration.  Move the scaling to occur
> internally to dirty bitmap code instead, so that callers now pass
> in bytes.
> 
> Signed-off-by: Eric Blake <eblake@redhat.com>

Reviewed-by: John Snow <jsnow@redhat.com>

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 09/17] dirty-bitmap: Change bdrv_dirty_iter_next() to report byte offset
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 09/17] dirty-bitmap: Change bdrv_dirty_iter_next() to report byte offset Eric Blake
@ 2017-07-10 23:20   ` John Snow
  2017-07-11 16:50   ` Eric Blake
  1 sibling, 0 replies; 38+ messages in thread
From: John Snow @ 2017-07-10 23:20 UTC (permalink / raw)
  To: Eric Blake, qemu-devel; +Cc: kwolf, Fam Zheng, qemu-block, Jeff Cody, Max Reitz



On 07/03/2017 11:10 AM, Eric Blake wrote:
> Thanks to recent cleanups, most callers were scaling a return value
> of sectors into bytes (the exception, in qcow2-bitmap, will be
> converted to byte-based iteration later).  Update the interface to
> do the scaling internally instead.
> 
> Signed-off-by: Eric Blake <eblake@redhat.com>
> 

Reviewed-By: John Snow <jsnow@redhat.com>

I still think about getting Arby's when I write that line, and now I'm 
hungry.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 09/17] dirty-bitmap: Change bdrv_dirty_iter_next() to report byte offset
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 09/17] dirty-bitmap: Change bdrv_dirty_iter_next() to report byte offset Eric Blake
  2017-07-10 23:20   ` John Snow
@ 2017-07-11 16:50   ` Eric Blake
  1 sibling, 0 replies; 38+ messages in thread
From: Eric Blake @ 2017-07-11 16:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, Fam Zheng, qemu-block, Jeff Cody, Max Reitz, jsnow

[-- Attachment #1: Type: text/plain, Size: 1501 bytes --]

On 07/03/2017 10:10 AM, Eric Blake wrote:
> Thanks to recent cleanups, most callers were scaling a return value
> of sectors into bytes (the exception, in qcow2-bitmap, will be
> converted to byte-based iteration later).  Update the interface to
> do the scaling internally instead.
> 
> Signed-off-by: Eric Blake <eblake@redhat.com>

> @@ -506,7 +506,7 @@ void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter)
> 
>  int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter)
>  {
> -    return hbitmap_iter_next(&iter->hbi);
> +    return hbitmap_iter_next(&iter->hbi) * BDRV_SECTOR_SIZE;
>  }
> 

> +++ b/block/qcow2-bitmap.c
> @@ -1105,7 +1105,7 @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
>      sbc = limit >> BDRV_SECTOR_BITS;
>      assert(DIV_ROUND_UP(bm_size, limit) == tb_size);
> 
> -    while ((sector = bdrv_dirty_iter_next(dbi)) != -1) {
> +    while ((sector = bdrv_dirty_iter_next(dbi) >> BDRV_SECTOR_BITS) != -1) {

Does clang's sanitizer complain about right shift of a negative number,
or is that one of the things that we can rely on even though C says it
is not strictly portable?  If it is a problem, I can always split the
check for bdrv_dirty_iter_next()<0 to occur separately from the while()
conditional; but I'd rather not go through with the churn unless it
actually chokes a build-bot as written.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 12/17] dirty-bitmap: Change bdrv_[re]set_dirty_bitmap() to use bytes
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 12/17] dirty-bitmap: Change bdrv_[re]set_dirty_bitmap() to use bytes Eric Blake
@ 2017-07-12 19:25   ` John Snow
  0 siblings, 0 replies; 38+ messages in thread
From: John Snow @ 2017-07-12 19:25 UTC (permalink / raw)
  To: Eric Blake, qemu-devel
  Cc: kwolf, Fam Zheng, qemu-block, Juan Quintela, Jeff Cody,
	Dr. David Alan Gilbert, Max Reitz, Stefan Hajnoczi



On 07/03/2017 11:10 AM, Eric Blake wrote:
> Some of the callers were already scaling bytes to sectors; others
> can be easily converted to pass byte offsets, all in our shift
> towards a consistent byte interface everywhere.  Making the change
> will also make it easier to write the hold-out callers to use byte
> rather than sectors for their iterations; it also makes it easier
> for a future dirty-bitmap patch to offload scaling over to the
> internal hbitmap.  Although all callers happen to pass
> sector-aligned values, make the internal scaling robust to any
> sub-sector requests.
> 
> Signed-off-by: Eric Blake <eblake@redhat.com>
> 

Reviewed-by: John Snow <jsnow@redhat.com>

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 14/17] qcow2: Switch load_bitmap_data() to byte-based iteration
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 14/17] qcow2: Switch load_bitmap_data() " Eric Blake
@ 2017-07-12 20:15   ` John Snow
  2017-07-13  9:16   ` Vladimir Sementsov-Ogievskiy
  1 sibling, 0 replies; 38+ messages in thread
From: John Snow @ 2017-07-12 20:15 UTC (permalink / raw)
  To: Eric Blake, qemu-devel
  Cc: kwolf, qemu-block, Max Reitz, Vladimir Sementsov-Ogievskiy



On 07/03/2017 11:10 AM, Eric Blake wrote:
> Now that we have adjusted the majority of the calls this function
> makes to be byte-based, it is easier to read the code if it makes
> passes over the image using bytes rather than sectors.
> 
> Signed-off-by: Eric Blake <eblake@redhat.com>
> 

Reviewed-by: John Snow <jsnow@redhat.com>

Vladimir, look good to you?

--js

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 15/17] qcow2: Switch store_bitmap_data() to byte-based iteration
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 15/17] qcow2: Switch store_bitmap_data() " Eric Blake
@ 2017-07-12 20:28   ` John Snow
  0 siblings, 0 replies; 38+ messages in thread
From: John Snow @ 2017-07-12 20:28 UTC (permalink / raw)
  To: Eric Blake, qemu-devel
  Cc: kwolf, qemu-block, Max Reitz, Vladimir Sementsov-Ogievskiy



On 07/03/2017 11:10 AM, Eric Blake wrote:
> Now that we have adjusted the majority of the calls this function
> makes to be byte-based, it is easier to read the code if it makes
> passes over the image using bytes rather than sectors.
> 
> Signed-off-by: Eric Blake <eblake@redhat.com>
> 

Reviewed-by: John Snow <jsnow@redhat.com>

Vladimir, yea/nay?

--js

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 17/17] dirty-bitmap: Convert internal hbitmap size/granularity
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 17/17] dirty-bitmap: Convert internal hbitmap size/granularity Eric Blake
@ 2017-07-12 21:00   ` John Snow
  2017-07-12 21:25     ` Eric Blake
  0 siblings, 1 reply; 38+ messages in thread
From: John Snow @ 2017-07-12 21:00 UTC (permalink / raw)
  To: Eric Blake, qemu-devel; +Cc: kwolf, Fam Zheng, qemu-block, Max Reitz



On 07/03/2017 11:10 AM, Eric Blake wrote:
> Now that all callers are using byte-based interfaces, there's no
> reason for our internal hbitmap to remain with sector-based
> granularity.  It also simplifies our internal scaling, since we
> already know that hbitmap widens requests out to granularity
> boundaries.
> 
> Signed-off-by: Eric Blake <eblake@redhat.com>
> 
> ---
> v4: rebase to earlier changes, include serialization, R-b dropped
> v3: no change
> v2: no change
> ---
>  block/dirty-bitmap.c | 60 +++++++++++++++-------------------------------------
>  1 file changed, 17 insertions(+), 43 deletions(-)
> 
> diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
> index 5bfc7bc..0b349f0 100644
> --- a/block/dirty-bitmap.c
> +++ b/block/dirty-bitmap.c
> @@ -38,7 +38,7 @@
>   */
>  struct BdrvDirtyBitmap {
>      QemuMutex *mutex;
> -    HBitmap *bitmap;            /* Dirty sector bitmap implementation */
> +    HBitmap *bitmap;            /* Dirty bitmap implementation */
>      HBitmap *meta;              /* Meta dirty bitmap */
>      BdrvDirtyBitmap *successor; /* Anonymous child; implies frozen status */
>      char *name;                 /* Optional non-empty unique ID */
> @@ -130,12 +130,7 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
>      }
>      bitmap = g_new0(BdrvDirtyBitmap, 1);
>      bitmap->mutex = &bs->dirty_bitmap_mutex;
> -    /*
> -     * TODO - let hbitmap track full granularity. For now, it is tracking
> -     * only sector granularity, as a shortcut for our iterators.
> -     */
> -    bitmap->bitmap = hbitmap_alloc(DIV_ROUND_UP(bitmap_size, BDRV_SECTOR_SIZE),
> -                                   ctz32(granularity) - BDRV_SECTOR_BITS);
> +    bitmap->bitmap = hbitmap_alloc(bitmap_size, ctz32(granularity));
>      bitmap->size = bitmap_size;
>      bitmap->name = g_strdup(name);
>      bitmap->disabled = false;
> @@ -310,7 +305,6 @@ void bdrv_dirty_bitmap_truncate(BlockDriverState *bs)
>      int64_t size = bdrv_getlength(bs);
> 
>      assert(size >= 0);
> -    size = DIV_ROUND_UP(size, BDRV_SECTOR_SIZE);

whoops uh, were we setting bitmap->size to the *sector* size prior to
this, even though we had already changed bitmap->size to be the byte size?

--js

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 17/17] dirty-bitmap: Convert internal hbitmap size/granularity
  2017-07-12 21:00   ` John Snow
@ 2017-07-12 21:25     ` Eric Blake
  0 siblings, 0 replies; 38+ messages in thread
From: Eric Blake @ 2017-07-12 21:25 UTC (permalink / raw)
  To: John Snow, qemu-devel; +Cc: kwolf, Fam Zheng, qemu-block, Max Reitz

[-- Attachment #1: Type: text/plain, Size: 1025 bytes --]

On 07/12/2017 04:00 PM, John Snow wrote:
> 
> 
> On 07/03/2017 11:10 AM, Eric Blake wrote:
>> Now that all callers are using byte-based interfaces, there's no
>> reason for our internal hbitmap to remain with sector-based
>> granularity.  It also simplifies our internal scaling, since we
>> already know that hbitmap widens requests out to granularity
>> boundaries.
>>
>> Signed-off-by: Eric Blake <eblake@redhat.com>
>>

>> @@ -310,7 +305,6 @@ void bdrv_dirty_bitmap_truncate(BlockDriverState *bs)
>>      int64_t size = bdrv_getlength(bs);
>>
>>      assert(size >= 0);
>> -    size = DIV_ROUND_UP(size, BDRV_SECTOR_SIZE);
> 
> whoops uh, were we setting bitmap->size to the *sector* size prior to
> this, even though we had already changed bitmap->size to be the byte size?

Oops. Looks like I have a bug in my rebasing of 5/17.  Good catch; I'll
have to post v5.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 14/17] qcow2: Switch load_bitmap_data() to byte-based iteration
  2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 14/17] qcow2: Switch load_bitmap_data() " Eric Blake
  2017-07-12 20:15   ` John Snow
@ 2017-07-13  9:16   ` Vladimir Sementsov-Ogievskiy
  2017-07-13 10:59     ` Eric Blake
  1 sibling, 1 reply; 38+ messages in thread
From: Vladimir Sementsov-Ogievskiy @ 2017-07-13  9:16 UTC (permalink / raw)
  To: Eric Blake, qemu-devel; +Cc: kwolf, jsnow, qemu-block, Max Reitz

03.07.2017 18:10, Eric Blake wrote:
> Now that we have adjusted the majority of the calls this function
> makes to be byte-based, it is easier to read the code if it makes
> passes over the image using bytes rather than sectors.
>
> Signed-off-by: Eric Blake <eblake@redhat.com>
>
> ---
> v4: new patch
> ---
>   block/qcow2-bitmap.c | 22 ++++++++--------------
>   1 file changed, 8 insertions(+), 14 deletions(-)
>
> diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
> index 280960a..1de2ab5 100644
> --- a/block/qcow2-bitmap.c
> +++ b/block/qcow2-bitmap.c
> @@ -291,9 +291,8 @@ static int load_bitmap_data(BlockDriverState *bs,
>   {
>       int ret = 0;
>       BDRVQcow2State *s = bs->opaque;
> -    uint64_t sector, limit, sbc;
> +    uint64_t offset, limit;
>       uint64_t bm_size = bdrv_dirty_bitmap_size(bitmap);
> -    uint64_t bm_sectors = DIV_ROUND_UP(bm_size, BDRV_SECTOR_SIZE);
>       uint8_t *buf = NULL;
>       uint64_t i, tab_size =
>               size_to_clusters(s,
> @@ -305,32 +304,27 @@ static int load_bitmap_data(BlockDriverState *bs,
>
>       buf = g_malloc(s->cluster_size);
>       limit = bytes_covered_by_bitmap_cluster(s, bitmap);
> -    sbc = limit >> BDRV_SECTOR_BITS;
> -    for (i = 0, sector = 0; i < tab_size; ++i, sector += sbc) {
> -        uint64_t count = MIN(bm_sectors - sector, sbc);
> +    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 * BDRV_SECTOR_SIZE,
> -                                                   count * BDRV_SECTOR_SIZE,
> +                bdrv_dirty_bitmap_deserialize_ones(bitmap, offset, count,

The change is that now 3rd parameter may not be aligned by sectors, but 
looks like it should be ok.

Reviewed-by: Vladimir Sementsov-Ogievskiy<vsementsov@virtuozzo.com>



>                                                      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 * BDRV_SECTOR_SIZE,
> -                                               count * BDRV_SECTOR_SIZE,
> +            bdrv_dirty_bitmap_deserialize_part(bitmap, buf, offset, count,
>                                                  false);
>           }
>       }


-- 
Best regards,
Vladimir

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [PATCH v4 14/17] qcow2: Switch load_bitmap_data() to byte-based iteration
  2017-07-13  9:16   ` Vladimir Sementsov-Ogievskiy
@ 2017-07-13 10:59     ` Eric Blake
  0 siblings, 0 replies; 38+ messages in thread
From: Eric Blake @ 2017-07-13 10:59 UTC (permalink / raw)
  To: Vladimir Sementsov-Ogievskiy, qemu-devel
  Cc: kwolf, jsnow, qemu-block, Max Reitz

[-- Attachment #1: Type: text/plain, Size: 1495 bytes --]

On 07/13/2017 04:16 AM, Vladimir Sementsov-Ogievskiy wrote:
> 03.07.2017 18:10, Eric Blake wrote:
>> Now that we have adjusted the majority of the calls this function
>> makes to be byte-based, it is easier to read the code if it makes
>> passes over the image using bytes rather than sectors.
>>
>> Signed-off-by: Eric Blake <eblake@redhat.com>
>>
>> ---
>> v4: new patch
>> ---

>>
>> -        if (offset == 0) {
>> +        if (data_offset == 0) {
>>               if (entry & BME_TABLE_ENTRY_FLAG_ALL_ONES) {
>> -                bdrv_dirty_bitmap_deserialize_ones(bitmap,
>> -                                                   sector *
>> BDRV_SECTOR_SIZE,
>> -                                                   count *
>> BDRV_SECTOR_SIZE,
>> +                bdrv_dirty_bitmap_deserialize_ones(bitmap, offset,
>> count,
> 
> The change is that now 3rd parameter may not be aligned by sectors, but
> looks like it should be ok.

Correct - the dirty bitmap automatically widens any non-aligned input
into granularity.

> 
> Reviewed-by: Vladimir Sementsov-Ogievskiy<vsementsov@virtuozzo.com>
> 

I posted a v5 prior to this email, if you want to add your Reviewed-by
on any patches there (I think this patch went unchanged into that
revision, but scripts don't always pick up R-b given on a previous
version of a patch).

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

end of thread, other threads:[~2017-07-13 10:59 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-07-03 15:10 [Qemu-devel] [PATCH v4 00/17] make dirty-bitmap byte-based Eric Blake
2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 01/17] dirty-bitmap: Report BlockDirtyInfo.count in bytes, as documented Eric Blake
2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 02/17] hbitmap: Rename serialization_granularity to serialization_align Eric Blake
2017-07-06 23:03   ` John Snow
2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 03/17] qcow2: Ensure bitmap serialization is aligned Eric Blake
2017-07-06 23:14   ` John Snow
2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 04/17] dirty-bitmap: Drop unused functions Eric Blake
2017-07-06 23:43   ` John Snow
2017-07-07  8:44     ` Vladimir Sementsov-Ogievskiy
2017-07-07 13:05       ` Vladimir Sementsov-Ogievskiy
2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 05/17] dirty-bitmap: Change bdrv_dirty_bitmap_size() to report bytes Eric Blake
2017-07-10 21:09   ` John Snow
2017-07-10 21:19     ` Eric Blake
2017-07-10 21:20       ` John Snow
2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 06/17] dirty-bitmap: Change bdrv_dirty_bitmap_*serialize*() to take bytes Eric Blake
2017-07-10 21:46   ` John Snow
2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 07/17] qcow2: Switch sectors_covered_by_bitmap_cluster() to byte-based Eric Blake
2017-07-10 22:54   ` John Snow
2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 08/17] dirty-bitmap: Set iterator start by offset, not sector Eric Blake
2017-07-10 23:02   ` John Snow
2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 09/17] dirty-bitmap: Change bdrv_dirty_iter_next() to report byte offset Eric Blake
2017-07-10 23:20   ` John Snow
2017-07-11 16:50   ` Eric Blake
2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 10/17] dirty-bitmap: Change bdrv_get_dirty_count() to report bytes Eric Blake
2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 11/17] dirty-bitmap: Change bdrv_get_dirty_locked() to take bytes Eric Blake
2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 12/17] dirty-bitmap: Change bdrv_[re]set_dirty_bitmap() to use bytes Eric Blake
2017-07-12 19:25   ` John Snow
2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 13/17] mirror: Switch mirror_dirty_init() to byte-based iteration Eric Blake
2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 14/17] qcow2: Switch load_bitmap_data() " Eric Blake
2017-07-12 20:15   ` John Snow
2017-07-13  9:16   ` Vladimir Sementsov-Ogievskiy
2017-07-13 10:59     ` Eric Blake
2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 15/17] qcow2: Switch store_bitmap_data() " Eric Blake
2017-07-12 20:28   ` John Snow
2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 16/17] dirty-bitmap: Switch bdrv_set_dirty() to bytes Eric Blake
2017-07-03 15:10 ` [Qemu-devel] [PATCH v4 17/17] dirty-bitmap: Convert internal hbitmap size/granularity Eric Blake
2017-07-12 21:00   ` John Snow
2017-07-12 21:25     ` Eric Blake

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.