From: "Lorenzo Stoakes (ARM)" <ljs@kernel.org>
To: stable@vger.kernel.org
Subject: [PATCH 6.12.y] perf: Track the perf mlock gift separately
Date: Wed, 21 Oct 2026 16:53:49 +0100 [thread overview]
Message-ID: <20261021155349.1698340-1-ljs@kernel.org> (raw)
In-Reply-To: <2026102117-rethink-jaybird-bd86@gregkh>
The locked_vm field in struct user_struct was originally introduced by
commit 789f90fcf6b0 ("perf_counter: per user mlock gift") to provide an
mlock-like budget for perf measured against mm->pinned_vm (since 2011).
perf grants each user a 'gift' of perf_event_mlock_kb * online CPUs of
buffer pages which is charged to user->locked_vm without any RLIMIT_MEMLOCK
check.
Only pages beyond the gift are checked against RLIMIT_MEMLOCK, per-mm, via
mm->pinned_vm, which makes it different from the standard mlock() check,
which is per-mm and made against RLIMIT_MEMLOCK.
However, since this was introduced, a number of other components have
utilised this field where a shared resource needed to be limited against
RLIMIT_MEMLOCK.
The other users are currently MSG_ZEROCOPY, io_uring, AF_XDP, iommufd,
s390 KVM zPCI and most recently, secretmem in commit 97d34aa65c29
("mm/secretmem: properly account locked pages").
This field is shared between all of these, but because the gift is not
checked against RLIMIT_MEMLOCK, user->locked_vm alone can exceed it - 16
CPUs * 516 KiB is already more than the default 8 MiB - after which every
other user of the field fails unconditionally.
This was reported by a user who saw secretmem failing while running a
simultaneous perf record.
Resolve the issue by simply giving perf its own field separate from the
rest.
BPF used user->locked_vm up until commit 80ee81e0403c ("bpf: Eliminate
rlimit-based memory accounting infra for bpf maps") which landed in 5.11.
Thus also eliminate the now-defunct ifdef for CONFIG_BPF_SYSCALL for
user->locked_vm.
This issue exists between all of the components which use user->locked_vm
and perf, however secretmem is the first user who has caused a report over
many years and has been backported, so target the fix at that.
Fixes: 97d34aa65c29 ("mm/secretmem: properly account locked pages")
Closes: https://lore.kernel.org/20261002175651.811343-1-ameer.hamza@truenas.com
Reported-by: Ameer Hamza <ameer.hamza@truenas.com>
Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@vger.kernel.org
(cherry picked from commit 78436f3882fb8d848c823bf8cf754988202c5ca5)
[ ljs - Applied to open-coded accounting in perf_mmap()/perf_mmap_close(). ]
Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
include/linux/sched/user.h | 8 +++++---
kernel/events/core.c | 12 ++++++------
2 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/include/linux/sched/user.h b/include/linux/sched/user.h
index 8d7e5521f7cd..ec262b605437 100644
--- a/include/linux/sched/user.h
+++ b/include/linux/sched/user.h
@@ -23,11 +23,13 @@ struct user_struct {
struct hlist_node uidhash_node;
kuid_t uid;
-#if defined(CONFIG_PERF_EVENTS) || defined(CONFIG_BPF_SYSCALL) || \
- defined(CONFIG_NET) || defined(CONFIG_IO_URING) || \
+#if defined(CONFIG_NET) || defined(CONFIG_IO_URING) || \
defined(CONFIG_VFIO_PCI_ZDEV_KVM) || IS_ENABLED(CONFIG_IOMMUFD) || \
defined(CONFIG_SECRETMEM)
- atomic_long_t locked_vm;
+ atomic_long_t locked_vm; /* pinned pages charged to RLIMIT_MEMLOCK */
+#endif
+#ifdef CONFIG_PERF_EVENTS
+ atomic_long_t perf_mlock; /* perf buffer pages within perf_event_mlock_kb */
#endif
#ifdef CONFIG_WATCH_QUEUE
atomic_t nr_watches; /* The number of watches this user currently has */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 6c9c3bfc0da2..fe93bb9cfad6 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -6533,7 +6533,7 @@ static void perf_mmap_close(struct vm_area_struct *vma)
perf_pmu_output_stop(event);
/* now it's safe to free the pages */
- atomic_long_sub(rb->aux_nr_pages - rb->aux_mmap_locked, &mmap_user->locked_vm);
+ atomic_long_sub(rb->aux_nr_pages - rb->aux_mmap_locked, &mmap_user->perf_mlock);
atomic64_sub(rb->aux_mmap_locked, &vma->vm_mm->pinned_vm);
/* this has to be the last one */
@@ -6608,7 +6608,7 @@ static void perf_mmap_close(struct vm_area_struct *vma)
*/
atomic_long_sub((size >> PAGE_SHIFT) + 1 - mmap_locked,
- &mmap_user->locked_vm);
+ &mmap_user->perf_mlock);
atomic64_sub(mmap_locked, &vma->vm_mm->pinned_vm);
free_uid(mmap_user);
@@ -6768,11 +6768,11 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
*/
user_lock_limit *= num_online_cpus();
- user_locked = atomic_long_read(&user->locked_vm);
+ user_locked = atomic_long_read(&user->perf_mlock);
/*
* sysctl_perf_event_mlock may have changed, so that
- * user->locked_vm > user_lock_limit
+ * user->perf_mlock > user_lock_limit
*/
if (user_locked > user_lock_limit)
user_locked = user_lock_limit;
@@ -6780,7 +6780,7 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
if (user_locked > user_lock_limit) {
/*
- * charge locked_vm until it hits user_lock_limit;
+ * charge perf_mlock until it hits user_lock_limit;
* charge the rest from pinned_vm
*/
extra = user_locked - user_lock_limit;
@@ -6832,7 +6832,7 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
unlock:
if (!ret) {
- atomic_long_add(user_extra, &user->locked_vm);
+ atomic_long_add(user_extra, &user->perf_mlock);
atomic64_add(extra, &vma->vm_mm->pinned_vm);
atomic_inc(&event->mmap_count);
--
2.56.0
next prev parent reply other threads:[~2026-10-21 15:53 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-21 14:43 FAILED: patch "[PATCH] perf: Track the perf mlock gift separately" failed to apply to 6.12-stable tree gregkh
2026-10-21 15:53 ` Lorenzo Stoakes (ARM) [this message]
2026-10-21 15:56 ` [PATCH 6.12.y] perf: Track the perf mlock gift separately Lorenzo Stoakes (ARM)
2026-10-23 20:02 ` Sasha Levin
2026-10-21 15:54 ` Lorenzo Stoakes (ARM)
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=20261021155349.1698340-1-ljs@kernel.org \
--to=ljs@kernel.org \
--cc=stable@vger.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