mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-06 03:45:24 -04:00
Merge "mm: Remove shrink_page"
This commit is contained in:
commit
c606037c2d
6 changed files with 187 additions and 2 deletions
|
|
@ -3237,6 +3237,9 @@ static const struct pid_entry tgid_base_stuff[] = {
|
|||
REG("mounts", S_IRUGO, proc_mounts_operations),
|
||||
REG("mountinfo", S_IRUGO, proc_mountinfo_operations),
|
||||
REG("mountstats", S_IRUSR, proc_mountstats_operations),
|
||||
#ifdef CONFIG_PROCESS_RECLAIM
|
||||
REG("reclaim", 0200, proc_reclaim_operations),
|
||||
#endif
|
||||
#ifdef CONFIG_PROC_PAGE_MONITOR
|
||||
REG("clear_refs", S_IWUSR, proc_clear_refs_operations),
|
||||
REG("smaps", S_IRUGO, proc_pid_smaps_operations),
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@ struct pde_opener {
|
|||
extern const struct inode_operations proc_link_inode_operations;
|
||||
extern const struct inode_operations proc_pid_link_inode_operations;
|
||||
extern const struct super_operations proc_sops;
|
||||
extern const struct file_operations proc_reclaim_operations;
|
||||
|
||||
void proc_init_kmemcache(void);
|
||||
void set_proc_pid_nlink(void);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/shmem_fs.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/pkeys.h>
|
||||
#include <linux/mm_inline.h>
|
||||
|
||||
#include <asm/elf.h>
|
||||
#include <asm/tlb.h>
|
||||
|
|
@ -1708,6 +1709,124 @@ const struct file_operations proc_pagemap_operations = {
|
|||
};
|
||||
#endif /* CONFIG_PROC_PAGE_MONITOR */
|
||||
|
||||
#ifdef CONFIG_PROCESS_RECLAIM
|
||||
static int reclaim_pte_range(pmd_t *pmd, unsigned long addr,
|
||||
unsigned long end, struct mm_walk *walk)
|
||||
{
|
||||
struct vm_area_struct *vma = walk->private;
|
||||
pte_t *pte, ptent;
|
||||
spinlock_t *ptl;
|
||||
struct page *page;
|
||||
LIST_HEAD(page_list);
|
||||
int isolated;
|
||||
|
||||
split_huge_pmd(vma, addr, pmd);
|
||||
if (pmd_trans_unstable(pmd))
|
||||
return 0;
|
||||
cont:
|
||||
isolated = 0;
|
||||
pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
|
||||
for (; addr != end; pte++, addr += PAGE_SIZE) {
|
||||
ptent = *pte;
|
||||
if (!pte_present(ptent))
|
||||
continue;
|
||||
|
||||
page = vm_normal_page(vma, addr, ptent);
|
||||
if (!page)
|
||||
continue;
|
||||
|
||||
if (isolate_lru_page(page))
|
||||
continue;
|
||||
|
||||
list_add(&page->lru, &page_list);
|
||||
inc_node_page_state(page, NR_ISOLATED_ANON +
|
||||
page_is_file_cache(page));
|
||||
isolated++;
|
||||
if (isolated >= SWAP_CLUSTER_MAX)
|
||||
break;
|
||||
}
|
||||
pte_unmap_unlock(pte - 1, ptl);
|
||||
reclaim_pages_from_list(&page_list);
|
||||
if (addr != end)
|
||||
goto cont;
|
||||
|
||||
cond_resched();
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum reclaim_type {
|
||||
RECLAIM_FILE,
|
||||
RECLAIM_ANON,
|
||||
RECLAIM_ALL,
|
||||
RECLAIM_RANGE,
|
||||
};
|
||||
|
||||
static ssize_t reclaim_write(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct task_struct *task;
|
||||
char buffer[PROC_NUMBUF];
|
||||
struct mm_struct *mm;
|
||||
struct vm_area_struct *vma;
|
||||
enum reclaim_type type;
|
||||
char *type_buf;
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
if (count > sizeof(buffer) - 1)
|
||||
count = sizeof(buffer) - 1;
|
||||
|
||||
if (copy_from_user(buffer, buf, count))
|
||||
return -EFAULT;
|
||||
|
||||
type_buf = strstrip(buffer);
|
||||
if (!strcmp(type_buf, "file"))
|
||||
type = RECLAIM_FILE;
|
||||
else if (!strcmp(type_buf, "anon"))
|
||||
type = RECLAIM_ANON;
|
||||
else if (!strcmp(type_buf, "all"))
|
||||
type = RECLAIM_ALL;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
task = get_proc_task(file->f_path.dentry->d_inode);
|
||||
if (!task)
|
||||
return -ESRCH;
|
||||
|
||||
mm = get_task_mm(task);
|
||||
if (mm) {
|
||||
const struct mm_walk_ops reclaim_walk_ops = {
|
||||
.pmd_entry = reclaim_pte_range,
|
||||
};
|
||||
|
||||
down_read(&mm->mmap_sem);
|
||||
for (vma = mm->mmap; vma; vma = vma->vm_next) {
|
||||
|
||||
if (is_vm_hugetlb_page(vma))
|
||||
continue;
|
||||
|
||||
if (type == RECLAIM_ANON && vma->vm_file)
|
||||
continue;
|
||||
if (type == RECLAIM_FILE && !vma->vm_file)
|
||||
continue;
|
||||
|
||||
walk_page_range(mm, vma->vm_start, vma->vm_end,
|
||||
&reclaim_walk_ops, vma);
|
||||
}
|
||||
flush_tlb_mm(mm);
|
||||
up_read(&mm->mmap_sem);
|
||||
mmput(mm);
|
||||
}
|
||||
put_task_struct(task);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
const struct file_operations proc_reclaim_operations = {
|
||||
.write = reclaim_write,
|
||||
.llseek = noop_llseek,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NUMA
|
||||
|
||||
struct numa_maps {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@
|
|||
#include <linux/memcontrol.h>
|
||||
#include <linux/highmem.h>
|
||||
|
||||
extern int isolate_lru_page(struct page *page);
|
||||
extern void putback_lru_page(struct page *page);
|
||||
extern unsigned long reclaim_pages_from_list(struct list_head *page_list);
|
||||
|
||||
/*
|
||||
* The anon_vma heads a list of private "related" vmas, to scan if
|
||||
* an anonymous page pointing to this anon_vma needs to be unmapped:
|
||||
|
|
|
|||
14
mm/Kconfig
14
mm/Kconfig
|
|
@ -832,3 +832,17 @@ config OOM_TASK_PRIORITY_ADJ_LIMIT
|
|||
before considering tasks with a lower oom_score_adj value.
|
||||
|
||||
endmenu
|
||||
|
||||
config PROCESS_RECLAIM
|
||||
bool "Enable process reclaim"
|
||||
depends on PROC_FS
|
||||
depends on QGKI
|
||||
default y
|
||||
help
|
||||
It allows to reclaim pages of the process by /proc/pid/reclaim.
|
||||
|
||||
(echo file > /proc/PID/reclaim) reclaims file-backed pages only.
|
||||
(echo anon > /proc/PID/reclaim) reclaims anonymous pages only.
|
||||
(echo all > /proc/PID/reclaim) reclaims all pages.
|
||||
|
||||
Any other value is ignored.
|
||||
|
|
|
|||
48
mm/vmscan.c
48
mm/vmscan.c
|
|
@ -1152,6 +1152,8 @@ static unsigned long shrink_page_list(struct list_head *page_list,
|
|||
goto keep;
|
||||
|
||||
VM_BUG_ON_PAGE(PageActive(page), page);
|
||||
if (pgdat)
|
||||
VM_BUG_ON_PAGE(page_pgdat(page) != pgdat, page);
|
||||
|
||||
nr_pages = compound_nr(page);
|
||||
|
||||
|
|
@ -1238,7 +1240,8 @@ static unsigned long shrink_page_list(struct list_head *page_list,
|
|||
/* Case 1 above */
|
||||
if (current_is_kswapd() &&
|
||||
PageReclaim(page) &&
|
||||
test_bit(PGDAT_WRITEBACK, &pgdat->flags)) {
|
||||
(pgdat &&
|
||||
test_bit(PGDAT_WRITEBACK, &pgdat->flags))) {
|
||||
stat->nr_immediate++;
|
||||
goto activate_locked;
|
||||
|
||||
|
|
@ -1372,7 +1375,8 @@ static unsigned long shrink_page_list(struct list_head *page_list,
|
|||
*/
|
||||
if (page_is_file_cache(page) &&
|
||||
(!current_is_kswapd() || !PageReclaim(page) ||
|
||||
!test_bit(PGDAT_DIRTY, &pgdat->flags))) {
|
||||
(pgdat &&
|
||||
!test_bit(PGDAT_DIRTY, &pgdat->flags)))) {
|
||||
/*
|
||||
* Immediately reclaim when written back.
|
||||
* Similar in principal to deactivate_page()
|
||||
|
|
@ -1495,6 +1499,13 @@ free_it:
|
|||
(*get_compound_page_dtor(page))(page);
|
||||
else
|
||||
list_add(&page->lru, &free_pages);
|
||||
/*
|
||||
* If pagelist are from multiple nodes, we should decrease
|
||||
* NR_ISOLATED_ANON + x on freed pages in here.
|
||||
*/
|
||||
if (!pgdat)
|
||||
dec_node_page_state(page, NR_ISOLATED_ANON +
|
||||
page_is_file_cache(page));
|
||||
continue;
|
||||
|
||||
activate_locked_split:
|
||||
|
|
@ -1565,6 +1576,39 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone,
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROCESS_RECLAIM
|
||||
unsigned long reclaim_pages_from_list(struct list_head *page_list)
|
||||
{
|
||||
struct scan_control sc = {
|
||||
.gfp_mask = GFP_KERNEL,
|
||||
.priority = DEF_PRIORITY,
|
||||
.may_writepage = 1,
|
||||
.may_unmap = 1,
|
||||
.may_swap = 1,
|
||||
};
|
||||
|
||||
unsigned long nr_reclaimed;
|
||||
struct reclaim_stat stat;
|
||||
struct page *page;
|
||||
|
||||
list_for_each_entry(page, page_list, lru)
|
||||
ClearPageActive(page);
|
||||
|
||||
nr_reclaimed = shrink_page_list(page_list, NULL, &sc,
|
||||
TTU_IGNORE_ACCESS, &stat, true);
|
||||
|
||||
while (!list_empty(page_list)) {
|
||||
page = lru_to_page(page_list);
|
||||
list_del(&page->lru);
|
||||
dec_node_page_state(page, NR_ISOLATED_ANON +
|
||||
page_is_file_cache(page));
|
||||
putback_lru_page(page);
|
||||
}
|
||||
|
||||
return nr_reclaimed;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Attempt to remove the specified page from its LRU. Only take this page
|
||||
* if it is of the appropriate PageActive status. Pages which are being
|
||||
|
|
|
|||
Loading…
Reference in a new issue