From: Alexei Starovoitov <alexei.starovoitov@gmail.com>
To: bpf@vger.kernel.org
Cc: daniel@iogearbox.net, andrii@kernel.org, eddyz87@gmail.com,
memxor@gmail.com, oleg@redhat.com, peterz@infradead.org,
mhiramat@kernel.org, jolsa@kernel.org, akpm@linux-foundation.org,
liam@infradead.org, ljs@kernel.org, surenb@google.com,
david@kernel.org, vbabka@kernel.org, jannh@google.com,
hughd@google.com, kees@kernel.org, mingo@redhat.com,
tglx@kernel.org, x86@kernel.org,
linux-trace-kernel@vger.kernel.org, linux-mm@kvack.org,
linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH bpf-next 0/9] uprobes: Don't stall fork() when mmap_lock is busy
Date: Thu, 22 Oct 2026 01:57:03 +0000 [thread overview]
Message-ID: <20261022015712.1297331-1-alexei.starovoitov@gmail.com> (raw)
From: Alexei Starovoitov <ast@kernel.org>
uprobe_register() and uprobe_unregister() stall every fork() in the system
when some process keeps its mmap_lock busy:
- register_for_each_vma() sleeps on that mmap_lock with dup_mmap_sem held
for writing.
- fork() of that process sleeps on that mmap_lock with dup_mmap_sem held
for reading. The next register_for_each_vma() waits for it, and other
forks wait for the writer. The process doesn't have to map the file.
We found it the hard way by using uprobes in production. uprobes were
attached to libraries and binaries that many processes map, on a large
number of hosts. On some of them every fork() was stuck for minutes while
uprobe was being registered.
Patch 5 fixes the first one. Patch 6 fixes the second one. Patch 1 is
a helper for them and patch 9 is the selftest.
The rest fix old bugs that patches 5 and 6 make easier to hit:
- Patch 2: exit_mmap() runs under dup_mmap_sem.
- Patches 3, 4: x86. The removal of optimized uprobe that failed half-way
is never finished, and SIGKILL triggers WARN_ON_ONCE().
- Patch 7: the child loses the breakpoint of an inherited perf event.
- Patch 8: the tracer that is killed leaves its breakpoints behind.
A process loops over mmap(4G, MAP_POPULATE) and munmap(). Another process
calls fork() in a loop. The longest fork() while uprobes are being attached
and the time to attach, in msec. 32 cpu VM, HZ=1000, no debug options,
median of 15-45 runs:
fork() attach
before after before after
the busy process maps the file
uprobe_multi, 1 uprobe 201 0.25 217 232
uprobe_multi, 4 uprobes 422 0.34 1483 1558
perf_event, 4 uprobes 421 0.47 3150 3322
it forks and doesn't map the file
uprobe_multi, 1 uprobe 198 0.07 212 9.6
uprobe_multi, 4 uprobes 203 0.08 213 13.4
perf_event, 4 uprobes 419 0.08 630 12.3
nobody keeps mmap_lock busy
uprobe_multi, 1000 processes 1.93 1.83 4.24 4.49
uprobe_multi, 5000 processes 8.88 8.60 8.33 9.23
I don't care which tree it goes through. It targets bpf-next only because
BPF CI will run the patches, including the new selftest.
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Alexei Starovoitov (9):
mm: Bring back mmap_write_trylock()
uprobes: Don't run exit_mmap() under dup_mmap_sem
uprobes/x86: Finish an unoptimization which failed half-way
uprobes/x86: Don't WARN if an optimized probe can't be written
uprobes: Don't sleep on mmap_lock under dup_mmap_sem
uprobes: Don't sleep on mmap_lock with dup_mmap_sem held in dup_mmap()
fork: Let the new task point to its mm before uprobes can find it
uprobes: Don't leak the breakpoints if the unregistering task is
killed
selftests/bpf: Test uprobes and fork() with busy mmap_lock
arch/x86/kernel/uprobes.c | 23 +-
include/linux/mmap_lock.h | 12 +
include/linux/uprobes.h | 5 +
kernel/events/uprobes.c | 260 ++++++++--
kernel/fork.c | 13 +-
mm/internal.h | 3 +-
mm/mmap.c | 33 +-
mm/nommu.c | 3 +-
.../selftests/bpf/prog_tests/uprobe_busy_mm.c | 447 ++++++++++++++++++
.../selftests/bpf/progs/uprobe_busy_mm.c | 22 +
10 files changed, 766 insertions(+), 55 deletions(-)
create mode 100644 tools/testing/selftests/bpf/prog_tests/uprobe_busy_mm.c
create mode 100644 tools/testing/selftests/bpf/progs/uprobe_busy_mm.c
--
2.55.0
next reply other threads:[~2026-10-22 1:57 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-22 1:57 Alexei Starovoitov [this message]
2026-10-22 1:57 ` [PATCH bpf-next 1/9] mm: Bring back mmap_write_trylock() Alexei Starovoitov
2026-10-22 1:57 ` [PATCH bpf-next 2/9] uprobes: Don't run exit_mmap() under dup_mmap_sem Alexei Starovoitov
2026-10-22 1:57 ` [PATCH bpf-next 3/9] uprobes/x86: Finish an unoptimization which failed half-way Alexei Starovoitov
2026-10-22 2:57 ` Gregory Price (Meta)
2026-10-22 1:57 ` [PATCH bpf-next 4/9] uprobes/x86: Don't WARN if an optimized probe can't be written Alexei Starovoitov
2026-10-22 2:37 ` bot+bpf-ci
2026-10-22 1:57 ` [PATCH bpf-next 5/9] uprobes: Don't sleep on mmap_lock under dup_mmap_sem Alexei Starovoitov
2026-10-22 2:37 ` bot+bpf-ci
2026-10-22 1:57 ` [PATCH bpf-next 6/9] uprobes: Don't sleep on mmap_lock with dup_mmap_sem held in dup_mmap() Alexei Starovoitov
2026-10-22 1:57 ` [PATCH bpf-next 7/9] fork: Let the new task point to its mm before uprobes can find it Alexei Starovoitov
2026-10-22 1:57 ` [PATCH bpf-next 8/9] uprobes: Don't leak the breakpoints if the unregistering task is killed Alexei Starovoitov
2026-10-22 1:57 ` [PATCH bpf-next 9/9] selftests/bpf: Test uprobes and fork() with busy mmap_lock Alexei Starovoitov
2026-10-22 2:37 ` bot+bpf-ci
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261022015712.1297331-1-alexei.starovoitov@gmail.com \
--to=alexei.starovoitov@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=andrii@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=david@kernel.org \
--cc=eddyz87@gmail.com \
--cc=hughd@google.com \
--cc=jannh@google.com \
--cc=jolsa@kernel.org \
--cc=kees@kernel.org \
--cc=liam@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=ljs@kernel.org \
--cc=memxor@gmail.com \
--cc=mhiramat@kernel.org \
--cc=mingo@redhat.com \
--cc=oleg@redhat.com \
--cc=peterz@infradead.org \
--cc=surenb@google.com \
--cc=tglx@kernel.org \
--cc=vbabka@kernel.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®