summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruenba@redhat.com>2025-01-26 17:57:06 +0100
committerKent Overstreet <kent.overstreet@linux.dev>2025-03-14 21:02:13 -0400
commitc722b818a2f8c43d75efeba8005af5f17dc535f0 (patch)
tree33b00ae5cfdc9c09cf7d5eb1f0ed71c9cfe7648e
parentbcachefs: add eytzinger0_for_each_prev (diff)
downloadlinux-c722b818a2f8c43d75efeba8005af5f17dc535f0.tar.gz
linux-c722b818a2f8c43d75efeba8005af5f17dc535f0.zip
bcachefs: improve eytzinger0_find_le self test
Rename eytzinger0_find_test_val() to eytzinger0_find_test_le() and add a new eytzinger0_find_test_val() wrapper that calls it. We have already established that the array is sorted in eytzinger order, so we can use the eytzinger iterator functions and check the boundary conditions to verify the result of eytzinger0_find_le(). Only scan the entire array if we get an incorrect result. When we need to scan, use eytzinger0_for_each_prev() so that we'll stop at the highest matching element in the array in case there are duplicates; going through the array linearly wouldn't give us that. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/util.c41
1 files changed, 30 insertions, 11 deletions
diff --git a/fs/bcachefs/util.c b/fs/bcachefs/util.c
index ebe3b5b1e615..d2f7ffcc4fd6 100644
--- a/fs/bcachefs/util.c
+++ b/fs/bcachefs/util.c
@@ -788,29 +788,48 @@ static inline int cmp_u16(const void *_l, const void *_r)
return (*l > *r) - (*r > *l);
}
-static void eytzinger0_find_test_val(u16 *test_array, unsigned nr, u16 search)
+static void eytzinger0_find_test_le(u16 *test_array, unsigned nr, u16 search)
{
- int i, c1 = -1, c2 = -1;
- ssize_t r;
+ int r, s;
+ bool bad;
r = eytzinger0_find_le(test_array, nr,
sizeof(test_array[0]),
cmp_u16, &search);
- if (r >= 0)
- c1 = test_array[r];
+ if (r >= 0) {
+ if (test_array[r] > search) {
+ bad = true;
+ } else {
+ s = eytzinger0_next(r, nr);
+ bad = s >= 0 && test_array[s] <= search;
+ }
+ } else {
+ s = eytzinger0_last(nr);
+ bad = s >= 0 && test_array[s] <= search;
+ }
- for (i = 0; i < nr; i++)
- if (test_array[i] <= search && test_array[i] > c2)
- c2 = test_array[i];
+ if (bad) {
+ s = -1;
+ eytzinger0_for_each_prev(j, nr) {
+ if (test_array[j] <= search) {
+ s = j;
+ break;
+ }
+ }
- if (c1 != c2) {
eytzinger0_for_each(j, nr)
pr_info("[%3u] = %12u\n", j, test_array[j]);
- pr_info("find_le(%2u) -> [%2zi] = %2i should be %2i\n",
- i, r, c1, c2);
+ pr_info("find_le(%12u) = %3i should be %3i\n",
+ search, r, s);
+ BUG();
}
}
+static void eytzinger0_find_test_val(u16 *test_array, unsigned nr, u16 search)
+{
+ eytzinger0_find_test_le(test_array, nr, search);
+}
+
void eytzinger0_find_test(void)
{
unsigned i, nr, allocated = 1 << 12;