mm: introduce MMF_VM_PREFERRDED flag From: Konstantin Khlebnikov This patch introduce mm->flags bit: MMF_VM_PREFERRED, which doubles access bit weight for this mm. Currently the only one effect: mm with this bit activates mapped file pages after first touch, if vma does not marked as sequentially accessed. This should be per-vma sign, but there no free bits in vma->vm_flags, maybe we can make this stuff 64-only. interface: prctl(PR_SET_MM_PREFERRED, 1) to set and prctl(PR_SET_MM_PREFERRED, 0) to clear. Signed-off-by: Konstantin Khlebnikov --- include/linux/prctl.h | 2 ++ include/linux/sched.h | 1 + kernel/sys.c | 17 +++++++++++++++++ mm/rmap.c | 5 ++++- 4 files changed, 24 insertions(+), 1 deletions(-) diff --git a/include/linux/prctl.h b/include/linux/prctl.h index 7ddc7f1..d0f9ceb 100644 --- a/include/linux/prctl.h +++ b/include/linux/prctl.h @@ -114,4 +114,6 @@ # define PR_SET_MM_START_BRK 6 # define PR_SET_MM_BRK 7 +#define PR_SET_MM_PREFERRED 36 + #endif /* _LINUX_PRCTL_H */ diff --git a/include/linux/sched.h b/include/linux/sched.h index 75c15c5..b60883a 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -437,6 +437,7 @@ extern int get_dumpable(struct mm_struct *mm); /* leave room for more dump flags */ #define MMF_VM_MERGEABLE 16 /* KSM may merge identical pages */ #define MMF_VM_HUGEPAGE 17 /* set when VM_HUGEPAGE is set on vma */ +#define MMF_VM_PREFERRED 18 /* Double pte access bits weight */ #define MMF_INIT_MASK (MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK) diff --git a/kernel/sys.c b/kernel/sys.c index 4070153..bacf8d5 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1810,6 +1810,20 @@ static int prctl_set_mm(int opt, unsigned long addr, } #endif +static int set_mm_preferred(struct mm_struct *mm, int state) +{ + switch (state) { + case 0: + clear_bit(MMF_VM_PREFERRED, &mm->flags); + return 0; + case 1: + set_bit(MMF_VM_PREFERRED, &mm->flags); + return 0; + default: + return -EINVAL; + } +} + SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, unsigned long, arg4, unsigned long, arg5) { @@ -1962,6 +1976,9 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, case PR_SET_MM: error = prctl_set_mm(arg2, arg3, arg4, arg5); break; + case PR_SET_MM_PREFERRED: + error = set_mm_preferred(me->mm, arg2); + break; default: error = -EINVAL; break; diff --git a/mm/rmap.c b/mm/rmap.c index 78cc46b..b0fd1d1 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -766,8 +766,11 @@ int page_referenced_one(struct page *page, struct vm_area_struct *vma, (*mapcount)--; - if (referenced) + if (referenced) { + if (test_bit(MMF_VM_PREFERRED, &mm->flags)) + referenced <<= 1; *vm_flags |= vma->vm_flags; + } out: return referenced; }