mm: add account_locked_vm utility function
locked_vm accounting is done roughly the same way in five places, so unify them in a helper. Include the helper's caller in the debug print to distinguish between callsites. Error codes stay the same, so user-visible behavior does too. The one exception is that the -EPERM case in tce_account_locked_vm is removed because Alexey has never seen it triggered. [daniel.m.jordan@oracle.com: v3] Link: http://lkml.kernel.org/r/20190529205019.20927-1-daniel.m.jordan@oracle.com [sfr@canb.auug.org.au: fix mm/util.c] Link: http://lkml.kernel.org/r/20190524175045.26897-1-daniel.m.jordan@oracle.com Signed-off-by: Daniel Jordan <daniel.m.jordan@oracle.com> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au> Tested-by: Alexey Kardashevskiy <aik@ozlabs.ru> Acked-by: Alex Williamson <alex.williamson@redhat.com> Cc: Alan Tull <atull@kernel.org> Cc: Alex Williamson <alex.williamson@redhat.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Christoph Lameter <cl@linux.com> Cc: Christophe Leroy <christophe.leroy@c-s.fr> Cc: Davidlohr Bueso <dave@stgolabs.net> Cc: Jason Gunthorpe <jgg@mellanox.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Moritz Fischer <mdf@kernel.org> Cc: Paul Mackerras <paulus@ozlabs.org> Cc: Steve Sistare <steven.sistare@oracle.com> Cc: Wu Hao <hao.wu@intel.com> Cc: Ira Weiny <ira.weiny@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:

committed by
Linus Torvalds

parent
73b20c84d4
commit
79eb597cba
75
mm/util.c
75
mm/util.c
@@ -7,6 +7,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/sched/mm.h>
|
||||
#include <linux/sched/signal.h>
|
||||
#include <linux/sched/task_stack.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/swap.h>
|
||||
@@ -300,6 +301,80 @@ void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack)
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* __account_locked_vm - account locked pages to an mm's locked_vm
|
||||
* @mm: mm to account against
|
||||
* @pages: number of pages to account
|
||||
* @inc: %true if @pages should be considered positive, %false if not
|
||||
* @task: task used to check RLIMIT_MEMLOCK
|
||||
* @bypass_rlim: %true if checking RLIMIT_MEMLOCK should be skipped
|
||||
*
|
||||
* Assumes @task and @mm are valid (i.e. at least one reference on each), and
|
||||
* that mmap_sem is held as writer.
|
||||
*
|
||||
* Return:
|
||||
* * 0 on success
|
||||
* * -ENOMEM if RLIMIT_MEMLOCK would be exceeded.
|
||||
*/
|
||||
int __account_locked_vm(struct mm_struct *mm, unsigned long pages, bool inc,
|
||||
struct task_struct *task, bool bypass_rlim)
|
||||
{
|
||||
unsigned long locked_vm, limit;
|
||||
int ret = 0;
|
||||
|
||||
lockdep_assert_held_write(&mm->mmap_sem);
|
||||
|
||||
locked_vm = mm->locked_vm;
|
||||
if (inc) {
|
||||
if (!bypass_rlim) {
|
||||
limit = task_rlimit(task, RLIMIT_MEMLOCK) >> PAGE_SHIFT;
|
||||
if (locked_vm + pages > limit)
|
||||
ret = -ENOMEM;
|
||||
}
|
||||
if (!ret)
|
||||
mm->locked_vm = locked_vm + pages;
|
||||
} else {
|
||||
WARN_ON_ONCE(pages > locked_vm);
|
||||
mm->locked_vm = locked_vm - pages;
|
||||
}
|
||||
|
||||
pr_debug("%s: [%d] caller %ps %c%lu %lu/%lu%s\n", __func__, task->pid,
|
||||
(void *)_RET_IP_, (inc) ? '+' : '-', pages << PAGE_SHIFT,
|
||||
locked_vm << PAGE_SHIFT, task_rlimit(task, RLIMIT_MEMLOCK),
|
||||
ret ? " - exceeded" : "");
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__account_locked_vm);
|
||||
|
||||
/**
|
||||
* account_locked_vm - account locked pages to an mm's locked_vm
|
||||
* @mm: mm to account against, may be NULL
|
||||
* @pages: number of pages to account
|
||||
* @inc: %true if @pages should be considered positive, %false if not
|
||||
*
|
||||
* Assumes a non-NULL @mm is valid (i.e. at least one reference on it).
|
||||
*
|
||||
* Return:
|
||||
* * 0 on success, or if mm is NULL
|
||||
* * -ENOMEM if RLIMIT_MEMLOCK would be exceeded.
|
||||
*/
|
||||
int account_locked_vm(struct mm_struct *mm, unsigned long pages, bool inc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (pages == 0 || !mm)
|
||||
return 0;
|
||||
|
||||
down_write(&mm->mmap_sem);
|
||||
ret = __account_locked_vm(mm, pages, inc, current,
|
||||
capable(CAP_IPC_LOCK));
|
||||
up_write(&mm->mmap_sem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(account_locked_vm);
|
||||
|
||||
unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr,
|
||||
unsigned long len, unsigned long prot,
|
||||
unsigned long flag, unsigned long pgoff)
|
||||
|
Reference in New Issue
Block a user