A BPF map preallocates memory for items by default. BPF_F_NO_PREALLOC flag turns preallocation off.
A preallocated map is faster. Sleepable programs could only work with preallocated maps until recently.
When it comes to concurrency, there's a significant difference:
When items are allocated and freed individually, RCU ensures that the memory is not reused until it is safe to do so.
Preallocated map can reuse an item right away.
Imagine a BPF program P obtained a pointer to a value with bpf_map_lookup_elem(). Neither P nor userspace ever modify values. However, the value DO change when the item is killed and reused for unrelated element in a preallocated map.
It looks like there's nothing P could do to obtain a stable view of the value, even with explicit locking (as bpf_map_update_elem() doesn't lock a brand new item before copying in data, which might be the same object P is currently looking into).
Even worse, a lookup in a map could yield a completely bogus result if the key is modified concurrently with lookup.
Is it even possible to use preallocated maps safely?