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, this was to be worked around by reserving an extra entry to avoid 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 in-place, refresh the LRU reference, and return immediately without triggering any eviction. Only proceed with node allocation if the key does not exist.
Links: [1] https://lore.kernel.org/bpf/20251117162033.6296-1-leon.hwang@linux.dev/
Leon Hwang (3): bpf: Avoid unintended eviction when updating lru_hash maps bpf: Avoid unintended eviction when updating lru_percpu_hash maps selftests/bpf: Add tests to verify no unintended eviction when updating lru hash maps
kernel/bpf/hashtab.c | 43 +++++++++++ .../selftests/bpf/prog_tests/htab_update.c | 73 +++++++++++++++++++ 2 files changed, 116 insertions(+)
-- 2.52.0