Commit-ID: b542b8f29ca47d0b4174ae2f13d5567181f59d5e Gitweb: http://git.kernel.org/tip/b542b8f29ca47d0b4174ae2f13d5567181f59d5e Author: Vegard Nossum <vegard.nossum@xxxxxxxxx> AuthorDate: Sat, 28 Feb 2009 08:48:28 +0100 Commit: Vegard Nossum <vegard.nossum@xxxxxxxxx> CommitDate: Sat, 28 Feb 2009 08:48:28 +0100 kmemcheck: fix split_page() of the page allocator I'd overlooked this API detail: a split_page() that turns a single order-n page allocation into n order-1 page allocations. We need a hook for kmemcheck here, because we need to split the shadow pages too. It fixes this oops: kernel BUG at include/linux/mm.h:253! invalid opcode: 0000 [#1] SMP last sysfs file: CPU 0 Pid: 1, comm: swapper Tainted: G W 2.6.29-rc6-00888-g42f6e3e-dirty #340 945P-A RIP: 0010:[<ffffffff802c2201>] [<ffffffff802c2201>] __free_pages+0x31/0x70 RSP: 0018:ffff88003f87fae0 EFLAGS: 00010202 RAX: 0000000000000000 RBX: 0000000000000001 RCX: 0000000000000060 RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffffffff819c8c20 RBP: ffff88003f87fb00 R08: ffff880000000000 R09: 0000000000000000 R10: ffff88003dfff000 R11: 0000000000001000 R12: ffffe2000173d000 R13: 0000000000000000 R14: 0000000000380000 R15: 4000000000000000 FS: 0000000000000000(0000) GS:ffff880002701000(0000) knlGS:0000000000000000 CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b CR2: ffff88003ea66c00 CR3: 0000000000201000 CR4: 00000000000006a0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff4ff0 DR7: 0000000000000400 Process swapper (pid: 1, threadinfo ffff88003f87e000, task ffff88003f880000) Stack: ffff88003f87fb00 ffffe20001755000 0000000000000001 0000000000000000 ffff88003f87fb30 ffffffff802eebb3 ffff88003f880000 0000000000000000 ffffe20001755000 0000000000000000 ffff88003f87fb80 ffffffff802c06dc Call Trace: [<ffffffff802eebb3>] kmemcheck_free_shadow+0xb3/0xc0 [<ffffffff802c06dc>] free_hot_cold_page+0x2c/0x2a0 [<ffffffff802c09bb>] free_hot_page+0xb/0x10 [<ffffffff802c223a>] __free_pages+0x6a/0x70 [<ffffffff802c22b7>] free_pages+0x77/0x80 [<ffffffff81aecadb>] alloc_large_system_hash+0x19b/0x29a [<ffffffff81b21f72>] tcp_init+0x196/0x379 [<ffffffff81b2257d>] inet_init+0x14d/0x287 [<ffffffff81b22430>] ? inet_init+0x0/0x287 [<ffffffff8020904a>] do_one_initcall+0x3a/0x1c0 [<ffffffff80238f76>] ? kmemcheck_show_addr+0xf6/0x100 [<ffffffff80238fba>] ? kmemcheck_show_all+0x3a/0x60 [<ffffffff802391d1>] ? kmemcheck_show+0x71/0xd0 [<ffffffff80239742>] ? kmemcheck_fault+0x72/0x90 [<ffffffff81006231>] ? pc87360_probe+0x7d1/0xe83 [<ffffffff8103930e>] ? trace_hardirqs_off_thunk+0x3a/0x3c [<ffffffff8103a1a0>] ? error_exit+0x30/0xb0 [<ffffffff802a86b3>] ? register_irq_proc+0xd3/0xe0 [<ffffffff80340000>] ? pagemap_pte_range+0xf0/0x250 [<ffffffff81ad074b>] kernel_init+0x158/0x1b0 Signed-off-by: Vegard Nossum <vegard.nossum@xxxxxxxxx> --- mm/page_alloc.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 2fdc4bb..5b0e676 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1058,6 +1058,14 @@ void split_page(struct page *page, unsigned int order) VM_BUG_ON(PageCompound(page)); VM_BUG_ON(!page_count(page)); + + /* + * Split shadow pages too, because free(page[0]) would + * otherwise free the whole shadow. + */ + if (kmemcheck_page_is_tracked(page)) + split_page(virt_to_page(page[0].shadow), order); + for (i = 1; i < (1 << order); i++) set_page_refcounted(page + i); } -- To unsubscribe from this list: send the line "unsubscribe linux-tip-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html