diff --git a/include/linux/mm.h b/include/linux/mm.h index e097df6..14ae918 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -771,6 +771,7 @@ struct zap_details { pgoff_t last_index; /* Highest page->index to unmap */ spinlock_t *i_mmap_lock; /* For unmap_mapping_range: */ unsigned long truncate_count; /* Compare vm_truncate_count */ + int ignore_reference; }; struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr, diff --git a/mm/madvise.c b/mm/madvise.c index 319528b..fdb0253 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -162,18 +162,22 @@ static long madvise_dontneed(struct vm_area_struct * vma, struct vm_area_struct ** prev, unsigned long start, unsigned long end) { + struct zap_details details ; + *prev = vma; if (vma->vm_flags & (VM_LOCKED|VM_HUGETLB|VM_PFNMAP)) return -EINVAL; if (unlikely(vma->vm_flags & VM_NONLINEAR)) { - struct zap_details details = { - .nonlinear_vma = vma, - .last_index = ULONG_MAX, - }; - zap_page_range(vma, start, end - start, &details); - } else - zap_page_range(vma, start, end - start, NULL); + details.nonlinear_vma = vma; + details.last_index = ULONG_MAX; + } else { + details.nonlinear_vma = NULL; + details.last_index = NULL; + } + + details.ignore_reference = true; + zap_page_range(vma, start, end - start, &details); return 0; } diff --git a/mm/memory.c b/mm/memory.c index ebfeedf..8aa0190 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -897,9 +897,13 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb, pte_t *pte; spinlock_t *ptl; int rss[NR_MM_COUNTERS]; - + bool ignore_reference = false; init_rss_vec(rss); + if (details && ((!details->check_mapping && !details->nonlinear_vma) + || !details->ignore_reference)) + details = NULL; + pte = pte_offset_map_lock(mm, pmd, addr, &ptl); arch_enter_lazy_mmu_mode(); do { @@ -949,7 +953,8 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb, if (pte_dirty(ptent)) set_page_dirty(page); if (pte_young(ptent) && - likely(!VM_SequentialReadHint(vma))) + likely(!VM_SequentialReadHint(vma)) && + likely(!ignore_reference)) mark_page_accessed(page); rss[MM_FILEPAGES]--; } @@ -1038,8 +1043,6 @@ static unsigned long unmap_page_range(struct mmu_gather *tlb, pgd_t *pgd; unsigned long next; - if (details && !details->check_mapping && !details->nonlinear_vma) - details = NULL; BUG_ON(addr >= end); mem_cgroup_uncharge_start(); @@ -1102,7 +1105,8 @@ unsigned long unmap_vmas(struct mmu_gather **tlbp, unsigned long tlb_start = 0; /* For tlb_finish_mmu */ int tlb_start_valid = 0; unsigned long start = start_addr; - spinlock_t *i_mmap_lock = details? details->i_mmap_lock: NULL; + spinlock_t *i_mmap_lock = details ? + (detais->check_mapping ? details->i_mmap_lock: NULL) : NULL; int fullmm = (*tlbp)->fullmm; struct mm_struct *mm = vma->vm_mm;