Commit 0b2811ba authored by Yury Norov's avatar Yury Norov

bitmap: relax find_nth_bit() limitation on return value

The function claims to return the bitmap size, if Nth bit doesn't exist.
This rule is violated in inline case because the fns() that is used
there doesn't know anything about size of the bitmap.

So, relax this requirement to '>= size', and make the outline
implementation a bit cheaper.

All in-tree kernel users of find_nth_bit() are safe against that.
Reported-by: default avatarRasmus Villemoes <linux@rasmusvillemoes.dk>
Closes: https://lore.kernel.org/all/Zi50cAgR8nZvgLa3@yury-ThinkPad/T/#m6da806a0525e74dcc91f35e5f20766ed4e853e8aSigned-off-by: default avatarYury Norov <yury.norov@gmail.com>
parent 77db1920
...@@ -220,7 +220,7 @@ unsigned long find_first_bit(const unsigned long *addr, unsigned long size) ...@@ -220,7 +220,7 @@ unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
* idx = find_first_bit(addr, size); * idx = find_first_bit(addr, size);
* *
* Returns the bit number of the N'th set bit. * Returns the bit number of the N'th set bit.
* If no such, returns @size. * If no such, returns >= @size.
*/ */
static inline static inline
unsigned long find_nth_bit(const unsigned long *addr, unsigned long size, unsigned long n) unsigned long find_nth_bit(const unsigned long *addr, unsigned long size, unsigned long n)
......
...@@ -87,7 +87,7 @@ out: \ ...@@ -87,7 +87,7 @@ out: \
if (sz % BITS_PER_LONG) \ if (sz % BITS_PER_LONG) \
tmp = (FETCH) & BITMAP_LAST_WORD_MASK(sz); \ tmp = (FETCH) & BITMAP_LAST_WORD_MASK(sz); \
found: \ found: \
sz = min(idx * BITS_PER_LONG + fns(tmp, nr), sz); \ sz = idx * BITS_PER_LONG + fns(tmp, nr); \
out: \ out: \
sz; \ sz; \
}) })
......
...@@ -244,7 +244,7 @@ static void __init test_find_nth_bit(void) ...@@ -244,7 +244,7 @@ static void __init test_find_nth_bit(void)
expect_eq_uint(60, find_nth_bit(bmap, 64 * 3, 5)); expect_eq_uint(60, find_nth_bit(bmap, 64 * 3, 5));
expect_eq_uint(80, find_nth_bit(bmap, 64 * 3, 6)); expect_eq_uint(80, find_nth_bit(bmap, 64 * 3, 6));
expect_eq_uint(123, find_nth_bit(bmap, 64 * 3, 7)); expect_eq_uint(123, find_nth_bit(bmap, 64 * 3, 7));
expect_eq_uint(64 * 3, find_nth_bit(bmap, 64 * 3, 8)); expect_eq_uint(0, !!(find_nth_bit(bmap, 64 * 3, 8) < 64 * 3));
expect_eq_uint(10, find_nth_bit(bmap, 64 * 3 - 1, 0)); expect_eq_uint(10, find_nth_bit(bmap, 64 * 3 - 1, 0));
expect_eq_uint(20, find_nth_bit(bmap, 64 * 3 - 1, 1)); expect_eq_uint(20, find_nth_bit(bmap, 64 * 3 - 1, 1));
...@@ -254,7 +254,7 @@ static void __init test_find_nth_bit(void) ...@@ -254,7 +254,7 @@ static void __init test_find_nth_bit(void)
expect_eq_uint(60, find_nth_bit(bmap, 64 * 3 - 1, 5)); expect_eq_uint(60, find_nth_bit(bmap, 64 * 3 - 1, 5));
expect_eq_uint(80, find_nth_bit(bmap, 64 * 3 - 1, 6)); expect_eq_uint(80, find_nth_bit(bmap, 64 * 3 - 1, 6));
expect_eq_uint(123, find_nth_bit(bmap, 64 * 3 - 1, 7)); expect_eq_uint(123, find_nth_bit(bmap, 64 * 3 - 1, 7));
expect_eq_uint(64 * 3 - 1, find_nth_bit(bmap, 64 * 3 - 1, 8)); expect_eq_uint(0, !!(find_nth_bit(bmap, 64 * 3 - 1, 8) < 64 * 3 - 1));
for_each_set_bit(bit, exp1, EXP1_IN_BITS) { for_each_set_bit(bit, exp1, EXP1_IN_BITS) {
b = find_nth_bit(exp1, EXP1_IN_BITS, cnt++); b = find_nth_bit(exp1, EXP1_IN_BITS, cnt++);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment