diff options
author | Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 2017-10-12 16:53:09 +0300 |
---|---|---|
committer | Jeff Cody <jcody@redhat.com> | 2017-12-18 10:54:13 -0500 |
commit | 56207df55ea546f3e72578a5920e68a346440b1a (patch) | |
tree | f3402035ecf937a994f7567663c54408e66939bf /util/hbitmap.c | |
parent | 411ad78115ebeb3411cf4b7622784b93dfabe259 (diff) |
hbitmap: add next_zero function
The function searches for next zero bit.
Also add interface for BdrvDirtyBitmap and unit test.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: 20171012135313.227864-2-vsementsov@virtuozzo.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
Diffstat (limited to 'util/hbitmap.c')
-rw-r--r-- | util/hbitmap.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/util/hbitmap.c b/util/hbitmap.c index 2f9d0fdbd0..289778a55c 100644 --- a/util/hbitmap.c +++ b/util/hbitmap.c @@ -188,6 +188,45 @@ void hbitmap_iter_init(HBitmapIter *hbi, const HBitmap *hb, uint64_t first) } } +int64_t hbitmap_next_zero(const HBitmap *hb, uint64_t start) +{ + size_t pos = (start >> hb->granularity) >> BITS_PER_LEVEL; + unsigned long *last_lev = hb->levels[HBITMAP_LEVELS - 1]; + uint64_t sz = hb->sizes[HBITMAP_LEVELS - 1]; + unsigned long cur = last_lev[pos]; + unsigned start_bit_offset = + (start >> hb->granularity) & (BITS_PER_LONG - 1); + int64_t res; + + cur |= (1UL << start_bit_offset) - 1; + assert((start >> hb->granularity) < hb->size); + + if (cur == (unsigned long)-1) { + do { + pos++; + } while (pos < sz && last_lev[pos] == (unsigned long)-1); + + if (pos >= sz) { + return -1; + } + + cur = last_lev[pos]; + } + + res = (pos << BITS_PER_LEVEL) + ctol(cur); + if (res >= hb->size) { + return -1; + } + + res = res << hb->granularity; + if (res < start) { + assert(((start - res) >> hb->granularity) == 0); + return start; + } + + return res; +} + bool hbitmap_empty(const HBitmap *hb) { return hb->count == 0; |