lkml.org 
[lkml]   [2012]   [Aug]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[RFC PATCH] mm: introduce N_LRU_MEMORY to distinguish between normal and movable memory
From: Wu Jianguo <wujianguo@huawei.com>

Hi all,
Now, We have node masks for both N_NORMAL_MEMORY and
N_HIGH_MEMORY to distinguish between normal and highmem on platforms such as x86.
But we still don't have such a mechanism to distinguish between "normal" and "movable"
memory.

As suggested by Christoph Lameter in threads
http://marc.info/?l=linux-mm&m=134323057602484&w=2, we introduce N_LRU_MEMORY to
distinguish between "normal" and "movable" memory.

And this patch will fix the bug described as follow:

When handling a memory node with only movable zone, function
early_kmem_cache_node_alloc() will allocate a page from remote node but
still increase object count on local node, which will trigger a BUG_ON()
as below when hot-removing this memory node. Actually there's no need to
create kmem_cache_node for memory node with only movable zone at all.

------------[ cut here ]------------
kernel BUG at mm/slub.c:3590!
invalid opcode: 0000 [#1] SMP
CPU 61
Modules linked in: autofs4 sunrpc cpufreq_ondemand acpi_cpufreq freq_table
mperf ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 ip6table_filter ip6_tables
ipv6 vfat fat dm_mirror dm_region_hash dm_log uinput iTCO_wdt
iTCO_vendor_support coretemp hwmon kvm_intel kvm crc32c_intel
ghash_clmulni_intel serio_raw pcspkr cdc_ether usbnet mii i2c_i801 i2c_core sg
lpc_ich mfd_core shpchp ioatdma i7core_edac edac_core igb dca bnx2 ext4
mbcache jbd2 sr_mod cdrom sd_mod crc_t10dif aesni_intel cryptd aes_x86_64
aes_generic bfa scsi_transport_fc scsi_tgt pata_acpi ata_generic ata_piix
megaraid_sas dm_mod [last unloaded: microcode]
Pid: 46287, comm: sh Not tainted 3.5.0-rc4-pgtable-00215-g35f0828-dirty #85
IBM System x3850 X5 -[7143O3G]-/Node 1, Processor Card
RIP: 0010:[<ffffffff81160b2a>] [<ffffffff81160b2a>]
slab_memory_callback+0x1ba/0x1c0
RSP: 0018:ffff880efdcb7c68 EFLAGS: 00010202
RAX: 0000000000000001 RBX: ffff880f7ec06100 RCX: 0000000100400001
RDX: 0000000100400002 RSI: ffff880f7ec02000 RDI: ffff880f7ec06100
RBP: ffff880efdcb7c78 R08: ffff88107b6fb098 R09: ffffffff81160a00
R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000019
R13: 00000000fffffffb R14: 0000000000000000 R15: ffffffff81abe930
FS: 00007f709f342700(0000) GS:ffff880f7f3a0000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000003b5a874570 CR3: 0000000f0da20000 CR4: 00000000000007e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process sh (pid: 46287, threadinfo ffff880efdcb6000, task ffff880f0fa50000)
Stack:
0000000000000004 ffff880efdcb7da8 ffff880efdcb7cb8 ffffffff81524af5
0000000000000001 ffffffff81a8b620 ffffffff81a8b640 0000000000000004
ffff880efdcb7da8 00000000ffffffff ffff880efdcb7d08 ffffffff8107a89a
Call Trace:
[<ffffffff81524af5>] notifier_call_chain+0x55/0x80
[<ffffffff8107a89a>] __blocking_notifier_call_chain+0x5a/0x80
[<ffffffff8107a8d6>] blocking_notifier_call_chain+0x16/0x20
[<ffffffff81352f0b>] memory_notify+0x1b/0x20
[<ffffffff81507104>] offline_pages+0x624/0x700
[<ffffffff811619de>] remove_memory+0x1e/0x20
[<ffffffff813530cc>] memory_block_change_state+0x13c/0x2e0
[<ffffffff81153e96>] ? alloc_pages_current+0xb6/0x120
[<ffffffff81353332>] store_mem_state+0xc2/0xd0
[<ffffffff8133e190>] dev_attr_store+0x20/0x30
[<ffffffff811e2d4f>] sysfs_write_file+0xef/0x170
[<ffffffff81173e28>] vfs_write+0xc8/0x190
[<ffffffff81173ff1>] sys_write+0x51/0x90
[<ffffffff81528d29>] system_call_fastpath+0x16/0x1b
Code: 8b 3d cb fd c4 00 be d0 00 00 00 e8 71 de ff ff 48 85 c0 75 9c 48 c7 c7
c0 7f a5 81 e8 c0 89 f1 ff b8 0d 80 00 00 e9 69 fe ff ff <0f> 0b eb fe 66 90
55 48 89 e5 41 57 41 56 41 55 41 54 53 48 83
RIP [<ffffffff81160b2a>] slab_memory_callback+0x1ba/0x1c0
RSP <ffff880efdcb7c68>
---[ end trace 749e9e9a67c78c12 ]---
Signed-off-by: Wu Jianguo <wujianguo@huawei.com>
Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
---
arch/alpha/mm/numa.c | 2 +-
arch/m32r/mm/discontig.c | 2 +-
arch/m68k/mm/motorola.c | 2 +-
arch/parisc/mm/init.c | 2 +-
arch/tile/kernel/setup.c | 2 +-
arch/x86/mm/init_64.c | 2 +-
drivers/base/node.c | 4 +++-
include/linux/nodemask.h | 5 +++--
mm/page_alloc.c | 10 ++++++++--
9 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c
index 3973ae3..8402b29 100644
--- a/arch/alpha/mm/numa.c
+++ b/arch/alpha/mm/numa.c
@@ -313,7 +313,7 @@ void __init paging_init(void)
zones_size[ZONE_DMA] = dma_local_pfn;
zones_size[ZONE_NORMAL] = (end_pfn - start_pfn) - dma_local_pfn;
}
- node_set_state(nid, N_NORMAL_MEMORY);
+ node_set_state(nid, N_LRU_MEMORY);
free_area_init_node(nid, zones_size, start_pfn, NULL);
}

diff --git a/arch/m32r/mm/discontig.c b/arch/m32r/mm/discontig.c
index 2c468e8..4d76e19 100644
--- a/arch/m32r/mm/discontig.c
+++ b/arch/m32r/mm/discontig.c
@@ -149,7 +149,7 @@ unsigned long __init zone_sizes_init(void)
zholes_size[ZONE_DMA] = mp->holes;
holes += zholes_size[ZONE_DMA];

- node_set_state(nid, N_NORMAL_MEMORY);
+ node_set_state(nid, N_LRU_MEMORY);
free_area_init_node(nid, zones_size, start_pfn, zholes_size);
}

diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c
index 0dafa69..31a0b00 100644
--- a/arch/m68k/mm/motorola.c
+++ b/arch/m68k/mm/motorola.c
@@ -300,7 +300,7 @@ void __init paging_init(void)
free_area_init_node(i, zones_size,
m68k_memory[i].addr >> PAGE_SHIFT, NULL);
if (node_present_pages(i))
- node_set_state(i, N_NORMAL_MEMORY);
+ node_set_state(i, N_LRU_MEMORY);
}
}

diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 3ac462d..ad286fd 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -277,7 +277,7 @@ static void __init setup_bootmem(void)
memset(pfnnid_map, 0xff, sizeof(pfnnid_map));

for (i = 0; i < npmem_ranges; i++) {
- node_set_state(i, N_NORMAL_MEMORY);
+ node_set_state(i, N_LRU_MEMORY);
node_set_online(i);
}
#endif
diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c
index 6a649a4..464672d 100644
--- a/arch/tile/kernel/setup.c
+++ b/arch/tile/kernel/setup.c
@@ -748,7 +748,7 @@ static void __init zone_sizes_init(void)

/* Track the type of memory on each node */
if (zones_size[ZONE_NORMAL] || zones_size[ZONE_DMA])
- node_set_state(i, N_NORMAL_MEMORY);
+ node_set_state(i, N_LRU_MEMORY);
#ifdef CONFIG_HIGHMEM
if (end != start)
node_set_state(i, N_HIGH_MEMORY);
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 2b6b4a3..43bf392 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -625,7 +625,7 @@ void __init paging_init(void)
* numa support is not compiled in, and later node_set_state
* will not set it back.
*/
- node_clear_state(0, N_NORMAL_MEMORY);
+ node_clear_state(0, N_LRU_MEMORY);

zone_sizes_init();
}
diff --git a/drivers/base/node.c b/drivers/base/node.c
index af1a177..4a631f9 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -617,6 +617,7 @@ static struct node_attr node_state_attr[] = {
_NODE_ATTR(possible, N_POSSIBLE),
_NODE_ATTR(online, N_ONLINE),
_NODE_ATTR(has_normal_memory, N_NORMAL_MEMORY),
+ _NODE_ATTR(has_lru_memory, N_LRU_MEMORY),
_NODE_ATTR(has_cpu, N_CPU),
#ifdef CONFIG_HIGHMEM
_NODE_ATTR(has_high_memory, N_HIGH_MEMORY),
@@ -628,8 +629,9 @@ static struct attribute *node_state_attrs[] = {
&node_state_attr[1].attr.attr,
&node_state_attr[2].attr.attr,
&node_state_attr[3].attr.attr,
-#ifdef CONFIG_HIGHMEM
&node_state_attr[4].attr.attr,
+#ifdef CONFIG_HIGHMEM
+ &node_state_attr[5].attr.attr,
#endif
NULL
};
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
index 7afc363..550f9a1 100644
--- a/include/linux/nodemask.h
+++ b/include/linux/nodemask.h
@@ -374,11 +374,12 @@ static inline void __nodes_fold(nodemask_t *dstp, const nodemask_t *origp,
enum node_states {
N_POSSIBLE, /* The node could become online at some point */
N_ONLINE, /* The node is online */
- N_NORMAL_MEMORY, /* The node has regular memory */
+ N_NORMAL_MEMORY, /* The node has normal memory */
+ N_LRU_MEMORY, /* The node has regular memory */
#ifdef CONFIG_HIGHMEM
N_HIGH_MEMORY, /* The node has regular or high memory */
#else
- N_HIGH_MEMORY = N_NORMAL_MEMORY,
+ N_HIGH_MEMORY = N_LRU_MEMORY,
#endif
N_CPU, /* The node has one or more cpus */
NR_NODE_STATES
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 009ac28..5a7eacb 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -87,6 +87,7 @@ nodemask_t node_states[NR_NODE_STATES] __read_mostly = {
[N_ONLINE] = { { [0] = 1UL } },
#ifndef CONFIG_NUMA
[N_NORMAL_MEMORY] = { { [0] = 1UL } },
+ [N_LRU_MEMORY] = { { [0] = 1UL } },
#ifdef CONFIG_HIGHMEM
[N_HIGH_MEMORY] = { { [0] = 1UL } },
#endif
@@ -4796,16 +4797,21 @@ out:
/* Any regular memory on that node ? */
static void __init check_for_regular_memory(pg_data_t *pgdat)
{
-#ifdef CONFIG_HIGHMEM
+ struct zone *zone;
enum zone_type zone_type;

for (zone_type = 0; zone_type <= ZONE_NORMAL; zone_type++) {
- struct zone *zone = &pgdat->node_zones[zone_type];
+ zone = &pgdat->node_zones[zone_type];
if (zone->present_pages) {
node_set_state(zone_to_nid(zone), N_NORMAL_MEMORY);
break;
}
}
+
+#ifdef CONFIG_HIGHMEM
+ zone = &pgdat->node_zones[ZONE_MOVABLE];
+ if (zone->present_pages)
+ node_set_state(zone_to_nid(zone), N_LRU_MEMORY);
#endif
}

--
1.7.1


.






\
 
 \ /
  Last update: 2012-08-09 07:24    [from the cache]
©2003-2011 Jasper Spaans