Track maximum size of locked memory, to be able to configure
RLIMIT_MEMLOCK resource limits. The information is available
with taskstats and cgroupstats netlink socket.

Signed-off-by: Topi Miettinen <toiwo...@gmail.com>
---
(Resending to lkml due to header size limits)

 arch/ia64/kernel/perfmon.c                 | 1 +
 arch/powerpc/kvm/book3s_64_vio.c           | 2 ++
 arch/powerpc/mm/mmu_context_iommu.c        | 2 ++
 drivers/infiniband/core/umem.c             | 1 +
 drivers/infiniband/hw/hfi1/user_pages.c    | 2 ++
 drivers/infiniband/hw/qib/qib_user_pages.c | 2 ++
 drivers/infiniband/hw/usnic/usnic_uiom.c   | 2 ++
 drivers/misc/mic/scif/scif_rma.c           | 1 +
 drivers/vfio/vfio_iommu_spapr_tce.c        | 2 ++
 drivers/vfio/vfio_iommu_type1.c            | 5 +++++
 kernel/bpf/syscall.c                       | 8 ++++++++
 kernel/events/core.c                       | 1 +
 mm/mlock.c                                 | 8 ++++++++
 mm/mmap.c                                  | 4 ++++
 mm/mremap.c                                | 4 ++++
 15 files changed, 45 insertions(+)

diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 2436ad5..7c6ae72 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -2341,6 +2341,7 @@ pfm_smpl_buffer_alloc(struct task_struct *task,
struct file *filp, pfm_context_t
        ctx->ctx_smpl_vaddr = (void *)vma->vm_start;
        *(unsigned long *)user_vaddr = vma->vm_start;
 +      task_update_resource_highwatermark(task, RLIMIT_MEMLOCK, size);
        return 0;
  error:
diff --git a/arch/powerpc/kvm/book3s_64_vio.c
b/arch/powerpc/kvm/book3s_64_vio.c
index 18cf6d1..40ea177 100644
--- a/arch/powerpc/kvm/book3s_64_vio.c
+++ b/arch/powerpc/kvm/book3s_64_vio.c
@@ -71,6 +71,8 @@ static long kvmppc_account_memlimit(unsigned long
stt_pages, bool inc)
                        ret = -ENOMEM;
                else
                        current->mm->locked_vm += stt_pages;
+               update_resource_highwatermark(RLIMIT_MEMLOCK,
+                                             locked << PAGE_SHIFT);
        } else {
                if (WARN_ON_ONCE(stt_pages > current->mm->locked_vm))
                        stt_pages = current->mm->locked_vm;
diff --git a/arch/powerpc/mm/mmu_context_iommu.c
b/arch/powerpc/mm/mmu_context_iommu.c
index da6a216..8c6bcbf 100644
--- a/arch/powerpc/mm/mmu_context_iommu.c
+++ b/arch/powerpc/mm/mmu_context_iommu.c
@@ -46,6 +46,8 @@ static long mm_iommu_adjust_locked_vm(struct mm_struct
*mm,
                        ret = -ENOMEM;
                else
                        mm->locked_vm += npages;
+               update_resource_highwatermark(RLIMIT_MEMLOCK,
+                                             locked << PAGE_SHIFT);
        } else {
                if (WARN_ON_ONCE(npages > mm->locked_vm))
                        npages = mm->locked_vm;
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index fe4d2e1..3c454eb 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -224,6 +224,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext
*context, unsigned long addr,
        ret = 0;
 +      update_resource_highwatermark(RLIMIT_MEMLOCK, locked << PAGE_SHIFT);
 out:
        if (ret < 0) {
                if (need_release)
diff --git a/drivers/infiniband/hw/hfi1/user_pages.c
b/drivers/infiniband/hw/hfi1/user_pages.c
index 88e10b5f..ca55f8c 100644
--- a/drivers/infiniband/hw/hfi1/user_pages.c
+++ b/drivers/infiniband/hw/hfi1/user_pages.c
@@ -111,6 +111,8 @@ int hfi1_acquire_user_pages(unsigned long vaddr,
size_t npages, bool writable,
        down_write(&current->mm->mmap_sem);
        current->mm->pinned_vm += ret;
+       update_resource_highwatermark(RLIMIT_MEMLOCK,
+                                     current->mm->pinned_vm << PAGE_SHIFT);
        up_write(&current->mm->mmap_sem);
        return ret;
diff --git a/drivers/infiniband/hw/qib/qib_user_pages.c
b/drivers/infiniband/hw/qib/qib_user_pages.c
index 2d2b94f..3a103c4 100644
--- a/drivers/infiniband/hw/qib/qib_user_pages.c
+++ b/drivers/infiniband/hw/qib/qib_user_pages.c
@@ -74,6 +74,8 @@ static int __qib_get_user_pages(unsigned long
start_page, size_t num_pages,
        }
        current->mm->pinned_vm += num_pages;
+       update_resource_highwatermark(RLIMIT_MEMLOCK,
+                                     current->mm->pinned_vm << PAGE_SHIFT);
        ret = 0;
        goto bail;
diff --git a/drivers/infiniband/hw/usnic/usnic_uiom.c
b/drivers/infiniband/hw/usnic/usnic_uiom.c
index a0b6ebe..6180654 100644
--- a/drivers/infiniband/hw/usnic/usnic_uiom.c
+++ b/drivers/infiniband/hw/usnic/usnic_uiom.c
@@ -178,6 +178,8 @@ static int usnic_uiom_get_pages(unsigned long addr,
size_t size, int writable,
                ret = 0;
        }
 +      update_resource_highwatermark(RLIMIT_MEMLOCK, locked << PAGE_SHIFT);
+
 out:
        if (ret < 0)
                usnic_uiom_put_pages(chunk_list, 0);
diff --git a/drivers/misc/mic/scif/scif_rma.c
b/drivers/misc/mic/scif/scif_rma.c
index e0203b1..acb970a 100644
--- a/drivers/misc/mic/scif/scif_rma.c
+++ b/drivers/misc/mic/scif/scif_rma.c
@@ -306,6 +306,7 @@ static inline int __scif_check_inc_pinned_vm(struct
mm_struct *mm,
                return -ENOMEM;
        }
        mm->pinned_vm = locked;
+       update_resource_highwatermark(RLIMIT_MEMLOCK, locked << PAGE_SHIFT);
        return 0;
 }
 diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c
b/drivers/vfio/vfio_iommu_spapr_tce.c
index 80378dd..13ee9e9 100644
--- a/drivers/vfio/vfio_iommu_spapr_tce.c
+++ b/drivers/vfio/vfio_iommu_spapr_tce.c
@@ -55,6 +55,8 @@ static long try_increment_locked_vm(long npages)
                        rlimit(RLIMIT_MEMLOCK),
                        ret ? " - exceeded" : "");
 +      update_resource_highwatermark(RLIMIT_MEMLOCK, locked << PAGE_SHIFT);
+
        up_write(&current->mm->mmap_sem);
        return ret;
diff --git a/drivers/vfio/vfio_iommu_type1.c
b/drivers/vfio/vfio_iommu_type1.c
index 2ba1942..e868ae5 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -145,6 +145,8 @@ static void vfio_lock_acct_bg(struct work_struct *work)
        mm = vwork->mm;
        down_write(&mm->mmap_sem);
        mm->locked_vm += vwork->npage;
+       update_resource_highwatermark(RLIMIT_MEMLOCK,
+                                     current->mm->locked_vm << PAGE_SHIFT);
        up_write(&mm->mmap_sem);
        mmput(mm);
        kfree(vwork);
@@ -160,6 +162,9 @@ static void vfio_lock_acct(long npage)
        if (down_write_trylock(&current->mm->mmap_sem)) {
                current->mm->locked_vm += npage;
+               update_resource_highwatermark(RLIMIT_MEMLOCK,
+                                             current->mm->locked_vm <<
+                                             PAGE_SHIFT);
                up_write(&current->mm->mmap_sem);
                return;
        }
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 46ecce4..0efa1c3 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -76,6 +76,10 @@ static int bpf_map_charge_memlock(struct bpf_map *map)
                return -EPERM;
        }
        map->user = user;
+
+       update_resource_highwatermark(RLIMIT_MEMLOCK,
+                                     atomic_long_read(&user->locked_vm) <<
+                                     PAGE_SHIFT);
        return 0;
 }
 @@ -601,6 +605,10 @@ static int bpf_prog_charge_memlock(struct bpf_prog
*prog)
                return -EPERM;
        }
        prog->aux->user = user;
+
+       update_resource_highwatermark(RLIMIT_MEMLOCK,
+                                     atomic_long_read(&user->locked_vm) <<
+                                     PAGE_SHIFT);
        return 0;
 }
 diff --git a/kernel/events/core.c b/kernel/events/core.c
index 43d43a2d..4b8b143 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5096,6 +5096,7 @@ accounting:
                if (!ret)
                        rb->aux_mmap_locked = extra;
        }
+       update_resource_highwatermark(RLIMIT_MEMLOCK, locked << PAGE_SHIFT);
  unlock:
        if (!ret) {
diff --git a/mm/mlock.c b/mm/mlock.c
index ef8dc9f..eb45857 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -648,6 +648,8 @@ static __must_check int do_mlock(unsigned long
start, size_t len, vm_flags_t fla
        if (error)
                return error;
 +      update_resource_highwatermark(RLIMIT_MEMLOCK, locked << PAGE_SHIFT);
+
        error = __mm_populate(start, len, 0);
        if (error)
                return __mlock_posix_error_return(error);
@@ -761,6 +763,9 @@ SYSCALL_DEFINE1(mlockall, int, flags)
        if (!ret && (flags & MCL_CURRENT))
                mm_populate(0, TASK_SIZE);
 +      update_resource_highwatermark(RLIMIT_MEMLOCK,
+                                     current->mm->total_vm << PAGE_SHIFT);
+
        return ret;
 }
 @@ -798,6 +803,9 @@ int user_shm_lock(size_t size, struct user_struct
*user)
        get_uid(user);
        user->locked_shm += locked;
        allowed = 1;
+
+       update_resource_highwatermark(RLIMIT_MEMLOCK,
+                                     user->locked_shm << PAGE_SHIFT);
 out:
        spin_unlock(&shmlock_user_lock);
        return allowed;
diff --git a/mm/mmap.c b/mm/mmap.c
index 305c456..c37f599 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2020,6 +2020,10 @@ static int acct_stack_growth(struct
vm_area_struct *vma, unsigned long size, uns
                return -ENOMEM;
        update_resource_highwatermark(RLIMIT_STACK, actual_size);
+       if (vma->vm_flags & VM_LOCKED)
+               update_resource_highwatermark(RLIMIT_MEMLOCK,
+                                             (mm->locked_vm + grow) <<
+                                             PAGE_SHIFT);
        return 0;
 }
diff --git a/mm/mremap.c b/mm/mremap.c
index 1f157ad..f1821335 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -394,6 +394,10 @@ static struct vm_area_struct
*vma_to_resize(unsigned long addr,
                *p = charged;
        }
 +      if (vma->vm_flags & VM_LOCKED)
+               update_resource_highwatermark(RLIMIT_MEMLOCK,
+                                             (mm->locked_vm << PAGE_SHIFT) +
+                                             new_len - old_len);
        return vma;
 }
 -- 2.8.1

Reply via email to