|
|
7711c0 |
From 31e5ab1930795584338fe2769a002b31c89c04b6 Mon Sep 17 00:00:00 2001
|
|
|
7711c0 |
From: John Snow <jsnow@redhat.com>
|
|
|
7711c0 |
Date: Wed, 20 Mar 2019 21:48:29 +0100
|
|
|
7711c0 |
Subject: [PATCH 036/163] dirty-bitmap: improve bdrv_dirty_bitmap_next_zero
|
|
|
7711c0 |
|
|
|
7711c0 |
RH-Author: John Snow <jsnow@redhat.com>
|
|
|
7711c0 |
Message-id: <20190320214838.22027-2-jsnow@redhat.com>
|
|
|
7711c0 |
Patchwork-id: 84993
|
|
|
7711c0 |
O-Subject: [RHEL-7.7 qemu-kvm-rhev PATCH 01/10] dirty-bitmap: improve bdrv_dirty_bitmap_next_zero
|
|
|
7711c0 |
Bugzilla: 1691048
|
|
|
7711c0 |
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
7711c0 |
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
|
|
7711c0 |
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
7711c0 |
|
|
|
7711c0 |
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
|
7711c0 |
|
|
|
7711c0 |
Add bytes parameter to the function, to limit searched range.
|
|
|
7711c0 |
|
|
|
7711c0 |
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
|
7711c0 |
(cherry picked from commit 76d570dc495c56bbdcc4574bfc6d512dcb8e9aa9)
|
|
|
7711c0 |
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
|
7711c0 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
7711c0 |
---
|
|
|
7711c0 |
block/backup.c | 3 ++-
|
|
|
7711c0 |
block/dirty-bitmap.c | 5 +++--
|
|
|
7711c0 |
include/block/dirty-bitmap.h | 3 ++-
|
|
|
7711c0 |
include/qemu/hbitmap.h | 10 +++++++---
|
|
|
7711c0 |
nbd/server.c | 2 +-
|
|
|
7711c0 |
tests/test-hbitmap.c | 2 +-
|
|
|
7711c0 |
util/hbitmap.c | 27 ++++++++++++++++++++++-----
|
|
|
7711c0 |
7 files changed, 38 insertions(+), 14 deletions(-)
|
|
|
7711c0 |
|
|
|
7711c0 |
diff --git a/block/backup.c b/block/backup.c
|
|
|
7711c0 |
index ac17db6..6a66b1c 100644
|
|
|
7711c0 |
--- a/block/backup.c
|
|
|
7711c0 |
+++ b/block/backup.c
|
|
|
7711c0 |
@@ -446,7 +446,8 @@ static void backup_incremental_init_copy_bitmap(BackupBlockJob *job)
|
|
|
7711c0 |
break;
|
|
|
7711c0 |
}
|
|
|
7711c0 |
|
|
|
7711c0 |
- offset = bdrv_dirty_bitmap_next_zero(job->sync_bitmap, offset);
|
|
|
7711c0 |
+ offset = bdrv_dirty_bitmap_next_zero(job->sync_bitmap, offset,
|
|
|
7711c0 |
+ UINT64_MAX);
|
|
|
7711c0 |
if (offset == -1) {
|
|
|
7711c0 |
hbitmap_set(job->copy_bitmap, cluster, end - cluster);
|
|
|
7711c0 |
break;
|
|
|
7711c0 |
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
|
|
|
7711c0 |
index 6b68839..b162f4a 100644
|
|
|
7711c0 |
--- a/block/dirty-bitmap.c
|
|
|
7711c0 |
+++ b/block/dirty-bitmap.c
|
|
|
7711c0 |
@@ -781,9 +781,10 @@ char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp)
|
|
|
7711c0 |
return hbitmap_sha256(bitmap->bitmap, errp);
|
|
|
7711c0 |
}
|
|
|
7711c0 |
|
|
|
7711c0 |
-int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t offset)
|
|
|
7711c0 |
+int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t offset,
|
|
|
7711c0 |
+ uint64_t bytes)
|
|
|
7711c0 |
{
|
|
|
7711c0 |
- return hbitmap_next_zero(bitmap->bitmap, offset);
|
|
|
7711c0 |
+ return hbitmap_next_zero(bitmap->bitmap, offset, bytes);
|
|
|
7711c0 |
}
|
|
|
7711c0 |
|
|
|
7711c0 |
void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src,
|
|
|
7711c0 |
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
|
|
|
7711c0 |
index 8f38a3d..102ccdd 100644
|
|
|
7711c0 |
--- a/include/block/dirty-bitmap.h
|
|
|
7711c0 |
+++ b/include/block/dirty-bitmap.h
|
|
|
7711c0 |
@@ -99,7 +99,8 @@ bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs);
|
|
|
7711c0 |
BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs,
|
|
|
7711c0 |
BdrvDirtyBitmap *bitmap);
|
|
|
7711c0 |
char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp);
|
|
|
7711c0 |
-int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t start);
|
|
|
7711c0 |
+int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t offset,
|
|
|
7711c0 |
+ uint64_t bytes);
|
|
|
7711c0 |
BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap_locked(BlockDriverState *bs,
|
|
|
7711c0 |
BdrvDirtyBitmap *bitmap,
|
|
|
7711c0 |
Error **errp);
|
|
|
7711c0 |
diff --git a/include/qemu/hbitmap.h b/include/qemu/hbitmap.h
|
|
|
7711c0 |
index a7cb780..1359755 100644
|
|
|
7711c0 |
--- a/include/qemu/hbitmap.h
|
|
|
7711c0 |
+++ b/include/qemu/hbitmap.h
|
|
|
7711c0 |
@@ -300,12 +300,16 @@ void hbitmap_iter_init(HBitmapIter *hbi, const HBitmap *hb, uint64_t first);
|
|
|
7711c0 |
unsigned long hbitmap_iter_skip_words(HBitmapIter *hbi);
|
|
|
7711c0 |
|
|
|
7711c0 |
/* hbitmap_next_zero:
|
|
|
7711c0 |
+ *
|
|
|
7711c0 |
+ * Find next not dirty bit within selected range. If not found, return -1.
|
|
|
7711c0 |
+ *
|
|
|
7711c0 |
* @hb: The HBitmap to operate on
|
|
|
7711c0 |
* @start: The bit to start from.
|
|
|
7711c0 |
- *
|
|
|
7711c0 |
- * Find next not dirty bit.
|
|
|
7711c0 |
+ * @count: Number of bits to proceed. If @start+@count > bitmap size, the whole
|
|
|
7711c0 |
+ * bitmap is looked through. You can use UINT64_MAX as @count to search up to
|
|
|
7711c0 |
+ * the bitmap end.
|
|
|
7711c0 |
*/
|
|
|
7711c0 |
-int64_t hbitmap_next_zero(const HBitmap *hb, uint64_t start);
|
|
|
7711c0 |
+int64_t hbitmap_next_zero(const HBitmap *hb, uint64_t start, uint64_t count);
|
|
|
7711c0 |
|
|
|
7711c0 |
/* hbitmap_create_meta:
|
|
|
7711c0 |
* Create a "meta" hbitmap to track dirtiness of the bits in this HBitmap.
|
|
|
7711c0 |
diff --git a/nbd/server.c b/nbd/server.c
|
|
|
7711c0 |
index e094300..0ab0dbd 100644
|
|
|
7711c0 |
--- a/nbd/server.c
|
|
|
7711c0 |
+++ b/nbd/server.c
|
|
|
7711c0 |
@@ -1952,7 +1952,7 @@ static unsigned int bitmap_to_extents(BdrvDirtyBitmap *bitmap, uint64_t offset,
|
|
|
7711c0 |
assert(begin < overall_end && nb_extents);
|
|
|
7711c0 |
while (begin < overall_end && i < nb_extents) {
|
|
|
7711c0 |
if (dirty) {
|
|
|
7711c0 |
- end = bdrv_dirty_bitmap_next_zero(bitmap, begin);
|
|
|
7711c0 |
+ end = bdrv_dirty_bitmap_next_zero(bitmap, begin, UINT64_MAX);
|
|
|
7711c0 |
} else {
|
|
|
7711c0 |
bdrv_set_dirty_iter(it, begin);
|
|
|
7711c0 |
end = bdrv_dirty_iter_next(it);
|
|
|
7711c0 |
diff --git a/tests/test-hbitmap.c b/tests/test-hbitmap.c
|
|
|
7711c0 |
index 5e67ac1..b04a45a 100644
|
|
|
7711c0 |
--- a/tests/test-hbitmap.c
|
|
|
7711c0 |
+++ b/tests/test-hbitmap.c
|
|
|
7711c0 |
@@ -939,7 +939,7 @@ static void test_hbitmap_iter_and_reset(TestHBitmapData *data,
|
|
|
7711c0 |
|
|
|
7711c0 |
static void test_hbitmap_next_zero_check(TestHBitmapData *data, int64_t start)
|
|
|
7711c0 |
{
|
|
|
7711c0 |
- int64_t ret1 = hbitmap_next_zero(data->hb, start);
|
|
|
7711c0 |
+ int64_t ret1 = hbitmap_next_zero(data->hb, start, UINT64_MAX);
|
|
|
7711c0 |
int64_t ret2 = start;
|
|
|
7711c0 |
for ( ; ret2 < data->size && hbitmap_get(data->hb, ret2); ret2++) {
|
|
|
7711c0 |
;
|
|
|
7711c0 |
diff --git a/util/hbitmap.c b/util/hbitmap.c
|
|
|
7711c0 |
index 8d402c5..09b3719 100644
|
|
|
7711c0 |
--- a/util/hbitmap.c
|
|
|
7711c0 |
+++ b/util/hbitmap.c
|
|
|
7711c0 |
@@ -53,6 +53,9 @@
|
|
|
7711c0 |
*/
|
|
|
7711c0 |
|
|
|
7711c0 |
struct HBitmap {
|
|
|
7711c0 |
+ /* Size of the bitmap, as requested in hbitmap_alloc. */
|
|
|
7711c0 |
+ uint64_t orig_size;
|
|
|
7711c0 |
+
|
|
|
7711c0 |
/* Number of total bits in the bottom level. */
|
|
|
7711c0 |
uint64_t size;
|
|
|
7711c0 |
|
|
|
7711c0 |
@@ -192,16 +195,28 @@ void hbitmap_iter_init(HBitmapIter *hbi, const HBitmap *hb, uint64_t first)
|
|
|
7711c0 |
}
|
|
|
7711c0 |
}
|
|
|
7711c0 |
|
|
|
7711c0 |
-int64_t hbitmap_next_zero(const HBitmap *hb, uint64_t start)
|
|
|
7711c0 |
+int64_t hbitmap_next_zero(const HBitmap *hb, uint64_t start, uint64_t count)
|
|
|
7711c0 |
{
|
|
|
7711c0 |
size_t pos = (start >> hb->granularity) >> BITS_PER_LEVEL;
|
|
|
7711c0 |
unsigned long *last_lev = hb->levels[HBITMAP_LEVELS - 1];
|
|
|
7711c0 |
- uint64_t sz = hb->sizes[HBITMAP_LEVELS - 1];
|
|
|
7711c0 |
unsigned long cur = last_lev[pos];
|
|
|
7711c0 |
- unsigned start_bit_offset =
|
|
|
7711c0 |
- (start >> hb->granularity) & (BITS_PER_LONG - 1);
|
|
|
7711c0 |
+ unsigned start_bit_offset;
|
|
|
7711c0 |
+ uint64_t end_bit, sz;
|
|
|
7711c0 |
int64_t res;
|
|
|
7711c0 |
|
|
|
7711c0 |
+ if (start >= hb->orig_size || count == 0) {
|
|
|
7711c0 |
+ return -1;
|
|
|
7711c0 |
+ }
|
|
|
7711c0 |
+
|
|
|
7711c0 |
+ end_bit = count > hb->orig_size - start ?
|
|
|
7711c0 |
+ hb->size :
|
|
|
7711c0 |
+ ((start + count - 1) >> hb->granularity) + 1;
|
|
|
7711c0 |
+ sz = (end_bit + BITS_PER_LONG - 1) >> BITS_PER_LEVEL;
|
|
|
7711c0 |
+
|
|
|
7711c0 |
+ /* There may be some zero bits in @cur before @start. We are not interested
|
|
|
7711c0 |
+ * in them, let's set them.
|
|
|
7711c0 |
+ */
|
|
|
7711c0 |
+ start_bit_offset = (start >> hb->granularity) & (BITS_PER_LONG - 1);
|
|
|
7711c0 |
cur |= (1UL << start_bit_offset) - 1;
|
|
|
7711c0 |
assert((start >> hb->granularity) < hb->size);
|
|
|
7711c0 |
|
|
|
7711c0 |
@@ -218,7 +233,7 @@ int64_t hbitmap_next_zero(const HBitmap *hb, uint64_t start)
|
|
|
7711c0 |
}
|
|
|
7711c0 |
|
|
|
7711c0 |
res = (pos << BITS_PER_LEVEL) + ctol(cur);
|
|
|
7711c0 |
- if (res >= hb->size) {
|
|
|
7711c0 |
+ if (res >= end_bit) {
|
|
|
7711c0 |
return -1;
|
|
|
7711c0 |
}
|
|
|
7711c0 |
|
|
|
7711c0 |
@@ -652,6 +667,8 @@ HBitmap *hbitmap_alloc(uint64_t size, int granularity)
|
|
|
7711c0 |
HBitmap *hb = g_new0(struct HBitmap, 1);
|
|
|
7711c0 |
unsigned i;
|
|
|
7711c0 |
|
|
|
7711c0 |
+ hb->orig_size = size;
|
|
|
7711c0 |
+
|
|
|
7711c0 |
assert(granularity >= 0 && granularity < 64);
|
|
|
7711c0 |
size = (size + (1ULL << granularity) - 1) >> granularity;
|
|
|
7711c0 |
assert(size <= ((uint64_t)1 << HBITMAP_LOG_MAX_SIZE));
|
|
|
7711c0 |
--
|
|
|
7711c0 |
1.8.3.1
|
|
|
7711c0 |
|