mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 02:21:52 +09:00
mm: pin locked file after fault. [1/2]
PD#SWPL-95400 Problem: If we pin a file in android, the whole data of this file will be loaded to DDR, but most of these data may not be used, this caused memory waste. Solution: delay mark mlocked flags for unevictable pages until it has been faulted. You can use following command to disable this function: echo 0 > /proc/sys/vm/shrink_unevictable Verify: sc2_ah212 Change-Id: I05bb7654cc228604fe692429efbe40af713ca5c3 Signed-off-by: Jianxiong Pan <jianxiong.pan@amlogic.com>
This commit is contained in:
committed by
Dongjin Kim
parent
0f59e46198
commit
07622f00e6
19
mm/gup.c
19
mm/gup.c
@@ -21,6 +21,9 @@
|
||||
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#ifdef CONFIG_AMLOGIC_PIN_LOCKED_FILE
|
||||
#include <linux/amlogic/pin_file.h>
|
||||
#endif
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
@@ -624,6 +627,21 @@ retry:
|
||||
* when it attempts to reclaim the page.
|
||||
*/
|
||||
if (page->mapping && trylock_page(page)) {
|
||||
#ifdef CONFIG_AMLOGIC_PIN_LOCKED_FILE
|
||||
struct address_space *mapping;
|
||||
|
||||
mapping = page_mapping(page);
|
||||
if (mapping &&
|
||||
test_bit(AS_LOCK_MAPPING, &mapping->flags) &&
|
||||
sysctrl_shrink_unevictable) {
|
||||
unlock_page(page);
|
||||
} else {
|
||||
/* same as #else */
|
||||
lru_add_drain();
|
||||
mlock_vma_page(page);
|
||||
unlock_page(page);
|
||||
}
|
||||
#else
|
||||
lru_add_drain(); /* push cached pages to LRU */
|
||||
/*
|
||||
* Because we lock page here, and migration is
|
||||
@@ -633,6 +651,7 @@ retry:
|
||||
*/
|
||||
mlock_vma_page(page);
|
||||
unlock_page(page);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
out:
|
||||
|
||||
78
mm/memory.c
78
mm/memory.c
@@ -85,6 +85,12 @@
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/tlb.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#ifdef CONFIG_AMLOGIC_PIN_LOCKED_FILE
|
||||
#include <linux/amlogic/pin_file.h>
|
||||
#endif
|
||||
#ifdef CONFIG_AMLOGIC_MEM_DEBUG
|
||||
#include <linux/amlogic/mem_debug.h>
|
||||
#endif
|
||||
|
||||
#include "pgalloc-track.h"
|
||||
#include "internal.h"
|
||||
@@ -4929,6 +4935,48 @@ unlock:
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_PIN_LOCKED_FILE
|
||||
static bool __restore_locked_page(struct page *page, struct vm_area_struct *vma,
|
||||
unsigned long addr, void *arg)
|
||||
{
|
||||
int ret;
|
||||
pte_t old_pte, *pte;
|
||||
spinlock_t *ptl; /* pte lock */
|
||||
|
||||
if (vma->vm_flags & (VM_LOCKED | VM_LOCKONFAULT)) {
|
||||
if (addr < vma->vm_start || addr >= vma->vm_end)
|
||||
return -EFAULT;
|
||||
if (!page_count(page))
|
||||
return -EINVAL;
|
||||
|
||||
pte = get_locked_pte(vma->vm_mm, addr, &ptl);
|
||||
if (!pte)
|
||||
return true;
|
||||
old_pte = *pte;
|
||||
pte_unmap_unlock(pte, ptl);
|
||||
/* already refaulted */
|
||||
if (pte_valid(old_pte) && pte_pfn(old_pte) == page_to_pfn(page))
|
||||
return true;
|
||||
|
||||
ret = insert_page(vma, addr, page, vma->vm_page_prot);
|
||||
pr_debug("%s, restore page:%lx for addr:%lx, vma:%px, ret:%d, old_pte:%llx\n",
|
||||
__func__, page_to_pfn(page), addr, vma, ret,
|
||||
(unsigned long long)pte_val(old_pte));
|
||||
return ret ? false : true;
|
||||
}
|
||||
return true; /* keep loop */
|
||||
}
|
||||
|
||||
static void restore_locked_page(struct page *page)
|
||||
{
|
||||
struct rmap_walk_control rwc = {
|
||||
.rmap_one = __restore_locked_page,
|
||||
};
|
||||
|
||||
rmap_walk(page, &rwc);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* By the time we get here, we already hold the mm semaphore
|
||||
*
|
||||
@@ -4944,6 +4992,9 @@ static vm_fault_t __handle_mm_fault(struct vm_area_struct *vma,
|
||||
.flags = flags,
|
||||
.pgoff = linear_page_index(vma, address),
|
||||
.gfp_mask = __get_fault_gfp_mask(vma),
|
||||
#ifdef CONFIG_AMLOGIC_PIN_LOCKED_FILE
|
||||
.pte = NULL,
|
||||
#endif
|
||||
};
|
||||
unsigned int dirty = flags & FAULT_FLAG_WRITE;
|
||||
struct mm_struct *mm = vma->vm_mm;
|
||||
@@ -5055,7 +5106,14 @@ static vm_fault_t __handle_mm_fault(struct vm_area_struct *vma,
|
||||
if (!vmf.pte && uffd_missing_sigbus)
|
||||
return VM_FAULT_SIGBUS;
|
||||
|
||||
return handle_pte_fault(&vmf);
|
||||
#ifdef CONFIG_AMLOGIC_MEM_DEBUG
|
||||
ret = handle_pte_fault(&vmf);
|
||||
if (!ret && vma->vm_flags & VM_LOCKED)
|
||||
mlock_fault_size++;
|
||||
return ret;
|
||||
#else
|
||||
return handle_pte_fault(&vmf);
|
||||
#endif
|
||||
|
||||
spf_fail:
|
||||
speculative_page_walk_end();
|
||||
@@ -5185,7 +5243,25 @@ retry_pud:
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_PIN_LOCKED_FILE
|
||||
ret = handle_pte_fault(&vmf);
|
||||
if (!ret) {
|
||||
struct page *page = NULL;
|
||||
|
||||
page = aml_mlock_page_as_lock_mapping(vma, mm, &vmf, address);
|
||||
if (page)
|
||||
restore_locked_page(page);
|
||||
}
|
||||
return ret;
|
||||
#endif
|
||||
#ifdef CONFIG_AMLOGIC_MEM_DEBUG
|
||||
ret = handle_pte_fault(&vmf);
|
||||
if (!ret && vma->vm_flags & VM_LOCKED)
|
||||
mlock_fault_size++;
|
||||
return ret;
|
||||
#else
|
||||
return handle_pte_fault(&vmf);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -54,6 +54,9 @@
|
||||
#include <linux/amlogic/aml_cma.h>
|
||||
#include <linux/delay.h>
|
||||
#endif
|
||||
#ifdef CONFIG_AMLOGIC_PIN_LOCKED_FILE
|
||||
#include <linux/amlogic/pin_file.h>
|
||||
#endif
|
||||
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
@@ -1295,6 +1298,10 @@ out:
|
||||
else
|
||||
put_page(newpage);
|
||||
}
|
||||
#ifdef CONFIG_AMLOGIC_PIN_LOCKED_FILE
|
||||
if (reason == MR_CONTIG_RANGE && rc == MIGRATEPAGE_SUCCESS)
|
||||
aml_clear_pin_locked_file(page);
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
10
mm/mlock.c
10
mm/mlock.c
@@ -25,6 +25,9 @@
|
||||
#include <linux/memcontrol.h>
|
||||
#include <linux/mm_inline.h>
|
||||
#include <linux/secretmem.h>
|
||||
#ifdef CONFIG_AMLOGIC_PIN_LOCKED_FILE
|
||||
#include <linux/amlogic/pin_file.h>
|
||||
#endif
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
@@ -193,6 +196,7 @@ unsigned int munlock_vma_page(struct page *page)
|
||||
/*
|
||||
* convert get_user_pages() return value to posix mlock() error
|
||||
*/
|
||||
#ifndef CONFIG_AMLOGIC_PIN_LOCKED_FILE_V2
|
||||
static int __mlock_posix_error_return(long retval)
|
||||
{
|
||||
if (retval == -EFAULT)
|
||||
@@ -201,6 +205,7 @@ static int __mlock_posix_error_return(long retval)
|
||||
retval = -EAGAIN;
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Prepare page for fast batched LRU putback via putback_lru_evictable_pagevec()
|
||||
@@ -588,6 +593,9 @@ static int apply_vma_lock_flags(unsigned long start, size_t len,
|
||||
tmp = vma->vm_end;
|
||||
if (tmp > end)
|
||||
tmp = end;
|
||||
#ifdef CONFIG_AMLOGIC_PIN_LOCKED_FILE
|
||||
reset_page_vma_flags(vma, flags);
|
||||
#endif
|
||||
error = mlock_fixup(vma, &prev, nstart, tmp, newflags);
|
||||
if (error)
|
||||
break;
|
||||
@@ -686,9 +694,11 @@ static __must_check int do_mlock(unsigned long start, size_t len, vm_flags_t fla
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
#ifndef CONFIG_AMLOGIC_PIN_LOCKED_FILE_V2
|
||||
error = __mm_populate(start, len, 0);
|
||||
if (error)
|
||||
return __mlock_posix_error_return(error);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
17
mm/rmap.c
17
mm/rmap.c
@@ -80,6 +80,9 @@
|
||||
#include <trace/events/tlb.h>
|
||||
|
||||
#include <trace/hooks/mm.h>
|
||||
#ifdef CONFIG_AMLOGIC_PIN_LOCKED_FILE
|
||||
#include <linux/amlogic/pin_file.h>
|
||||
#endif
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
@@ -1471,8 +1474,14 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
|
||||
* cleared). But stop unmapping even in those cases.
|
||||
*/
|
||||
if (!PageTransCompound(page) || (PageHead(page) &&
|
||||
!PageDoubleMap(page) && !PageAnon(page)))
|
||||
!PageDoubleMap(page) && !PageAnon(page)))
|
||||
#ifdef CONFIG_AMLOGIC_PIN_LOCKED_FILE
|
||||
/* only keep refault pages */
|
||||
if (aml_is_pin_locked_file(page))
|
||||
mlock_vma_page(page);
|
||||
#else
|
||||
mlock_vma_page(page);
|
||||
#endif
|
||||
page_vma_mapped_walk_done(&pvmw);
|
||||
ret = false;
|
||||
break;
|
||||
@@ -2036,7 +2045,13 @@ static bool page_mlock_one(struct page *page, struct vm_area_struct *vma,
|
||||
* nor on an Anon THP (which may still be PTE-mapped
|
||||
* after DoubleMap was cleared).
|
||||
*/
|
||||
#ifdef CONFIG_AMLOGIC_PIN_LOCKED_FILE
|
||||
/* only keep refault pages */
|
||||
if (aml_is_pin_locked_file(page))
|
||||
mlock_vma_page(page);
|
||||
#else
|
||||
mlock_vma_page(page);
|
||||
#endif
|
||||
/*
|
||||
* No need to scan further once the page is marked
|
||||
* as mlocked.
|
||||
|
||||
10
mm/vmscan.c
10
mm/vmscan.c
@@ -77,6 +77,9 @@
|
||||
#ifdef CONFIG_AMLOGIC_CMA
|
||||
#include <linux/amlogic/aml_cma.h>
|
||||
#endif
|
||||
#ifdef CONFIG_AMLOGIC_PIN_LOCKED_FILE
|
||||
#include <linux/amlogic/pin_file.h>
|
||||
#endif
|
||||
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(mm_vmscan_direct_reclaim_begin);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(mm_vmscan_direct_reclaim_end);
|
||||
@@ -1674,6 +1677,13 @@ retry:
|
||||
enum ttu_flags flags = TTU_BATCH_FLUSH;
|
||||
bool was_swapbacked = PageSwapBacked(page);
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_PIN_LOCKED_FILE
|
||||
if (mapping &&
|
||||
test_bit(AS_LOCK_MAPPING, &mapping->flags) &&
|
||||
!aml_is_pin_locked_file(page) &&
|
||||
!PageMlocked(page))
|
||||
flags |= TTU_IGNORE_MLOCK;
|
||||
#endif
|
||||
if (unlikely(PageTransHuge(page)))
|
||||
flags |= TTU_SPLIT_HUGE_PMD;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user