]> git.ipfire.org Git - thirdparty/kernel/linux.git/commit
perf maps: Add maps__mutate_mapping
authorIan Rogers <irogers@google.com>
Thu, 11 Jun 2026 16:41:18 +0000 (09:41 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 15 Jun 2026 12:01:27 +0000 (09:01 -0300)
commit75a4888b7029a1f98613aef91f517b2ee1f03d43
tree3ad6a84892a68da2ccd77ccbefe6b0536a55f9f7
parent325aabebbbc0520f95db3974d46e13a081cf6c28
perf maps: Add maps__mutate_mapping

During kernel ELF symbol parsing (dso__process_kernel_symbol), proc
kallsyms image loading (dso__load_kernel_sym,
dso__load_guest_kernel_sym), and dynamic kernel memory map alignment
updates (machine__update_kernel_mmap), the loader directly modifies live
virtual address boundary keys fields on map objects.

If these boundaries are mutated while the map pointer actively resides
inside the parent maps cache array list (kmaps) outside of any lock
closure, an unsafe concurrent window is exposed where parallel worker
lookup threads (e.g., inside perf top) can mistakenly assume the cache
remains sorted based on stale parameters, executing binary search
queries (bsearch) across an unsorted range and triggering lookup
failures.

Fix this by introducing maps__mutate_mapping() that explicitly acquires
the parent maps write semaphore lock, executes an incoming mutation
callback block to perform the field updates under lock protection, and
invalidates the sorted tracking flags prior to releasing the write lock.

This guarantees synchronization invariants, closing the concurrent
lookup race window. The adjacent module alignment pass inside
machine__create_kernel_maps() is safely preserved as a high-performance
lockless pass, as its invocation lifecycle bounds remain strictly
single-threaded by contract during session initialization construction.

To safely support this unconditional down_write write lock mutator
without recursive read-to-write self-deadlock upgrades during lazy
symbol loading, we introduce a public maps__load_maps() API.

It copies map pointers under a brief read lock and force-loads all
modules locklessly outside the lock. Callers (such as perf inject) must
pre-load all kernel symbol maps up front at startup using
maps__load_maps(), completely bypassing dynamic runtime mutations.

Fixes: 39b12f781271 ("perf tools: Make it possible to read object code from vmlinux")
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Tested-by: James Clark <james.clark@linaro.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Gabriel Marin <gmx@google.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/machine.c
tools/perf/util/maps.c
tools/perf/util/maps.h
tools/perf/util/symbol-elf.c
tools/perf/util/symbol.c