]> git.dujemihanovic.xyz Git - linux.git/commitdiff
bitmap: relax find_nth_bit() limitation on return value
authorYury Norov <yury.norov@gmail.com>
Thu, 2 May 2024 17:12:56 +0000 (10:12 -0700)
committerYury Norov <yury.norov@gmail.com>
Thu, 9 May 2024 16:25:08 +0000 (09:25 -0700)
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: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Closes: https://lore.kernel.org/all/Zi50cAgR8nZvgLa3@yury-ThinkPad/T/#m6da806a0525e74dcc91f35e5f20766ed4e853e8a
Signed-off-by: Yury Norov <yury.norov@gmail.com>
include/linux/find.h
lib/find_bit.c
lib/test_bitmap.c

index c69598e383c1618fbbdd99e252f70c2cacfd72df..02751e43d448d40c81e1b531f117ba135e5cc142 100644 (file)
@@ -220,7 +220,7 @@ unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
  *      idx = find_first_bit(addr, size);
  *
  * Returns the bit number of the N'th set bit.
- * If no such, returns @size.
+ * If no such, returns >= @size.
  */
 static inline
 unsigned long find_nth_bit(const unsigned long *addr, unsigned long size, unsigned long n)
index 32f99e9a670e64fcdc8e9a7e67d29df199486a69..0bddfc3ff248349b7459e6b9ce55b004300f6d7a 100644 (file)
@@ -87,7 +87,7 @@ out:                                                                          \
        if (sz % BITS_PER_LONG)                                                 \
                tmp = (FETCH) & BITMAP_LAST_WORD_MASK(sz);                      \
 found:                                                                         \
-       sz = min(idx * BITS_PER_LONG + fns(tmp, nr), sz);                       \
+       sz = idx * BITS_PER_LONG + fns(tmp, nr);                                \
 out:                                                                           \
        sz;                                                                     \
 })
index 6b2b33579f565bfb1326cb63db8bd165515aebe9..088838f829c99b79b88a5c5124b8ccedcfd27ec4 100644 (file)
@@ -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(80,  find_nth_bit(bmap, 64 * 3, 6));
        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(20,  find_nth_bit(bmap, 64 * 3 - 1, 1));
@@ -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(80,  find_nth_bit(bmap, 64 * 3 - 1, 6));
        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) {
                b = find_nth_bit(exp1, EXP1_IN_BITS, cnt++);