diff options
Diffstat (limited to 'mm/memory.c')
-rw-r--r-- | mm/memory.c | 73 |
1 files changed, 35 insertions, 38 deletions
diff --git a/mm/memory.c b/mm/memory.c index ca0003947115..d176154c243f 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -837,6 +837,8 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, | |||
837 | */ | 837 | */ |
838 | make_migration_entry_read(&entry); | 838 | make_migration_entry_read(&entry); |
839 | pte = swp_entry_to_pte(entry); | 839 | pte = swp_entry_to_pte(entry); |
840 | if (pte_swp_soft_dirty(*src_pte)) | ||
841 | pte = pte_swp_mksoft_dirty(pte); | ||
840 | set_pte_at(src_mm, addr, src_pte, pte); | 842 | set_pte_at(src_mm, addr, src_pte, pte); |
841 | } | 843 | } |
842 | } | 844 | } |
@@ -3519,12 +3521,12 @@ static int do_nonlinear_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3519 | } | 3521 | } |
3520 | 3522 | ||
3521 | int numa_migrate_prep(struct page *page, struct vm_area_struct *vma, | 3523 | int numa_migrate_prep(struct page *page, struct vm_area_struct *vma, |
3522 | unsigned long addr, int current_nid) | 3524 | unsigned long addr, int page_nid) |
3523 | { | 3525 | { |
3524 | get_page(page); | 3526 | get_page(page); |
3525 | 3527 | ||
3526 | count_vm_numa_event(NUMA_HINT_FAULTS); | 3528 | count_vm_numa_event(NUMA_HINT_FAULTS); |
3527 | if (current_nid == numa_node_id()) | 3529 | if (page_nid == numa_node_id()) |
3528 | count_vm_numa_event(NUMA_HINT_FAULTS_LOCAL); | 3530 | count_vm_numa_event(NUMA_HINT_FAULTS_LOCAL); |
3529 | 3531 | ||
3530 | return mpol_misplaced(page, vma, addr); | 3532 | return mpol_misplaced(page, vma, addr); |
@@ -3535,7 +3537,7 @@ int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3535 | { | 3537 | { |
3536 | struct page *page = NULL; | 3538 | struct page *page = NULL; |
3537 | spinlock_t *ptl; | 3539 | spinlock_t *ptl; |
3538 | int current_nid = -1; | 3540 | int page_nid = -1; |
3539 | int target_nid; | 3541 | int target_nid; |
3540 | bool migrated = false; | 3542 | bool migrated = false; |
3541 | 3543 | ||
@@ -3565,15 +3567,10 @@ int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3565 | return 0; | 3567 | return 0; |
3566 | } | 3568 | } |
3567 | 3569 | ||
3568 | current_nid = page_to_nid(page); | 3570 | page_nid = page_to_nid(page); |
3569 | target_nid = numa_migrate_prep(page, vma, addr, current_nid); | 3571 | target_nid = numa_migrate_prep(page, vma, addr, page_nid); |
3570 | pte_unmap_unlock(ptep, ptl); | 3572 | pte_unmap_unlock(ptep, ptl); |
3571 | if (target_nid == -1) { | 3573 | if (target_nid == -1) { |
3572 | /* | ||
3573 | * Account for the fault against the current node if it not | ||
3574 | * being replaced regardless of where the page is located. | ||
3575 | */ | ||
3576 | current_nid = numa_node_id(); | ||
3577 | put_page(page); | 3574 | put_page(page); |
3578 | goto out; | 3575 | goto out; |
3579 | } | 3576 | } |
@@ -3581,11 +3578,11 @@ int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3581 | /* Migrate to the requested node */ | 3578 | /* Migrate to the requested node */ |
3582 | migrated = migrate_misplaced_page(page, target_nid); | 3579 | migrated = migrate_misplaced_page(page, target_nid); |
3583 | if (migrated) | 3580 | if (migrated) |
3584 | current_nid = target_nid; | 3581 | page_nid = target_nid; |
3585 | 3582 | ||
3586 | out: | 3583 | out: |
3587 | if (current_nid != -1) | 3584 | if (page_nid != -1) |
3588 | task_numa_fault(current_nid, 1, migrated); | 3585 | task_numa_fault(page_nid, 1, migrated); |
3589 | return 0; | 3586 | return 0; |
3590 | } | 3587 | } |
3591 | 3588 | ||
@@ -3600,7 +3597,6 @@ static int do_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3600 | unsigned long offset; | 3597 | unsigned long offset; |
3601 | spinlock_t *ptl; | 3598 | spinlock_t *ptl; |
3602 | bool numa = false; | 3599 | bool numa = false; |
3603 | int local_nid = numa_node_id(); | ||
3604 | 3600 | ||
3605 | spin_lock(&mm->page_table_lock); | 3601 | spin_lock(&mm->page_table_lock); |
3606 | pmd = *pmdp; | 3602 | pmd = *pmdp; |
@@ -3623,9 +3619,10 @@ static int do_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3623 | for (addr = _addr + offset; addr < _addr + PMD_SIZE; pte++, addr += PAGE_SIZE) { | 3619 | for (addr = _addr + offset; addr < _addr + PMD_SIZE; pte++, addr += PAGE_SIZE) { |
3624 | pte_t pteval = *pte; | 3620 | pte_t pteval = *pte; |
3625 | struct page *page; | 3621 | struct page *page; |
3626 | int curr_nid = local_nid; | 3622 | int page_nid = -1; |
3627 | int target_nid; | 3623 | int target_nid; |
3628 | bool migrated; | 3624 | bool migrated = false; |
3625 | |||
3629 | if (!pte_present(pteval)) | 3626 | if (!pte_present(pteval)) |
3630 | continue; | 3627 | continue; |
3631 | if (!pte_numa(pteval)) | 3628 | if (!pte_numa(pteval)) |
@@ -3647,25 +3644,19 @@ static int do_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3647 | if (unlikely(page_mapcount(page) != 1)) | 3644 | if (unlikely(page_mapcount(page) != 1)) |
3648 | continue; | 3645 | continue; |
3649 | 3646 | ||
3650 | /* | 3647 | page_nid = page_to_nid(page); |
3651 | * Note that the NUMA fault is later accounted to either | 3648 | target_nid = numa_migrate_prep(page, vma, addr, page_nid); |
3652 | * the node that is currently running or where the page is | 3649 | pte_unmap_unlock(pte, ptl); |
3653 | * migrated to. | 3650 | if (target_nid != -1) { |
3654 | */ | 3651 | migrated = migrate_misplaced_page(page, target_nid); |
3655 | curr_nid = local_nid; | 3652 | if (migrated) |
3656 | target_nid = numa_migrate_prep(page, vma, addr, | 3653 | page_nid = target_nid; |
3657 | page_to_nid(page)); | 3654 | } else { |
3658 | if (target_nid == -1) { | ||
3659 | put_page(page); | 3655 | put_page(page); |
3660 | continue; | ||
3661 | } | 3656 | } |
3662 | 3657 | ||
3663 | /* Migrate to the requested node */ | 3658 | if (page_nid != -1) |
3664 | pte_unmap_unlock(pte, ptl); | 3659 | task_numa_fault(page_nid, 1, migrated); |
3665 | migrated = migrate_misplaced_page(page, target_nid); | ||
3666 | if (migrated) | ||
3667 | curr_nid = target_nid; | ||
3668 | task_numa_fault(curr_nid, 1, migrated); | ||
3669 | 3660 | ||
3670 | pte = pte_offset_map_lock(mm, pmdp, addr, &ptl); | 3661 | pte = pte_offset_map_lock(mm, pmdp, addr, &ptl); |
3671 | } | 3662 | } |
@@ -3863,15 +3854,21 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3863 | * space. Kernel faults are handled more gracefully. | 3854 | * space. Kernel faults are handled more gracefully. |
3864 | */ | 3855 | */ |
3865 | if (flags & FAULT_FLAG_USER) | 3856 | if (flags & FAULT_FLAG_USER) |
3866 | mem_cgroup_enable_oom(); | 3857 | mem_cgroup_oom_enable(); |
3867 | 3858 | ||
3868 | ret = __handle_mm_fault(mm, vma, address, flags); | 3859 | ret = __handle_mm_fault(mm, vma, address, flags); |
3869 | 3860 | ||
3870 | if (flags & FAULT_FLAG_USER) | 3861 | if (flags & FAULT_FLAG_USER) { |
3871 | mem_cgroup_disable_oom(); | 3862 | mem_cgroup_oom_disable(); |
3872 | 3863 | /* | |
3873 | if (WARN_ON(task_in_memcg_oom(current) && !(ret & VM_FAULT_OOM))) | 3864 | * The task may have entered a memcg OOM situation but |
3874 | mem_cgroup_oom_synchronize(); | 3865 | * if the allocation error was handled gracefully (no |
3866 | * VM_FAULT_OOM), there is no need to kill anything. | ||
3867 | * Just clean up the OOM state peacefully. | ||
3868 | */ | ||
3869 | if (task_in_memcg_oom(current) && !(ret & VM_FAULT_OOM)) | ||
3870 | mem_cgroup_oom_synchronize(false); | ||
3871 | } | ||
3875 | 3872 | ||
3876 | return ret; | 3873 | return ret; |
3877 | } | 3874 | } |