sbitmap: fix sbitmap_for_each_set()

We need to ignore bits in the cleared mask when iterating over all set
bits.

Fixes: ea86ea2cdc ("sbitmap: ammortize cost of clearing bits")
Reported-by: Jens Axboe@kernel.dk>
Signed-off-by: Omar Sandoval <osandov@fb.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Omar Sandoval 2018-12-03 14:45:43 -08:00 committed by Jens Axboe
parent fe1f452640
commit 8c2def893a

View file

@ -265,12 +265,14 @@ static inline void __sbitmap_for_each_set(struct sbitmap *sb,
nr = SB_NR_TO_BIT(sb, start); nr = SB_NR_TO_BIT(sb, start);
while (scanned < sb->depth) { while (scanned < sb->depth) {
struct sbitmap_word *word = &sb->map[index]; unsigned long word;
unsigned int depth = min_t(unsigned int, word->depth - nr, unsigned int depth = min_t(unsigned int,
sb->map[index].depth - nr,
sb->depth - scanned); sb->depth - scanned);
scanned += depth; scanned += depth;
if (!word->word) word = sb->map[index].word & ~sb->map[index].cleared;
if (!word)
goto next; goto next;
/* /*
@ -280,7 +282,7 @@ static inline void __sbitmap_for_each_set(struct sbitmap *sb,
*/ */
depth += nr; depth += nr;
while (1) { while (1) {
nr = find_next_bit(&word->word, depth, nr); nr = find_next_bit(&word, depth, nr);
if (nr >= depth) if (nr >= depth)
break; break;
if (!fn(sb, (index << sb->shift) + nr, data)) if (!fn(sb, (index << sb->shift) + nr, data))