History

mm: merge parameters for change_protection()

change_protection() was used by either the NUMA or mprotect() code, there's one parameter for each of the callers (dirty_accountable and prot_numa). Further, these parameters are passed along the calls: - change_protection_range() - change_p4d_range() - change_pud_range() - change_pmd_range() - ... Now we introduce a flag for change_protect() and all these helpers to replace these parameters. Then we can avoid passing multiple parameters multiple times along the way. More importantly, it'll greatly simplify the work if we want to introduce any new parameters to change_protection(). In the follow up patches, a new parameter for userfaultfd write protection will be introduced. No functional change at all.

Peter Xu committed 6 years ago

Commit 58705441 parent 72981e05 files · +33 −17Browse files

Unified · Split

5 files
  1. include/linux/huge_mm.h +1 −1
  2. include/linux/mm.h +13 −1
  3. mm/huge_memory.c +2 −1
  4. mm/mempolicy.c +1 −1
  5. mm/mprotect.c +16 −13
include/linux/huge_mm.h+1−1
@@ -46,7 +46,7 @@ extern bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr, · 45 unmodified lines
46 pmd_t *old_pmd, pmd_t *new_pmd);46 pmd_t *old_pmd, pmd_t *new_pmd);
47extern int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,47extern int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
48 unsigned long addr, pgprot_t newprot,48 unsigned long addr, pgprot_t newprot,
49 int prot_numa);49 unsigned long cp_flags);
50vm_fault_t vmf_insert_pfn_pmd_prot(struct vm_fault *vmf, pfn_t pfn,50vm_fault_t vmf_insert_pfn_pmd_prot(struct vm_fault *vmf, pfn_t pfn,
51 pgprot_t pgprot, bool write);51 pgprot_t pgprot, bool write);
52 52
include/linux/mm.h+13−1
@@ -1771,9 +1771,21 @@ extern unsigned long move_page_tables(struct vm_area_struct *vma, · 1770 unmodified lines
1771 unsigned long old_addr, struct vm_area_struct *new_vma,1771 unsigned long old_addr, struct vm_area_struct *new_vma,
1772 unsigned long new_addr, unsigned long len,1772 unsigned long new_addr, unsigned long len,
1773 bool need_rmap_locks);1773 bool need_rmap_locks);
1774
1775/*
1776 * Flags used by change_protection(). For now we make it a bitmap so
1777 * that we can pass in multiple flags just like parameters. However
1778 * for now all the callers are only use one of the flags at the same
1779 * time.
1780 */
1781/* Whether we should allow dirty bit accounting */
1782#define MM_CP_DIRTY_ACCT (1UL << 0)
1783/* Whether this protection change is for NUMA hints */
1784#define MM_CP_PROT_NUMA (1UL << 1)
1785
1774extern unsigned long change_protection(struct vm_area_struct *vma, unsigned long start,1786extern unsigned long change_protection(struct vm_area_struct *vma, unsigned long start,
1775 unsigned long end, pgprot_t newprot,1787 unsigned long end, pgprot_t newprot,
1776 int dirty_accountable, int prot_numa);1788 unsigned long cp_flags);
1777extern int mprotect_fixup(struct vm_area_struct *vma,1789extern int mprotect_fixup(struct vm_area_struct *vma,
1778 struct vm_area_struct **pprev, unsigned long start,1790 struct vm_area_struct **pprev, unsigned long start,
1779 unsigned long end, unsigned long newflags);1791 unsigned long end, unsigned long newflags);
mm/huge_memory.c+2−1
@@ -1979,13 +1979,14 @@ bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr, · 1978 unmodified lines
1979 * - HPAGE_PMD_NR is protections changed and TLB flush necessary1979 * - HPAGE_PMD_NR is protections changed and TLB flush necessary
1980 */1980 */
1981int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,1981int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
1982 unsigned long addr, pgprot_t newprot, int prot_numa)1982 unsigned long addr, pgprot_t newprot, unsigned long cp_flags)
1983{1983{
1984 struct mm_struct *mm = vma->vm_mm;1984 struct mm_struct *mm = vma->vm_mm;
1985 spinlock_t *ptl;1985 spinlock_t *ptl;
1986 pmd_t entry;1986 pmd_t entry;
1987 bool preserve_write;1987 bool preserve_write;
1988 int ret;1988 int ret;
1989 bool prot_numa = cp_flags & MM_CP_PROT_NUMA;
1989 1990
1990 ptl = __pmd_trans_huge_lock(pmd, vma);1991 ptl = __pmd_trans_huge_lock(pmd, vma);
1991 if (!ptl)1992 if (!ptl)
mm/mempolicy.c+1−1
@@ -627,7 +627,7 @@ unsigned long change_prot_numa(struct vm_area_struct *vma, · 626 unmodified lines
627{627{
628 int nr_updated;628 int nr_updated;
629 629
630 nr_updated = change_protection(vma, addr, end, PAGE_NONE, 0, 1);630 nr_updated = change_protection(vma, addr, end, PAGE_NONE, MM_CP_PROT_NUMA);
631 if (nr_updated)631 if (nr_updated)
632 count_vm_numa_events(NUMA_PTE_UPDATES, nr_updated);632 count_vm_numa_events(NUMA_PTE_UPDATES, nr_updated);
633 633
mm/mprotect.c+16−13
@@ -37,12 +37,14 @@ · 36 unmodified lines
37 37
38static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,38static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
39 unsigned long addr, unsigned long end, pgprot_t newprot,39 unsigned long addr, unsigned long end, pgprot_t newprot,
40 int dirty_accountable, int prot_numa)40 unsigned long cp_flags)
41{41{
42 pte_t *pte, oldpte;42 pte_t *pte, oldpte;
43 spinlock_t *ptl;43 spinlock_t *ptl;
44 unsigned long pages = 0;44 unsigned long pages = 0;
45 int target_node = NUMA_NO_NODE;45 int target_node = NUMA_NO_NODE;
46 bool dirty_accountable = cp_flags & MM_CP_DIRTY_ACCT;
47 bool prot_numa = cp_flags & MM_CP_PROT_NUMA;
46 48
47 /*49 /*
48 * Can be called with only the mmap_sem for reading by50 * Can be called with only the mmap_sem for reading by
@@ -188,7 +190,7 @@ static inline int pmd_none_or_clear_bad_unless_trans_huge(pmd_t *pmd) · 139 unmodified lines
188 190
189static inline unsigned long change_pmd_range(struct vm_area_struct *vma,191static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
190 pud_t *pud, unsigned long addr, unsigned long end,192 pud_t *pud, unsigned long addr, unsigned long end,
191 pgprot_t newprot, int dirty_accountable, int prot_numa)193 pgprot_t newprot, unsigned long cp_flags)
192{194{
193 pmd_t *pmd;195 pmd_t *pmd;
194 unsigned long next;196 unsigned long next;
@@ -229,7 +231,7 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma, · 34 unmodified lines
229 __split_huge_pmd(vma, pmd, addr, false, NULL);231 __split_huge_pmd(vma, pmd, addr, false, NULL);
230 } else {232 } else {
231 int nr_ptes = change_huge_pmd(vma, pmd, addr,233 int nr_ptes = change_huge_pmd(vma, pmd, addr,
232 newprot, prot_numa);234 newprot, cp_flags);
233 235
234 if (nr_ptes) {236 if (nr_ptes) {
235 if (nr_ptes == HPAGE_PMD_NR) {237 if (nr_ptes == HPAGE_PMD_NR) {
@@ -244,7 +246,7 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma, · 8 unmodified lines
244 /* fall through, the trans huge pmd just split */246 /* fall through, the trans huge pmd just split */
245 }247 }
246 this_pages = change_pte_range(vma, pmd, addr, next, newprot,248 this_pages = change_pte_range(vma, pmd, addr, next, newprot,
247 dirty_accountable, prot_numa);249 cp_flags);
248 pages += this_pages;250 pages += this_pages;
249next:251next:
250 cond_resched();252 cond_resched();
@@ -260,7 +262,7 @@ next: · 9 unmodified lines
260 262
261static inline unsigned long change_pud_range(struct vm_area_struct *vma,263static inline unsigned long change_pud_range(struct vm_area_struct *vma,
262 p4d_t *p4d, unsigned long addr, unsigned long end,264 p4d_t *p4d, unsigned long addr, unsigned long end,
263 pgprot_t newprot, int dirty_accountable, int prot_numa)265 pgprot_t newprot, unsigned long cp_flags)
264{266{
265 pud_t *pud;267 pud_t *pud;
266 unsigned long next;268 unsigned long next;
@@ -272,7 +274,7 @@ static inline unsigned long change_pud_range(struct vm_area_struct *vma, · 5 unmodified lines
272 if (pud_none_or_clear_bad(pud))274 if (pud_none_or_clear_bad(pud))
273 continue;275 continue;
274 pages += change_pmd_range(vma, pud, addr, next, newprot,276 pages += change_pmd_range(vma, pud, addr, next, newprot,
275 dirty_accountable, prot_numa);277 cp_flags);
276 } while (pud++, addr = next, addr != end);278 } while (pud++, addr = next, addr != end);
277 279
278 return pages;280 return pages;
@@ -280,7 +282,7 @@ static inline unsigned long change_pud_range(struct vm_area_struct *vma, · 1 unmodified line
280 282
281static inline unsigned long change_p4d_range(struct vm_area_struct *vma,283static inline unsigned long change_p4d_range(struct vm_area_struct *vma,
282 pgd_t *pgd, unsigned long addr, unsigned long end,284 pgd_t *pgd, unsigned long addr, unsigned long end,
283 pgprot_t newprot, int dirty_accountable, int prot_numa)285 pgprot_t newprot, unsigned long cp_flags)
284{286{
285 p4d_t *p4d;287 p4d_t *p4d;
286 unsigned long next;288 unsigned long next;
@@ -292,7 +294,7 @@ static inline unsigned long change_p4d_range(struct vm_area_struct *vma, · 5 unmodified lines
292 if (p4d_none_or_clear_bad(p4d))294 if (p4d_none_or_clear_bad(p4d))
293 continue;295 continue;
294 pages += change_pud_range(vma, p4d, addr, next, newprot,296 pages += change_pud_range(vma, p4d, addr, next, newprot,
295 dirty_accountable, prot_numa);297 cp_flags);
296 } while (p4d++, addr = next, addr != end);298 } while (p4d++, addr = next, addr != end);
297 299
298 return pages;300 return pages;
@@ -300,7 +302,7 @@ static inline unsigned long change_p4d_range(struct vm_area_struct *vma, · 1 unmodified line
300 302
301static unsigned long change_protection_range(struct vm_area_struct *vma,303static unsigned long change_protection_range(struct vm_area_struct *vma,
302 unsigned long addr, unsigned long end, pgprot_t newprot,304 unsigned long addr, unsigned long end, pgprot_t newprot,
303 int dirty_accountable, int prot_numa)305 unsigned long cp_flags)
304{306{
305 struct mm_struct *mm = vma->vm_mm;307 struct mm_struct *mm = vma->vm_mm;
306 pgd_t *pgd;308 pgd_t *pgd;
@@ -317,7 +319,7 @@ static unsigned long change_protection_range(struct vm_area_struct *vma, · 10 unmodified lines
317 if (pgd_none_or_clear_bad(pgd))319 if (pgd_none_or_clear_bad(pgd))
318 continue;320 continue;
319 pages += change_p4d_range(vma, pgd, addr, next, newprot,321 pages += change_p4d_range(vma, pgd, addr, next, newprot,
320 dirty_accountable, prot_numa);322 cp_flags);
321 } while (pgd++, addr = next, addr != end);323 } while (pgd++, addr = next, addr != end);
322 324
323 /* Only flush the TLB if we actually modified any entries: */325 /* Only flush the TLB if we actually modified any entries: */
@@ -330,14 +332,15 @@ static unsigned long change_protection_range(struct vm_area_struct *vma, · 6 unmodified lines
330 332
331unsigned long change_protection(struct vm_area_struct *vma, unsigned long start,333unsigned long change_protection(struct vm_area_struct *vma, unsigned long start,
332 unsigned long end, pgprot_t newprot,334 unsigned long end, pgprot_t newprot,
333 int dirty_accountable, int prot_numa)335 unsigned long cp_flags)
334{336{
335 unsigned long pages;337 unsigned long pages;
336 338
337 if (is_vm_hugetlb_page(vma))339 if (is_vm_hugetlb_page(vma))
338 pages = hugetlb_change_protection(vma, start, end, newprot);340 pages = hugetlb_change_protection(vma, start, end, newprot);
339 else341 else
340 pages = change_protection_range(vma, start, end, newprot, dirty_accountable, prot_numa);342 pages = change_protection_range(vma, start, end, newprot,
343 cp_flags);
341 344
342 return pages;345 return pages;
343}346}
@@ -459,7 +462,7 @@ success: · 115 unmodified lines
459 vma_set_page_prot(vma);462 vma_set_page_prot(vma);
460 463
461 change_protection(vma, start, end, vma->vm_page_prot,464 change_protection(vma, start, end, vma->vm_page_prot,
462 dirty_accountable, 0);465 dirty_accountable ? MM_CP_DIRTY_ACCT : 0);
463 466
464 /*467 /*
465 * Private VM_LOCKED VMA becoming writable: trigger COW to avoid major468 * Private VM_LOCKED VMA becoming writable: trigger COW to avoid major