This unintended LRU eviction issue was observed while developing the selftest for "[PATCH bpf-next v10 0/8] bpf: Introduce BPF_F_CPU and BPF_F_ALL_CPUS flags for percpu maps" [1].
When updating an existing element in lru_hash or lru_percpu_hash maps, the current implementation calls prealloc_lru_pop() to get a new node before checking if the key already exists. If the map is full, this triggers LRU eviction and removes an existing element, even though the update operation only needs to modify the value in-place. In the selftest of the aforementioned patch, this was to be worked around by reserving an extra entry to void triggering eviction in __htab_lru_percpu_map_update_elem(). However, the underlying issue remains problematic because: 1. Users may unexpectedly lose entries when updating existing keys in a full map. 2. The eviction overhead is unnecessary for existing key updates. This patchset fixes the issue by first checking if the key exists before allocating a new node. If the key is found, update the value using the extra LRU node without triggering any eviction. Only proceed with node allocation if the key does not exist. Links: [1] https://lore.kernel.org/bpf/[email protected]/ Changes: v1 -> v2: * Tidy hash handling in LRU code. * Factor out bpf_lru_node_reset_state helper. * Factor out bpf_lru_move_next_inactive_rotation helper. * Update element using preallocated extra elements in order to avoid breaking the update atomicity (per Alexei). * Check values on other CPUs in tests (per bot). * v1: https://lore.kernel.org/bpf/[email protected]/ Leon Hwang (5): bpf: lru: Tidy hash handling in LRU code bpf: lru: Factor out bpf_lru_node_reset_state helper bpf: lru: Factor out bpf_lru_move_next_inactive_rotation helper bpf: lru: Fix unintended eviction when updating lru hash maps selftests/bpf: Add tests to verify no unintended eviction when updating lru_[percpu_,]hash maps kernel/bpf/bpf_lru_list.c | 228 ++++++++++++++---- kernel/bpf/bpf_lru_list.h | 10 +- kernel/bpf/hashtab.c | 90 ++++++- .../selftests/bpf/prog_tests/htab_update.c | 129 ++++++++++ 4 files changed, 402 insertions(+), 55 deletions(-) -- 2.52.0

