Skip to content

Commit

Permalink
mm: fix bad rss-counter if remap_file_pages raced migration
Browse files Browse the repository at this point in the history
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 <[email protected]>
Tested-by: Sasha Levin [email protected]>
Tested-by: Dave Jones [email protected]>
Cc: Cyrill Gorcunov <[email protected]>
Cc: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Hugh Dickins authored and torvalds committed Mar 19, 2014
1 parent 7c1cfac commit 8878439
Showing 1 changed file with 22 additions and 6 deletions.
28 changes: 22 additions & 6 deletions mm/fremap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
} else { /* zap_pte() is not called when pte_none() */
if (!pte_file(pte)) {
update_hiwater_rss(mm);
dec_mm_counter(mm, MM_FILEPAGES);
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);
}
}
} else {
if (!pte_file(pte))
free_swap_and_cache(pte_to_swp_entry(pte));
pte_clear_not_present_full(mm, addr, ptep, 0);
}
}
Expand Down

0 comments on commit 8878439

Please sign in to comment.