Updated from Linux LTS 3.10.18 to 3.10.19
This commit is contained in:
@@ -1288,64 +1288,90 @@ out:
|
||||
int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
unsigned long addr, pmd_t pmd, pmd_t *pmdp)
|
||||
{
|
||||
struct anon_vma *anon_vma = NULL;
|
||||
struct page *page;
|
||||
unsigned long haddr = addr & HPAGE_PMD_MASK;
|
||||
int page_nid = -1, this_nid = numa_node_id();
|
||||
int target_nid;
|
||||
int current_nid = -1;
|
||||
bool migrated;
|
||||
bool page_locked;
|
||||
bool migrated = false;
|
||||
|
||||
spin_lock(&mm->page_table_lock);
|
||||
if (unlikely(!pmd_same(pmd, *pmdp)))
|
||||
goto out_unlock;
|
||||
|
||||
page = pmd_page(pmd);
|
||||
get_page(page);
|
||||
current_nid = page_to_nid(page);
|
||||
page_nid = page_to_nid(page);
|
||||
count_vm_numa_event(NUMA_HINT_FAULTS);
|
||||
if (current_nid == numa_node_id())
|
||||
if (page_nid == this_nid)
|
||||
count_vm_numa_event(NUMA_HINT_FAULTS_LOCAL);
|
||||
|
||||
/*
|
||||
* Acquire the page lock to serialise THP migrations but avoid dropping
|
||||
* page_table_lock if at all possible
|
||||
*/
|
||||
page_locked = trylock_page(page);
|
||||
target_nid = mpol_misplaced(page, vma, haddr);
|
||||
if (target_nid == -1) {
|
||||
put_page(page);
|
||||
goto clear_pmdnuma;
|
||||
/* If the page was locked, there are no parallel migrations */
|
||||
if (page_locked)
|
||||
goto clear_pmdnuma;
|
||||
|
||||
/*
|
||||
* Otherwise wait for potential migrations and retry. We do
|
||||
* relock and check_same as the page may no longer be mapped.
|
||||
* As the fault is being retried, do not account for it.
|
||||
*/
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
wait_on_page_locked(page);
|
||||
page_nid = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Acquire the page lock to serialise THP migrations */
|
||||
/* Page is misplaced, serialise migrations and parallel THP splits */
|
||||
get_page(page);
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
lock_page(page);
|
||||
if (!page_locked)
|
||||
lock_page(page);
|
||||
anon_vma = page_lock_anon_vma_read(page);
|
||||
|
||||
/* Confirm the PTE did not while locked */
|
||||
spin_lock(&mm->page_table_lock);
|
||||
if (unlikely(!pmd_same(pmd, *pmdp))) {
|
||||
unlock_page(page);
|
||||
put_page(page);
|
||||
page_nid = -1;
|
||||
goto out_unlock;
|
||||
}
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
|
||||
/* Migrate the THP to the requested node */
|
||||
/*
|
||||
* Migrate the THP to the requested node, returns with page unlocked
|
||||
* and pmd_numa cleared.
|
||||
*/
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
migrated = migrate_misplaced_transhuge_page(mm, vma,
|
||||
pmdp, pmd, addr, page, target_nid);
|
||||
if (!migrated)
|
||||
goto check_same;
|
||||
if (migrated)
|
||||
page_nid = target_nid;
|
||||
|
||||
task_numa_fault(target_nid, HPAGE_PMD_NR, true);
|
||||
return 0;
|
||||
|
||||
check_same:
|
||||
spin_lock(&mm->page_table_lock);
|
||||
if (unlikely(!pmd_same(pmd, *pmdp)))
|
||||
goto out_unlock;
|
||||
goto out;
|
||||
clear_pmdnuma:
|
||||
BUG_ON(!PageLocked(page));
|
||||
pmd = pmd_mknonnuma(pmd);
|
||||
set_pmd_at(mm, haddr, pmdp, pmd);
|
||||
VM_BUG_ON(pmd_numa(*pmdp));
|
||||
update_mmu_cache_pmd(vma, addr, pmdp);
|
||||
unlock_page(page);
|
||||
out_unlock:
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
if (current_nid != -1)
|
||||
task_numa_fault(current_nid, HPAGE_PMD_NR, false);
|
||||
|
||||
out:
|
||||
if (anon_vma)
|
||||
page_unlock_anon_vma_read(anon_vma);
|
||||
|
||||
if (page_nid != -1)
|
||||
task_numa_fault(page_nid, HPAGE_PMD_NR, migrated);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
54
mm/memory.c
54
mm/memory.c
@@ -3484,12 +3484,12 @@ static int do_nonlinear_fault(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
}
|
||||
|
||||
int numa_migrate_prep(struct page *page, struct vm_area_struct *vma,
|
||||
unsigned long addr, int current_nid)
|
||||
unsigned long addr, int page_nid)
|
||||
{
|
||||
get_page(page);
|
||||
|
||||
count_vm_numa_event(NUMA_HINT_FAULTS);
|
||||
if (current_nid == numa_node_id())
|
||||
if (page_nid == numa_node_id())
|
||||
count_vm_numa_event(NUMA_HINT_FAULTS_LOCAL);
|
||||
|
||||
return mpol_misplaced(page, vma, addr);
|
||||
@@ -3500,7 +3500,7 @@ int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
{
|
||||
struct page *page = NULL;
|
||||
spinlock_t *ptl;
|
||||
int current_nid = -1;
|
||||
int page_nid = -1;
|
||||
int target_nid;
|
||||
bool migrated = false;
|
||||
|
||||
@@ -3530,15 +3530,10 @@ int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
return 0;
|
||||
}
|
||||
|
||||
current_nid = page_to_nid(page);
|
||||
target_nid = numa_migrate_prep(page, vma, addr, current_nid);
|
||||
page_nid = page_to_nid(page);
|
||||
target_nid = numa_migrate_prep(page, vma, addr, page_nid);
|
||||
pte_unmap_unlock(ptep, ptl);
|
||||
if (target_nid == -1) {
|
||||
/*
|
||||
* Account for the fault against the current node if it not
|
||||
* being replaced regardless of where the page is located.
|
||||
*/
|
||||
current_nid = numa_node_id();
|
||||
put_page(page);
|
||||
goto out;
|
||||
}
|
||||
@@ -3546,11 +3541,11 @@ int do_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
/* Migrate to the requested node */
|
||||
migrated = migrate_misplaced_page(page, target_nid);
|
||||
if (migrated)
|
||||
current_nid = target_nid;
|
||||
page_nid = target_nid;
|
||||
|
||||
out:
|
||||
if (current_nid != -1)
|
||||
task_numa_fault(current_nid, 1, migrated);
|
||||
if (page_nid != -1)
|
||||
task_numa_fault(page_nid, 1, migrated);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3565,7 +3560,6 @@ static int do_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
unsigned long offset;
|
||||
spinlock_t *ptl;
|
||||
bool numa = false;
|
||||
int local_nid = numa_node_id();
|
||||
|
||||
spin_lock(&mm->page_table_lock);
|
||||
pmd = *pmdp;
|
||||
@@ -3588,9 +3582,10 @@ static int do_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
for (addr = _addr + offset; addr < _addr + PMD_SIZE; pte++, addr += PAGE_SIZE) {
|
||||
pte_t pteval = *pte;
|
||||
struct page *page;
|
||||
int curr_nid = local_nid;
|
||||
int page_nid = -1;
|
||||
int target_nid;
|
||||
bool migrated;
|
||||
bool migrated = false;
|
||||
|
||||
if (!pte_present(pteval))
|
||||
continue;
|
||||
if (!pte_numa(pteval))
|
||||
@@ -3612,25 +3607,19 @@ static int do_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
if (unlikely(page_mapcount(page) != 1))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Note that the NUMA fault is later accounted to either
|
||||
* the node that is currently running or where the page is
|
||||
* migrated to.
|
||||
*/
|
||||
curr_nid = local_nid;
|
||||
target_nid = numa_migrate_prep(page, vma, addr,
|
||||
page_to_nid(page));
|
||||
if (target_nid == -1) {
|
||||
page_nid = page_to_nid(page);
|
||||
target_nid = numa_migrate_prep(page, vma, addr, page_nid);
|
||||
pte_unmap_unlock(pte, ptl);
|
||||
if (target_nid != -1) {
|
||||
migrated = migrate_misplaced_page(page, target_nid);
|
||||
if (migrated)
|
||||
page_nid = target_nid;
|
||||
} else {
|
||||
put_page(page);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Migrate to the requested node */
|
||||
pte_unmap_unlock(pte, ptl);
|
||||
migrated = migrate_misplaced_page(page, target_nid);
|
||||
if (migrated)
|
||||
curr_nid = target_nid;
|
||||
task_numa_fault(curr_nid, 1, migrated);
|
||||
if (page_nid != -1)
|
||||
task_numa_fault(page_nid, 1, migrated);
|
||||
|
||||
pte = pte_offset_map_lock(mm, pmdp, addr, &ptl);
|
||||
}
|
||||
@@ -4032,6 +4021,7 @@ int generic_access_phys(struct vm_area_struct *vma, unsigned long addr,
|
||||
|
||||
return len;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(generic_access_phys);
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
19
mm/migrate.c
19
mm/migrate.c
@@ -1710,12 +1710,12 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
|
||||
unlock_page(new_page);
|
||||
put_page(new_page); /* Free it */
|
||||
|
||||
unlock_page(page);
|
||||
/* Retake the callers reference and putback on LRU */
|
||||
get_page(page);
|
||||
putback_lru_page(page);
|
||||
|
||||
count_vm_events(PGMIGRATE_FAIL, HPAGE_PMD_NR);
|
||||
isolated = 0;
|
||||
goto out;
|
||||
mod_zone_page_state(page_zone(page),
|
||||
NR_ISOLATED_ANON + page_lru, -HPAGE_PMD_NR);
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1732,9 +1732,9 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
|
||||
entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
|
||||
entry = pmd_mkhuge(entry);
|
||||
|
||||
page_add_new_anon_rmap(new_page, vma, haddr);
|
||||
|
||||
pmdp_clear_flush(vma, haddr, pmd);
|
||||
set_pmd_at(mm, haddr, pmd, entry);
|
||||
page_add_new_anon_rmap(new_page, vma, haddr);
|
||||
update_mmu_cache_pmd(vma, address, &entry);
|
||||
page_remove_rmap(page);
|
||||
/*
|
||||
@@ -1753,7 +1753,6 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
|
||||
count_vm_events(PGMIGRATE_SUCCESS, HPAGE_PMD_NR);
|
||||
count_vm_numa_events(NUMA_PAGE_MIGRATE, HPAGE_PMD_NR);
|
||||
|
||||
out:
|
||||
mod_zone_page_state(page_zone(page),
|
||||
NR_ISOLATED_ANON + page_lru,
|
||||
-HPAGE_PMD_NR);
|
||||
@@ -1762,6 +1761,10 @@ out:
|
||||
out_fail:
|
||||
count_vm_events(PGMIGRATE_FAIL, HPAGE_PMD_NR);
|
||||
out_dropref:
|
||||
entry = pmd_mknonnuma(entry);
|
||||
set_pmd_at(mm, haddr, pmd, entry);
|
||||
update_mmu_cache_pmd(vma, address, &entry);
|
||||
|
||||
unlock_page(page);
|
||||
put_page(page);
|
||||
return 0;
|
||||
|
||||
@@ -145,7 +145,7 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
|
||||
split_huge_page_pmd(vma, addr, pmd);
|
||||
else if (change_huge_pmd(vma, pmd, addr, newprot,
|
||||
prot_numa)) {
|
||||
pages += HPAGE_PMD_NR;
|
||||
pages++;
|
||||
continue;
|
||||
}
|
||||
/* fall through */
|
||||
|
||||
@@ -242,7 +242,7 @@ int walk_page_range(unsigned long addr, unsigned long end,
|
||||
if (err)
|
||||
break;
|
||||
pgd++;
|
||||
} while (addr = next, addr != end);
|
||||
} while (addr = next, addr < end);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -388,12 +388,12 @@ nocache:
|
||||
addr = ALIGN(first->va_end, align);
|
||||
if (addr < vstart)
|
||||
goto nocache;
|
||||
if (addr + size - 1 < addr)
|
||||
if (addr + size < addr)
|
||||
goto overflow;
|
||||
|
||||
} else {
|
||||
addr = ALIGN(vstart, align);
|
||||
if (addr + size - 1 < addr)
|
||||
if (addr + size < addr)
|
||||
goto overflow;
|
||||
|
||||
n = vmap_area_root.rb_node;
|
||||
@@ -420,7 +420,7 @@ nocache:
|
||||
if (addr + cached_hole_size < first->va_start)
|
||||
cached_hole_size = first->va_start - addr;
|
||||
addr = ALIGN(first->va_end, align);
|
||||
if (addr + size - 1 < addr)
|
||||
if (addr + size < addr)
|
||||
goto overflow;
|
||||
|
||||
if (list_is_last(&first->list, &vmap_area_list))
|
||||
|
||||
Reference in New Issue
Block a user