diff options
author | Hugh Dickins <hughd@google.com> | 2012-12-16 21:56:58 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-16 22:02:38 -0500 |
commit | a4f1de176614f634c367e5994a7bcc428c940df0 (patch) | |
tree | 9193f723c6f61442cf1fbc50e2db48d060f417d6 | |
parent | 2dfea3803dcf70983d14ce1dcbb3e97a7459a28b (diff) |
mm: fix kernel BUG at huge_memory.c:1474!
Andrea's autonuma-benchmark numa01 hits kernel BUG at huge_memory.c:1474!
in change_huge_pmd called from change_protection from change_prot_numa
from task_numa_work.
That BUG, introduced in the huge zero page commit cad7f613c4d0 ("thp:
change_huge_pmd(): make sure we don't try to make a page writable")
was trying to verify that newprot never adds write permission to an
anonymous huge page; but Automatic NUMA Balancing's 4b10e7d562c9 ("mm:
mempolicy: Implement change_prot_numa() in terms of change_protection()")
adds a new prot_numa path into change_huge_pmd(), which makes no use of
the newprot provided, and may retain the write bit in the pmd.
Just move the BUG_ON(pmd_write(entry)) up into the !prot_numa block.
Signed-off-by: Hugh Dickins <hughd@google.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | mm/huge_memory.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index d7ee1691fd21..32754eece63e 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c | |||
@@ -1460,9 +1460,10 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, | |||
1460 | if (__pmd_trans_huge_lock(pmd, vma) == 1) { | 1460 | if (__pmd_trans_huge_lock(pmd, vma) == 1) { |
1461 | pmd_t entry; | 1461 | pmd_t entry; |
1462 | entry = pmdp_get_and_clear(mm, addr, pmd); | 1462 | entry = pmdp_get_and_clear(mm, addr, pmd); |
1463 | if (!prot_numa) | 1463 | if (!prot_numa) { |
1464 | entry = pmd_modify(entry, newprot); | 1464 | entry = pmd_modify(entry, newprot); |
1465 | else { | 1465 | BUG_ON(pmd_write(entry)); |
1466 | } else { | ||
1466 | struct page *page = pmd_page(*pmd); | 1467 | struct page *page = pmd_page(*pmd); |
1467 | 1468 | ||
1468 | /* only check non-shared pages */ | 1469 | /* only check non-shared pages */ |
@@ -1471,7 +1472,6 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, | |||
1471 | entry = pmd_mknuma(entry); | 1472 | entry = pmd_mknuma(entry); |
1472 | } | 1473 | } |
1473 | } | 1474 | } |
1474 | BUG_ON(pmd_write(entry)); | ||
1475 | set_pmd_at(mm, addr, pmd, entry); | 1475 | set_pmd_at(mm, addr, pmd, entry); |
1476 | spin_unlock(&vma->vm_mm->page_table_lock); | 1476 | spin_unlock(&vma->vm_mm->page_table_lock); |
1477 | ret = 1; | 1477 | ret = 1; |