From patchwork Wed Jan 9 09:32:31 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tang Chen X-Patchwork-Id: 210644 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from ozlabs.org (localhost [IPv6:::1]) by ozlabs.org (Postfix) with ESMTP id 620582C03F9 for ; Wed, 9 Jan 2013 20:34:10 +1100 (EST) Received: from song.cn.fujitsu.com (unknown [222.73.24.84]) by ozlabs.org (Postfix) with ESMTP id 753D02C00D2 for ; Wed, 9 Jan 2013 20:33:33 +1100 (EST) X-IronPort-AV: E=Sophos;i="4.84,437,1355068800"; d="scan'208";a="6551286" Received: from unknown (HELO tang.cn.fujitsu.com) ([10.167.250.3]) by song.cn.fujitsu.com with ESMTP; 09 Jan 2013 17:31:29 +0800 Received: from fnstmail02.fnst.cn.fujitsu.com (tang.cn.fujitsu.com [127.0.0.1]) by tang.cn.fujitsu.com (8.14.3/8.13.1) with ESMTP id r099XQhY028273; Wed, 9 Jan 2013 17:33:27 +0800 Received: from tangchen.fnst.cn.fujitsu.com ([10.167.225.117]) by fnstmail02.fnst.cn.fujitsu.com (Lotus Domino Release 8.5.3) with ESMTP id 2013010917325315-803903 ; Wed, 9 Jan 2013 17:32:53 +0800 From: Tang Chen To: akpm@linux-foundation.org, rientjes@google.com, len.brown@intel.com, benh@kernel.crashing.org, paulus@samba.org, cl@linux.com, minchan.kim@gmail.com, kosaki.motohiro@jp.fujitsu.com, isimatu.yasuaki@jp.fujitsu.com, wujianguo@huawei.com, wency@cn.fujitsu.com, tangchen@cn.fujitsu.com, hpa@zytor.com, linfeng@cn.fujitsu.com, laijs@cn.fujitsu.com, mgorman@suse.de, yinghai@kernel.org, glommer@parallels.com Subject: [PATCH v6 07/15] memory-hotplug: move pgdat_resize_lock into sparse_remove_one_section() Date: Wed, 9 Jan 2013 17:32:31 +0800 Message-Id: <1357723959-5416-8-git-send-email-tangchen@cn.fujitsu.com> X-Mailer: git-send-email 1.7.10.1 In-Reply-To: <1357723959-5416-1-git-send-email-tangchen@cn.fujitsu.com> References: <1357723959-5416-1-git-send-email-tangchen@cn.fujitsu.com> X-MIMETrack: Itemize by SMTP Server on mailserver/fnst(Release 8.5.3|September 15, 2011) at 2013/01/09 17:32:53, Serialize by Router on mailserver/fnst(Release 8.5.3|September 15, 2011) at 2013/01/09 17:32:58, Serialize complete at 2013/01/09 17:32:58 Cc: linux-s390@vger.kernel.org, linux-ia64@vger.kernel.org, linux-acpi@vger.kernel.org, linux-sh@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, cmetcalf@tilera.com, linux-mm@kvack.org, sparclinux@vger.kernel.org, linuxppc-dev@lists.ozlabs.org X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" In __remove_section(), we locked pgdat_resize_lock when calling sparse_remove_one_section(). This lock will disable irq. But we don't need to lock the whole function. If we do some work to free pagetables in free_section_usemap(), we need to call flush_tlb_all(), which need irq enabled. Otherwise the WARN_ON_ONCE() in smp_call_function_many() will be triggered. If we lock the whole sparse_remove_one_section(), then we come to this call trace: [ 454.796248] ------------[ cut here ]------------ [ 454.851408] WARNING: at kernel/smp.c:461 smp_call_function_many+0xbd/0x260() [ 454.935620] Hardware name: PRIMEQUEST 1800E ...... [ 455.652201] Call Trace: [ 455.681391] [] warn_slowpath_common+0x7f/0xc0 [ 455.753151] [] ? leave_mm+0x50/0x50 [ 455.814527] [] warn_slowpath_null+0x1a/0x20 [ 455.884208] [] smp_call_function_many+0xbd/0x260 [ 455.959082] [] smp_call_function+0x3b/0x50 [ 456.027722] [] ? leave_mm+0x50/0x50 [ 456.089098] [] on_each_cpu+0x3b/0xc0 [ 456.151512] [] flush_tlb_all+0x1c/0x20 [ 456.216004] [] remove_pagetable+0x14e/0x1d0 [ 456.285683] [] vmemmap_free+0x18/0x20 [ 456.349139] [] sparse_remove_one_section+0xf7/0x100 [ 456.427126] [] __remove_section+0xa2/0xb0 [ 456.494726] [] __remove_pages+0xa0/0xd0 [ 456.560258] [] arch_remove_memory+0x6b/0xc0 [ 456.629937] [] remove_memory+0xb8/0xf0 [ 456.694431] [] acpi_memory_device_remove+0x53/0x96 [ 456.771379] [] acpi_device_remove+0x90/0xb2 [ 456.841059] [] __device_release_driver+0x7c/0xf0 [ 456.915928] [] device_release_driver+0x2f/0x50 [ 456.988719] [] acpi_bus_remove+0x32/0x6d [ 457.055285] [] acpi_bus_trim+0x91/0x102 [ 457.120814] [] acpi_bus_hot_remove_device+0x88/0x16b [ 457.199840] [] acpi_os_execute_deferred+0x27/0x34 [ 457.275756] [] process_one_work+0x20e/0x5c0 [ 457.345434] [] ? process_one_work+0x19f/0x5c0 [ 457.417190] [] ? acpi_os_wait_events_complete+0x23/0x23 [ 457.499332] [] worker_thread+0x12e/0x370 [ 457.565896] [] ? manage_workers+0x180/0x180 [ 457.635574] [] kthread+0xee/0x100 [ 457.694871] [] ? __lock_release+0x129/0x190 [ 457.764552] [] ? __init_kthread_worker+0x70/0x70 [ 457.839427] [] ret_from_fork+0x7c/0xb0 [ 457.903914] [] ? __init_kthread_worker+0x70/0x70 [ 457.978784] ---[ end trace 25e85300f542aa01 ]--- Signed-off-by: Tang Chen Signed-off-by: Lai Jiangshan Signed-off-by: Wen Congyang Acked-by: KAMEZAWA Hiroyuki --- mm/memory_hotplug.c | 4 ---- mm/sparse.c | 5 ++++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 0682d2a..674e791 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -442,8 +442,6 @@ static int __remove_section(struct zone *zone, struct mem_section *ms) #else static int __remove_section(struct zone *zone, struct mem_section *ms) { - unsigned long flags; - struct pglist_data *pgdat = zone->zone_pgdat; int ret = -EINVAL; if (!valid_section(ms)) @@ -453,9 +451,7 @@ static int __remove_section(struct zone *zone, struct mem_section *ms) if (ret) return ret; - pgdat_resize_lock(pgdat, &flags); sparse_remove_one_section(zone, ms); - pgdat_resize_unlock(pgdat, &flags); return 0; } #endif diff --git a/mm/sparse.c b/mm/sparse.c index aadbb2a..05ca73a 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -796,8 +796,10 @@ static inline void clear_hwpoisoned_pages(struct page *memmap, int nr_pages) void sparse_remove_one_section(struct zone *zone, struct mem_section *ms) { struct page *memmap = NULL; - unsigned long *usemap = NULL; + unsigned long *usemap = NULL, flags; + struct pglist_data *pgdat = zone->zone_pgdat; + pgdat_resize_lock(pgdat, &flags); if (ms->section_mem_map) { usemap = ms->pageblock_flags; memmap = sparse_decode_mem_map(ms->section_mem_map, @@ -805,6 +807,7 @@ void sparse_remove_one_section(struct zone *zone, struct mem_section *ms) ms->section_mem_map = 0; ms->pageblock_flags = NULL; } + pgdat_resize_unlock(pgdat, &flags); clear_hwpoisoned_pages(memmap, PAGES_PER_SECTION); free_section_usemap(memmap, usemap);