Skip to content

Commit

Permalink
memory-hotplug: move pgdat_resize_lock into sparse_remove_one_section()
Browse files Browse the repository at this point in the history
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:

  ------------[ cut here ]------------
  WARNING: at kernel/smp.c:461 smp_call_function_many+0xbd/0x260()
  Hardware name: PRIMEQUEST 1800E
  ......
  Call Trace:
    smp_call_function_many+0xbd/0x260
    smp_call_function+0x3b/0x50
    on_each_cpu+0x3b/0xc0
    flush_tlb_all+0x1c/0x20
    remove_pagetable+0x14e/0x1d0
    vmemmap_free+0x18/0x20
    sparse_remove_one_section+0xf7/0x100
    __remove_section+0xa2/0xb0
    __remove_pages+0xa0/0xd0
    arch_remove_memory+0x6b/0xc0
    remove_memory+0xb8/0xf0
    acpi_memory_device_remove+0x53/0x96
    acpi_device_remove+0x90/0xb2
    __device_release_driver+0x7c/0xf0
    device_release_driver+0x2f/0x50
    acpi_bus_remove+0x32/0x6d
    acpi_bus_trim+0x91/0x102
    acpi_bus_hot_remove_device+0x88/0x16b
    acpi_os_execute_deferred+0x27/0x34
    process_one_work+0x20e/0x5c0
    worker_thread+0x12e/0x370
    kthread+0xee/0x100
    ret_from_fork+0x7c/0xb0
  ---[ end trace 25e85300f542aa01 ]---

Signed-off-by: Tang Chen <[email protected]>
Signed-off-by: Lai Jiangshan <[email protected]>
Signed-off-by: Wen Congyang <[email protected]>
Acked-by: KAMEZAWA Hiroyuki <[email protected]>
Cc: KOSAKI Motohiro <[email protected]>
Cc: Jiang Liu <[email protected]>
Cc: Jianguo Wu <[email protected]>
Cc: Wu Jianguo <[email protected]>
Cc: Yasuaki Ishimatsu <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
tang-chen authored and torvalds committed Feb 24, 2013
1 parent 46723bf commit cd09968
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 5 deletions.
4 changes: 0 additions & 4 deletions mm/memory_hotplug.c
Original file line number Diff line number Diff line change
Expand Up @@ -444,8 +444,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))
Expand All @@ -455,9 +453,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
Expand Down
5 changes: 4 additions & 1 deletion mm/sparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -796,15 +796,18 @@ 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,
__section_nr(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);
Expand Down

0 comments on commit cd09968

Please sign in to comment.