From f63ea4e92bad1dbad58b198f51ac48657c1facbd Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Wed, 28 Jun 2017 15:05:03 +0300 Subject: hbitmap: improve dirty iter Make dirty iter resistant to resetting bits in corresponding HBitmap. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Max Reitz Reviewed-by: John Snow Message-id: 20170628120530.31251-4-vsementsov@virtuozzo.com Signed-off-by: Max Reitz --- util/hbitmap.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'util') diff --git a/util/hbitmap.c b/util/hbitmap.c index 35088e1..0b38817 100644 --- a/util/hbitmap.c +++ b/util/hbitmap.c @@ -106,8 +106,9 @@ unsigned long hbitmap_iter_skip_words(HBitmapIter *hbi) unsigned long cur; do { - cur = hbi->cur[--i]; + i--; pos >>= BITS_PER_LEVEL; + cur = hbi->cur[i] & hb->levels[i][pos]; } while (cur == 0); /* Check for end of iteration. We always use fewer than BITS_PER_LONG @@ -139,6 +140,26 @@ unsigned long hbitmap_iter_skip_words(HBitmapIter *hbi) return cur; } +int64_t hbitmap_iter_next(HBitmapIter *hbi) +{ + unsigned long cur = hbi->cur[HBITMAP_LEVELS - 1] & + hbi->hb->levels[HBITMAP_LEVELS - 1][hbi->pos]; + int64_t item; + + if (cur == 0) { + cur = hbitmap_iter_skip_words(hbi); + if (cur == 0) { + return -1; + } + } + + /* The next call will resume work from the next bit. */ + hbi->cur[HBITMAP_LEVELS - 1] = cur & (cur - 1); + item = ((uint64_t)hbi->pos << BITS_PER_LEVEL) + ctzl(cur); + + return item << hbi->granularity; +} + void hbitmap_iter_init(HBitmapIter *hbi, const HBitmap *hb, uint64_t first) { unsigned i, bit; -- cgit v1.1