summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorDavidlohr Bueso <dave@stgolabs.net>2019-02-06 12:59:15 -0500
committerJason Gunthorpe <jgg@mellanox.com>2019-02-07 14:54:02 -0500
commit70f8a3ca68d3e1f3344d959981ca55d5f6ec77f7 (patch)
tree5c43234a8f1697bf3d1a4a8926a014b922b046ff /kernel
parenta2bfd708b17adb6e597e70d4eca824667f2d4e3c (diff)
mm: make mm->pinned_vm an atomic64 counter
Taking a sleeping lock to _only_ increment a variable is quite the overkill, and pretty much all users do this. Furthermore, some drivers (ie: infiniband and scif) that need pinned semantics can go to quite some trouble to actually delay via workqueue (un)accounting for pinned pages when not possible to acquire it. By making the counter atomic we no longer need to hold the mmap_sem and can simply some code around it for pinned_vm users. The counter is 64-bit such that we need not worry about overflows such as rdma user input controlled from userspace. Reviewed-by: Ira Weiny <ira.weiny@intel.com> Reviewed-by: Christoph Lameter <cl@linux.com> Reviewed-by: Daniel Jordan <daniel.m.jordan@oracle.com> Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Davidlohr Bueso <dbueso@suse.de> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/events/core.c8
-rw-r--r--kernel/fork.c2
2 files changed, 5 insertions, 5 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index e5ede6918050..29e9f2473656 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5459,7 +5459,7 @@ static void perf_mmap_close(struct vm_area_struct *vma)
5459 5459
5460 /* now it's safe to free the pages */ 5460 /* now it's safe to free the pages */
5461 atomic_long_sub(rb->aux_nr_pages, &mmap_user->locked_vm); 5461 atomic_long_sub(rb->aux_nr_pages, &mmap_user->locked_vm);
5462 vma->vm_mm->pinned_vm -= rb->aux_mmap_locked; 5462 atomic64_sub(rb->aux_mmap_locked, &vma->vm_mm->pinned_vm);
5463 5463
5464 /* this has to be the last one */ 5464 /* this has to be the last one */
5465 rb_free_aux(rb); 5465 rb_free_aux(rb);
@@ -5532,7 +5532,7 @@ again:
5532 */ 5532 */
5533 5533
5534 atomic_long_sub((size >> PAGE_SHIFT) + 1, &mmap_user->locked_vm); 5534 atomic_long_sub((size >> PAGE_SHIFT) + 1, &mmap_user->locked_vm);
5535 vma->vm_mm->pinned_vm -= mmap_locked; 5535 atomic64_sub(mmap_locked, &vma->vm_mm->pinned_vm);
5536 free_uid(mmap_user); 5536 free_uid(mmap_user);
5537 5537
5538out_put: 5538out_put:
@@ -5680,7 +5680,7 @@ accounting:
5680 5680
5681 lock_limit = rlimit(RLIMIT_MEMLOCK); 5681 lock_limit = rlimit(RLIMIT_MEMLOCK);
5682 lock_limit >>= PAGE_SHIFT; 5682 lock_limit >>= PAGE_SHIFT;
5683 locked = vma->vm_mm->pinned_vm + extra; 5683 locked = atomic64_read(&vma->vm_mm->pinned_vm) + extra;
5684 5684
5685 if ((locked > lock_limit) && perf_paranoid_tracepoint_raw() && 5685 if ((locked > lock_limit) && perf_paranoid_tracepoint_raw() &&
5686 !capable(CAP_IPC_LOCK)) { 5686 !capable(CAP_IPC_LOCK)) {
@@ -5721,7 +5721,7 @@ accounting:
5721unlock: 5721unlock:
5722 if (!ret) { 5722 if (!ret) {
5723 atomic_long_add(user_extra, &user->locked_vm); 5723 atomic_long_add(user_extra, &user->locked_vm);
5724 vma->vm_mm->pinned_vm += extra; 5724 atomic64_add(extra, &vma->vm_mm->pinned_vm);
5725 5725
5726 atomic_inc(&event->mmap_count); 5726 atomic_inc(&event->mmap_count);
5727 } else if (rb) { 5727 } else if (rb) {
diff --git a/kernel/fork.c b/kernel/fork.c
index b69248e6f0e0..85e08c379a9e 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -981,7 +981,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,
981 mm_pgtables_bytes_init(mm); 981 mm_pgtables_bytes_init(mm);
982 mm->map_count = 0; 982 mm->map_count = 0;
983 mm->locked_vm = 0; 983 mm->locked_vm = 0;
984 mm->pinned_vm = 0; 984 atomic64_set(&mm->pinned_vm, 0);
985 memset(&mm->rss_stat, 0, sizeof(mm->rss_stat)); 985 memset(&mm->rss_stat, 0, sizeof(mm->rss_stat));
986 spin_lock_init(&mm->page_table_lock); 986 spin_lock_init(&mm->page_table_lock);
987 spin_lock_init(&mm->arg_lock); 987 spin_lock_init(&mm->arg_lock);