mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-04 04:06:26 +00:00
mm: fix bad rss-counter if remap_file_pages raced migration
Fix some "Bad rss-counter state" reports on exit, arising from the interaction between page migration and remap_file_pages(): zap_pte() must count a migration entry when zapping it. And yes, it is possible (though very unusual) to find an anon page or swap entry in a VM_SHARED nonlinear mapping: coming from that horrid get_user_pages(write, force) case which COWs even in a shared mapping. Signed-off-by: Hugh Dickins <hughd@google.com> Tested-by: Sasha Levin sasha.levin@oracle.com> Tested-by: Dave Jones davej@redhat.com> Cc: Cyrill Gorcunov <gorcunov@gmail.com> Cc: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
7c1cfacca2
commit
887843961c
30
mm/fremap.c
30
mm/fremap.c
@ -23,28 +23,44 @@
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
static int mm_counter(struct page *page)
|
||||
{
|
||||
return PageAnon(page) ? MM_ANONPAGES : MM_FILEPAGES;
|
||||
}
|
||||
|
||||
static void zap_pte(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
unsigned long addr, pte_t *ptep)
|
||||
{
|
||||
pte_t pte = *ptep;
|
||||
struct page *page;
|
||||
swp_entry_t entry;
|
||||
|
||||
if (pte_present(pte)) {
|
||||
struct page *page;
|
||||
|
||||
flush_cache_page(vma, addr, pte_pfn(pte));
|
||||
pte = ptep_clear_flush(vma, addr, ptep);
|
||||
page = vm_normal_page(vma, addr, pte);
|
||||
if (page) {
|
||||
if (pte_dirty(pte))
|
||||
set_page_dirty(page);
|
||||
update_hiwater_rss(mm);
|
||||
dec_mm_counter(mm, mm_counter(page));
|
||||
page_remove_rmap(page);
|
||||
page_cache_release(page);
|
||||
update_hiwater_rss(mm);
|
||||
dec_mm_counter(mm, MM_FILEPAGES);
|
||||
}
|
||||
} else {
|
||||
if (!pte_file(pte))
|
||||
free_swap_and_cache(pte_to_swp_entry(pte));
|
||||
} else { /* zap_pte() is not called when pte_none() */
|
||||
if (!pte_file(pte)) {
|
||||
update_hiwater_rss(mm);
|
||||
entry = pte_to_swp_entry(pte);
|
||||
if (non_swap_entry(entry)) {
|
||||
if (is_migration_entry(entry)) {
|
||||
page = migration_entry_to_page(entry);
|
||||
dec_mm_counter(mm, mm_counter(page));
|
||||
}
|
||||
} else {
|
||||
free_swap_and_cache(entry);
|
||||
dec_mm_counter(mm, MM_SWAPENTS);
|
||||
}
|
||||
}
|
||||
pte_clear_not_present_full(mm, addr, ptep, 0);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user