diff options
author | Omar Sandoval <osandov@fb.com> | 2018-12-03 14:45:43 -0800 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2018-12-03 17:03:58 -0700 |
commit | 8c2def893afc60d88160d524acf345765cf0c447 (patch) | |
tree | 1591bf8e79e27bc533c1781923b154f9545ce2f0 /include/linux/sbitmap.h | |
parent | fe1f452640d888c4311ef35c8ee497f47c3ea17c (diff) |
sbitmap: fix sbitmap_for_each_set()
We need to ignore bits in the cleared mask when iterating over all set
bits.
Fixes: ea86ea2cdced ("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>
Diffstat (limited to 'include/linux/sbitmap.h')
-rw-r--r-- | include/linux/sbitmap.h | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/include/linux/sbitmap.h b/include/linux/sbitmap.h index 92806a2dbab7..03f50fcedc79 100644 --- a/include/linux/sbitmap.h +++ b/include/linux/sbitmap.h @@ -265,12 +265,14 @@ static inline void __sbitmap_for_each_set(struct sbitmap *sb, nr = SB_NR_TO_BIT(sb, start); while (scanned < sb->depth) { - struct sbitmap_word *word = &sb->map[index]; - unsigned int depth = min_t(unsigned int, word->depth - nr, + unsigned long word; + unsigned int depth = min_t(unsigned int, + sb->map[index].depth - nr, sb->depth - scanned); scanned += depth; - if (!word->word) + word = sb->map[index].word & ~sb->map[index].cleared; + if (!word) goto next; /* @@ -280,7 +282,7 @@ static inline void __sbitmap_for_each_set(struct sbitmap *sb, */ depth += nr; while (1) { - nr = find_next_bit(&word->word, depth, nr); + nr = find_next_bit(&word, depth, nr); if (nr >= depth) break; if (!fn(sb, (index << sb->shift) + nr, data)) |