mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 05:39:54 -04:00
Merge "mm: support vector address ranges for process_madvise"
This commit is contained in:
commit
9faf140cf6
24 changed files with 175 additions and 27 deletions
|
|
@ -475,3 +475,4 @@
|
|||
543 common fspick sys_fspick
|
||||
544 common pidfd_open sys_pidfd_open
|
||||
# 545 reserved for clone3
|
||||
546 common process_madvise sys_process_madvise
|
||||
|
|
|
|||
|
|
@ -449,3 +449,4 @@
|
|||
433 common fspick sys_fspick
|
||||
434 common pidfd_open sys_pidfd_open
|
||||
435 common clone3 sys_clone3
|
||||
436 common process_madvise sys_process_madvise
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
#define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE + 5)
|
||||
#define __ARM_NR_COMPAT_END (__ARM_NR_COMPAT_BASE + 0x800)
|
||||
|
||||
#define __NR_compat_syscalls 436
|
||||
#define __NR_compat_syscalls 437
|
||||
#endif
|
||||
|
||||
#define __ARCH_WANT_SYS_CLONE
|
||||
|
|
|
|||
|
|
@ -879,6 +879,8 @@ __SYSCALL(__NR_fspick, sys_fspick)
|
|||
__SYSCALL(__NR_pidfd_open, sys_pidfd_open)
|
||||
#define __NR_clone3 435
|
||||
__SYSCALL(__NR_clone3, sys_clone3)
|
||||
#define __NR_process_madvise 436
|
||||
__SYSCALL(__NR_process_madvise, sys_process_madvise)
|
||||
|
||||
/*
|
||||
* Please add new compat syscalls above this comment and update
|
||||
|
|
|
|||
|
|
@ -356,3 +356,4 @@
|
|||
433 common fspick sys_fspick
|
||||
434 common pidfd_open sys_pidfd_open
|
||||
# 435 reserved for clone3
|
||||
436 common process_madvise sys_process_madvise
|
||||
|
|
|
|||
|
|
@ -435,3 +435,4 @@
|
|||
433 common fspick sys_fspick
|
||||
434 common pidfd_open sys_pidfd_open
|
||||
# 435 reserved for clone3
|
||||
436 common process_madvise sys_process_madvise
|
||||
|
|
|
|||
|
|
@ -441,3 +441,4 @@
|
|||
433 common fspick sys_fspick
|
||||
434 common pidfd_open sys_pidfd_open
|
||||
435 common clone3 sys_clone3
|
||||
436 common process_madvise sys_process_madvise
|
||||
|
|
|
|||
|
|
@ -374,3 +374,4 @@
|
|||
433 n32 fspick sys_fspick
|
||||
434 n32 pidfd_open sys_pidfd_open
|
||||
435 n32 clone3 __sys_clone3
|
||||
436 n32 process_madvise sys_process_madvise
|
||||
|
|
|
|||
|
|
@ -350,3 +350,4 @@
|
|||
433 n64 fspick sys_fspick
|
||||
434 n64 pidfd_open sys_pidfd_open
|
||||
435 n64 clone3 __sys_clone3
|
||||
436 n64 process_madvise sys_process_madvise
|
||||
|
|
|
|||
|
|
@ -433,3 +433,4 @@
|
|||
433 common fspick sys_fspick
|
||||
434 common pidfd_open sys_pidfd_open
|
||||
435 common clone3 sys_clone3_wrapper
|
||||
436 common process_madvise sys_process_madvise
|
||||
|
|
|
|||
|
|
@ -517,3 +517,4 @@
|
|||
433 common fspick sys_fspick
|
||||
434 common pidfd_open sys_pidfd_open
|
||||
435 nospu clone3 ppc_clone3
|
||||
436 common process_madvise sys_process_madvise
|
||||
|
|
|
|||
|
|
@ -438,3 +438,4 @@
|
|||
433 common fspick sys_fspick sys_fspick
|
||||
434 common pidfd_open sys_pidfd_open sys_pidfd_open
|
||||
435 common clone3 sys_clone3 sys_clone3
|
||||
443 common process_madvise sys_process_madvise sys_process_madvise
|
||||
|
|
|
|||
|
|
@ -438,3 +438,4 @@
|
|||
433 common fspick sys_fspick
|
||||
434 common pidfd_open sys_pidfd_open
|
||||
# 435 reserved for clone3
|
||||
436 common process_madvise sys_process_madvise
|
||||
|
|
|
|||
|
|
@ -481,3 +481,4 @@
|
|||
433 common fspick sys_fspick
|
||||
434 common pidfd_open sys_pidfd_open
|
||||
# 435 reserved for clone3
|
||||
436 common process_madvise sys_process_madvise
|
||||
|
|
|
|||
|
|
@ -440,3 +440,4 @@
|
|||
433 i386 fspick sys_fspick __ia32_sys_fspick
|
||||
434 i386 pidfd_open sys_pidfd_open __ia32_sys_pidfd_open
|
||||
435 i386 clone3 sys_clone3 __ia32_sys_clone3
|
||||
436 i386 process_madvise sys_process_madvise
|
||||
|
|
|
|||
|
|
@ -357,6 +357,7 @@
|
|||
433 common fspick __x64_sys_fspick
|
||||
434 common pidfd_open __x64_sys_pidfd_open
|
||||
435 common clone3 __x64_sys_clone3/ptregs
|
||||
436 common process_madvise sys_process_madvise
|
||||
|
||||
#
|
||||
# x32-specific system call numbers start at 512 to avoid cache impact
|
||||
|
|
|
|||
|
|
@ -406,3 +406,4 @@
|
|||
433 common fspick sys_fspick
|
||||
434 common pidfd_open sys_pidfd_open
|
||||
435 common clone3 sys_clone3
|
||||
443 common process_madvise sys_process_madvise
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ extern const struct file_operations pidfd_fops;
|
|||
struct file;
|
||||
|
||||
extern struct pid *pidfd_pid(const struct file *file);
|
||||
struct pid *pidfd_get_pid(unsigned int fd);
|
||||
|
||||
static inline struct pid *get_pid(struct pid *pid)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -874,6 +874,9 @@ asmlinkage long sys_munlockall(void);
|
|||
asmlinkage long sys_mincore(unsigned long start, size_t len,
|
||||
unsigned char __user * vec);
|
||||
asmlinkage long sys_madvise(unsigned long start, size_t len, int behavior);
|
||||
asmlinkage long sys_process_madvise(int which, pid_t upid,
|
||||
const struct iovec __user *vec, unsigned long vlen,
|
||||
int behavior, unsigned long flags);
|
||||
asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size,
|
||||
unsigned long prot, unsigned long pgoff,
|
||||
unsigned long flags);
|
||||
|
|
|
|||
|
|
@ -850,9 +850,11 @@ __SYSCALL(__NR_pidfd_open, sys_pidfd_open)
|
|||
#define __NR_clone3 435
|
||||
__SYSCALL(__NR_clone3, sys_clone3)
|
||||
#endif
|
||||
#define __NR_process_madvise 436
|
||||
__SYSCALL(__NR_process_madvise, sys_process_madvise)
|
||||
|
||||
#undef __NR_syscalls
|
||||
#define __NR_syscalls 436
|
||||
#define __NR_syscalls 437
|
||||
|
||||
/*
|
||||
* 32 bit systems traditionally used different
|
||||
|
|
|
|||
|
|
@ -1470,23 +1470,6 @@ end:
|
|||
return retval;
|
||||
}
|
||||
|
||||
static struct pid *pidfd_get_pid(unsigned int fd)
|
||||
{
|
||||
struct fd f;
|
||||
struct pid *pid;
|
||||
|
||||
f = fdget(fd);
|
||||
if (!f.file)
|
||||
return ERR_PTR(-EBADF);
|
||||
|
||||
pid = pidfd_pid(f.file);
|
||||
if (!IS_ERR(pid))
|
||||
get_pid(pid);
|
||||
|
||||
fdput(f);
|
||||
return pid;
|
||||
}
|
||||
|
||||
static long kernel_waitid(int which, pid_t upid, struct waitid_info *infop,
|
||||
int options, struct rusage *ru)
|
||||
{
|
||||
|
|
|
|||
17
kernel/pid.c
17
kernel/pid.c
|
|
@ -454,6 +454,23 @@ struct pid *find_ge_pid(int nr, struct pid_namespace *ns)
|
|||
return idr_get_next(&ns->idr, &nr);
|
||||
}
|
||||
|
||||
struct pid *pidfd_get_pid(unsigned int fd)
|
||||
{
|
||||
struct fd f;
|
||||
struct pid *pid;
|
||||
|
||||
f = fdget(fd);
|
||||
if (!f.file)
|
||||
return ERR_PTR(-EBADF);
|
||||
|
||||
pid = pidfd_pid(f.file);
|
||||
if (!IS_ERR(pid))
|
||||
get_pid(pid);
|
||||
|
||||
fdput(f);
|
||||
return pid;
|
||||
}
|
||||
|
||||
/**
|
||||
* pidfd_create() - Create a new pid file descriptor.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -280,6 +280,7 @@ COND_SYSCALL(mlockall);
|
|||
COND_SYSCALL(munlockall);
|
||||
COND_SYSCALL(mincore);
|
||||
COND_SYSCALL(madvise);
|
||||
COND_SYSCALL(process_madvise);
|
||||
COND_SYSCALL(remap_file_pages);
|
||||
COND_SYSCALL(mbind);
|
||||
COND_SYSCALL_COMPAT(mbind);
|
||||
|
|
|
|||
140
mm/madvise.c
140
mm/madvise.c
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/falloc.h>
|
||||
#include <linux/fadvise.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/sched/mm.h>
|
||||
#include <linux/ksm.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/file.h>
|
||||
|
|
@ -38,6 +39,7 @@
|
|||
struct madvise_walk_private {
|
||||
struct mmu_gather *tlb;
|
||||
bool pageout;
|
||||
struct task_struct *target_task;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -318,6 +320,10 @@ static int madvise_cold_or_pageout_pte_range(pmd_t *pmd,
|
|||
if (fatal_signal_pending(current))
|
||||
return -EINTR;
|
||||
|
||||
if (private->target_task &&
|
||||
fatal_signal_pending(private->target_task))
|
||||
return -EINTR;
|
||||
|
||||
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
if (pmd_trans_huge(*pmd)) {
|
||||
pmd_t orig_pmd;
|
||||
|
|
@ -479,12 +485,14 @@ static const struct mm_walk_ops cold_walk_ops = {
|
|||
};
|
||||
|
||||
static void madvise_cold_page_range(struct mmu_gather *tlb,
|
||||
struct task_struct *task,
|
||||
struct vm_area_struct *vma,
|
||||
unsigned long addr, unsigned long end)
|
||||
{
|
||||
struct madvise_walk_private walk_private = {
|
||||
.pageout = false,
|
||||
.tlb = tlb,
|
||||
.target_task = task,
|
||||
};
|
||||
|
||||
tlb_start_vma(tlb, vma);
|
||||
|
|
@ -492,7 +500,8 @@ static void madvise_cold_page_range(struct mmu_gather *tlb,
|
|||
tlb_end_vma(tlb, vma);
|
||||
}
|
||||
|
||||
static long madvise_cold(struct vm_area_struct *vma,
|
||||
static long madvise_cold(struct task_struct *task,
|
||||
struct vm_area_struct *vma,
|
||||
struct vm_area_struct **prev,
|
||||
unsigned long start_addr, unsigned long end_addr)
|
||||
{
|
||||
|
|
@ -505,19 +514,21 @@ static long madvise_cold(struct vm_area_struct *vma,
|
|||
|
||||
lru_add_drain();
|
||||
tlb_gather_mmu(&tlb, mm, start_addr, end_addr);
|
||||
madvise_cold_page_range(&tlb, vma, start_addr, end_addr);
|
||||
madvise_cold_page_range(&tlb, task, vma, start_addr, end_addr);
|
||||
tlb_finish_mmu(&tlb, start_addr, end_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void madvise_pageout_page_range(struct mmu_gather *tlb,
|
||||
struct task_struct *task,
|
||||
struct vm_area_struct *vma,
|
||||
unsigned long addr, unsigned long end)
|
||||
{
|
||||
struct madvise_walk_private walk_private = {
|
||||
.pageout = true,
|
||||
.tlb = tlb,
|
||||
.target_task = task,
|
||||
};
|
||||
|
||||
tlb_start_vma(tlb, vma);
|
||||
|
|
@ -541,7 +552,8 @@ static inline bool can_do_pageout(struct vm_area_struct *vma)
|
|||
inode_permission(file_inode(vma->vm_file), MAY_WRITE) == 0;
|
||||
}
|
||||
|
||||
static long madvise_pageout(struct vm_area_struct *vma,
|
||||
static long madvise_pageout(struct task_struct *task,
|
||||
struct vm_area_struct *vma,
|
||||
struct vm_area_struct **prev,
|
||||
unsigned long start_addr, unsigned long end_addr)
|
||||
{
|
||||
|
|
@ -557,7 +569,7 @@ static long madvise_pageout(struct vm_area_struct *vma,
|
|||
|
||||
lru_add_drain();
|
||||
tlb_gather_mmu(&tlb, mm, start_addr, end_addr);
|
||||
madvise_pageout_page_range(&tlb, vma, start_addr, end_addr);
|
||||
madvise_pageout_page_range(&tlb, task, vma, start_addr, end_addr);
|
||||
tlb_finish_mmu(&tlb, start_addr, end_addr);
|
||||
|
||||
return 0;
|
||||
|
|
@ -937,7 +949,8 @@ static int madvise_inject_error(int behavior,
|
|||
#endif
|
||||
|
||||
static long
|
||||
madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev,
|
||||
madvise_vma(struct task_struct *task, struct vm_area_struct *vma,
|
||||
struct vm_area_struct **prev,
|
||||
unsigned long start, unsigned long end, int behavior)
|
||||
{
|
||||
switch (behavior) {
|
||||
|
|
@ -946,9 +959,9 @@ madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev,
|
|||
case MADV_WILLNEED:
|
||||
return madvise_willneed(vma, prev, start, end);
|
||||
case MADV_COLD:
|
||||
return madvise_cold(vma, prev, start, end);
|
||||
return madvise_cold(task, vma, prev, start, end);
|
||||
case MADV_PAGEOUT:
|
||||
return madvise_pageout(vma, prev, start, end);
|
||||
return madvise_pageout(task, vma, prev, start, end);
|
||||
case MADV_FREE:
|
||||
case MADV_DONTNEED:
|
||||
return madvise_dontneed_free(vma, prev, start, end, behavior);
|
||||
|
|
@ -995,6 +1008,22 @@ madvise_behavior_valid(int behavior)
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
process_madvise_behavior_valid(int behavior)
|
||||
{
|
||||
switch (behavior) {
|
||||
case MADV_COLD:
|
||||
case MADV_PAGEOUT:
|
||||
#ifdef CONFIG_KSM
|
||||
case MADV_MERGEABLE:
|
||||
case MADV_UNMERGEABLE:
|
||||
#endif
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The madvise(2) system call.
|
||||
*
|
||||
|
|
@ -1042,6 +1071,11 @@ madvise_behavior_valid(int behavior)
|
|||
* MADV_DONTDUMP - the application wants to prevent pages in the given range
|
||||
* from being included in its core dump.
|
||||
* MADV_DODUMP - cancel MADV_DONTDUMP: no longer exclude from core dump.
|
||||
* MADV_COLD - the application is not expected to use this memory soon,
|
||||
* deactivate pages in this range so that they can be reclaimed
|
||||
* easily if memory pressure hanppens.
|
||||
* MADV_PAGEOUT - the application is not expected to use this memory soon,
|
||||
* page out the pages in this range immediately.
|
||||
*
|
||||
* return values:
|
||||
* zero - success
|
||||
|
|
@ -1148,7 +1182,8 @@ int do_madvise(struct task_struct *target_task, struct mm_struct *mm,
|
|||
tmp = end;
|
||||
|
||||
/* Here vma->vm_start <= start < tmp <= (end|vma->vm_end). */
|
||||
error = madvise_vma(vma, &prev, start, tmp, behavior);
|
||||
error = madvise_vma(target_task, vma, &prev,
|
||||
start, tmp, behavior);
|
||||
if (error)
|
||||
goto out;
|
||||
start = tmp;
|
||||
|
|
@ -1176,3 +1211,92 @@ SYSCALL_DEFINE3(madvise, unsigned long, start, size_t, len_in, int, behavior)
|
|||
{
|
||||
return do_madvise(current, current->mm, start, len_in, behavior);
|
||||
}
|
||||
|
||||
static int do_process_madvise(struct task_struct *target_task,
|
||||
struct mm_struct *mm, struct iov_iter *iter, int behavior)
|
||||
{
|
||||
struct iovec iovec;
|
||||
int ret = 0;
|
||||
|
||||
while (iov_iter_count(iter)) {
|
||||
iovec = iov_iter_iovec(iter);
|
||||
ret = do_madvise(target_task, mm, (unsigned long)iovec.iov_base,
|
||||
iovec.iov_len, behavior);
|
||||
if (ret < 0)
|
||||
break;
|
||||
iov_iter_advance(iter, iovec.iov_len);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE6(process_madvise, int, which, pid_t, upid,
|
||||
const struct iovec __user *, vec, unsigned long, vlen,
|
||||
int, behavior, unsigned long, flags)
|
||||
{
|
||||
ssize_t ret;
|
||||
struct pid *pid;
|
||||
struct task_struct *task;
|
||||
struct mm_struct *mm;
|
||||
struct iovec iovstack[UIO_FASTIOV];
|
||||
struct iovec *iov = iovstack;
|
||||
struct iov_iter iter;
|
||||
|
||||
if (flags != 0)
|
||||
return -EINVAL;
|
||||
|
||||
switch (which) {
|
||||
case P_PID:
|
||||
if (upid <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
pid = find_get_pid(upid);
|
||||
if (!pid)
|
||||
return -ESRCH;
|
||||
break;
|
||||
case P_PIDFD:
|
||||
if (upid < 0)
|
||||
return -EINVAL;
|
||||
|
||||
pid = pidfd_get_pid(upid);
|
||||
if (IS_ERR(pid))
|
||||
return PTR_ERR(pid);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
task = get_pid_task(pid, PIDTYPE_PID);
|
||||
if (!task) {
|
||||
ret = -ESRCH;
|
||||
goto put_pid;
|
||||
}
|
||||
|
||||
if (task->mm != current->mm &&
|
||||
!process_madvise_behavior_valid(behavior)) {
|
||||
ret = -EINVAL;
|
||||
goto release_task;
|
||||
}
|
||||
|
||||
mm = mm_access(task, PTRACE_MODE_ATTACH_FSCREDS);
|
||||
if (IS_ERR_OR_NULL(mm)) {
|
||||
ret = IS_ERR(mm) ? PTR_ERR(mm) : -ESRCH;
|
||||
goto release_task;
|
||||
}
|
||||
|
||||
ret = import_iovec(READ, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter);
|
||||
if (ret >= 0) {
|
||||
size_t total_len = iov_iter_count(&iter);
|
||||
|
||||
ret = do_process_madvise(task, mm, &iter, behavior);
|
||||
if (ret >= 0)
|
||||
ret = total_len - iov_iter_count(&iter);
|
||||
kfree(iov);
|
||||
}
|
||||
mmput(mm);
|
||||
release_task:
|
||||
put_task_struct(task);
|
||||
put_pid:
|
||||
put_pid(pid);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue