test_lru_sanity3 fills a map of tgt_free * 2 elements and then reads
back all but the last few, which fails on a machine with six CPUs:
test_lru_sanity3 (map_type:9 map_flags:0x0): test_lru_map.c:463:
test_lru_sanity3: Assertion `!bpf_map_lookup_elem_with_ref_bit(
lru_map_fd, key, value)' failed.
Elements are handed to a CPU in refills of lru->target_free, which
bpf_lru_populate() derives from the map size as clamp((nr_elems /
num_possible_cpus()) / 2, 1, LOCAL_FREE_TARGET), so 21 for a 256 element
map and six CPUs. A refill that the global free list cannot satisfy in
full does not stop there: bpf_lru_list_pop_free_to_local() calls
__bpf_lru_list_shrink() for the remainder, which evicts elements that
are still in the map. 256 is not a multiple of 21, so filling the map
ends on a partial refill that drops 17 of the elements the test goes on
to reference, and the lookup fails on the first of them.
Whether the size divides evenly depends on the CPU count alone, which is
why this passes on two and on sixty four CPUs and fails on six.
batch_size is already __tgt_size(tgt_free), the refill size of a map of
__map_size(batch_size) elements, so size the map that way and filling it
consumes whole refills and evicts nothing. Start the keys of the last
insert at map_size + 1, they were placed just past the old size.
Fixes: 5e9388f7984a ("selftests/bpf: adapt one more case in test_lru_map to the
new target_free")
Signed-off-by: Eva Kurchatova <[email protected]>
---
tools/testing/selftests/bpf/test_lru_map.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/bpf/test_lru_map.c
b/tools/testing/selftests/bpf/test_lru_map.c
index 0921939532c6..fc67a337d3c1 100644
--- a/tools/testing/selftests/bpf/test_lru_map.c
+++ b/tools/testing/selftests/bpf/test_lru_map.c
@@ -441,8 +441,18 @@ static void test_lru_sanity3(int map_type, int map_flags,
unsigned int tgt_free)
assert(sched_next_online(0, &next_cpu) != -1);
batch_size = __tgt_size(tgt_free);
+ if (!batch_size)
+ batch_size = 1;
+
+ /* The local free list is refilled lru->target_free elements at a
+ * time, and a refill the global free list cannot satisfy in full
+ * shrinks the LRU list, which evicts elements that are still live.
+ * Size the map so that target_free divides it, otherwise filling it
+ * ends on a partial refill and evicts the elements referenced below.
+ */
+ map_size = __map_size(batch_size);
+ assert(__tgt_size(map_size) == batch_size);
- map_size = tgt_free * 2;
lru_map_fd = create_map(map_type, map_flags, map_size);
assert(lru_map_fd != -1);
@@ -466,7 +476,7 @@ static void test_lru_sanity3(int map_type, int map_flags,
unsigned int tgt_free)
}
/* Insert new batch_size: replaces the non-referenced elements */
- key = 2 * tgt_free + 1;
+ key = 1 + map_size;
end_key = key + batch_size;
for (; key < end_key; key++) {
assert(!bpf_map_update_elem(lru_map_fd, &key, value,
--
2.55.0