| From 0e41331ae2eae507ae70a0d94257b6064a270dbe Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 4 Sep 2019 14:46:18 -0700 |
| Subject: perf/core: Rework memory accounting in perf_mmap() |
| |
| From: Song Liu <songliubraving@fb.com> |
| |
| [ Upstream commit d44248a41337731a111374822d7d4451b64e73e4 ] |
| |
| perf_mmap() always increases user->locked_vm. As a result, "extra" could |
| grow bigger than "user_extra", which doesn't make sense. Here is an |
| example case: |
| |
| (Note: Assume "user_lock_limit" is very small.) |
| |
| | # of perf_mmap calls |vma->vm_mm->pinned_vm|user->locked_vm| |
| | 0 | 0 | 0 | |
| | 1 | user_extra | user_extra | |
| | 2 | 3 * user_extra | 2 * user_extra| |
| | 3 | 6 * user_extra | 3 * user_extra| |
| | 4 | 10 * user_extra | 4 * user_extra| |
| |
| Fix this by maintaining proper user_extra and extra. |
| |
| Reviewed-By: Hechao Li <hechaol@fb.com> |
| Reported-by: Hechao Li <hechaol@fb.com> |
| Signed-off-by: Song Liu <songliubraving@fb.com> |
| Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> |
| Cc: <kernel-team@fb.com> |
| Cc: Jie Meng <jmeng@fb.com> |
| Cc: Linus Torvalds <torvalds@linux-foundation.org> |
| Cc: Peter Zijlstra <peterz@infradead.org> |
| Cc: Thomas Gleixner <tglx@linutronix.de> |
| Link: https://lkml.kernel.org/r/20190904214618.3795672-1-songliubraving@fb.com |
| Signed-off-by: Ingo Molnar <mingo@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| kernel/events/core.c | 17 +++++++++++++++-- |
| 1 file changed, 15 insertions(+), 2 deletions(-) |
| |
| diff --git a/kernel/events/core.c b/kernel/events/core.c |
| index a2a50b668ef32..c0a6a50e01af6 100644 |
| --- a/kernel/events/core.c |
| +++ b/kernel/events/core.c |
| @@ -5585,7 +5585,8 @@ again: |
| * undo the VM accounting. |
| */ |
| |
| - atomic_long_sub((size >> PAGE_SHIFT) + 1, &mmap_user->locked_vm); |
| + atomic_long_sub((size >> PAGE_SHIFT) + 1 - mmap_locked, |
| + &mmap_user->locked_vm); |
| atomic64_sub(mmap_locked, &vma->vm_mm->pinned_vm); |
| free_uid(mmap_user); |
| |
| @@ -5729,8 +5730,20 @@ accounting: |
| |
| user_locked = atomic_long_read(&user->locked_vm) + user_extra; |
| |
| - if (user_locked > user_lock_limit) |
| + if (user_locked <= user_lock_limit) { |
| + /* charge all to locked_vm */ |
| + } else if (atomic_long_read(&user->locked_vm) >= user_lock_limit) { |
| + /* charge all to pinned_vm */ |
| + extra = user_extra; |
| + user_extra = 0; |
| + } else { |
| + /* |
| + * charge locked_vm until it hits user_lock_limit; |
| + * charge the rest from pinned_vm |
| + */ |
| extra = user_locked - user_lock_limit; |
| + user_extra -= extra; |
| + } |
| |
| lock_limit = rlimit(RLIMIT_MEMLOCK); |
| lock_limit >>= PAGE_SHIFT; |
| -- |
| 2.20.1 |
| |