diff options
author | Dimitri Sivanich <sivanich@sgi.com> | 2009-06-23 15:37:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-23 15:50:05 -0400 |
commit | 364df0ebfbbb1330bfc6ca159f4d6020efc15a12 (patch) | |
tree | 80c79bf145d8388ad96a0f7c47a4d25642e403a1 | |
parent | 01ff53f416757da416413bc32229770a8448b6ef (diff) |
mm: fix handling of pagesets for downed cpus
After downing/upping a cpu, an attempt to set
/proc/sys/vm/percpu_pagelist_fraction results in an oops in
percpu_pagelist_fraction_sysctl_handler().
If a processor is downed then we need to set the pageset pointer back to
the boot pageset.
Updates of the high water marks should not access pagesets of unpopulated
zones (those pointer go to the boot pagesets which would be no longer
functional if their size would be increased beyond zero).
Signed-off-by: Dimitri Sivanich <sivanich@sgi.com>
Signed-off-by: Christoph Lameter <cl@linux-foundation.org>
Reviewed-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | mm/page_alloc.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 30d5093a099d..aecc9cdfdfce 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -3026,7 +3026,7 @@ bad: | |||
3026 | if (dzone == zone) | 3026 | if (dzone == zone) |
3027 | break; | 3027 | break; |
3028 | kfree(zone_pcp(dzone, cpu)); | 3028 | kfree(zone_pcp(dzone, cpu)); |
3029 | zone_pcp(dzone, cpu) = NULL; | 3029 | zone_pcp(dzone, cpu) = &boot_pageset[cpu]; |
3030 | } | 3030 | } |
3031 | return -ENOMEM; | 3031 | return -ENOMEM; |
3032 | } | 3032 | } |
@@ -3041,7 +3041,7 @@ static inline void free_zone_pagesets(int cpu) | |||
3041 | /* Free per_cpu_pageset if it is slab allocated */ | 3041 | /* Free per_cpu_pageset if it is slab allocated */ |
3042 | if (pset != &boot_pageset[cpu]) | 3042 | if (pset != &boot_pageset[cpu]) |
3043 | kfree(pset); | 3043 | kfree(pset); |
3044 | zone_pcp(zone, cpu) = NULL; | 3044 | zone_pcp(zone, cpu) = &boot_pageset[cpu]; |
3045 | } | 3045 | } |
3046 | } | 3046 | } |
3047 | 3047 | ||
@@ -4659,7 +4659,7 @@ int percpu_pagelist_fraction_sysctl_handler(ctl_table *table, int write, | |||
4659 | ret = proc_dointvec_minmax(table, write, file, buffer, length, ppos); | 4659 | ret = proc_dointvec_minmax(table, write, file, buffer, length, ppos); |
4660 | if (!write || (ret == -EINVAL)) | 4660 | if (!write || (ret == -EINVAL)) |
4661 | return ret; | 4661 | return ret; |
4662 | for_each_zone(zone) { | 4662 | for_each_populated_zone(zone) { |
4663 | for_each_online_cpu(cpu) { | 4663 | for_each_online_cpu(cpu) { |
4664 | unsigned long high; | 4664 | unsigned long high; |
4665 | high = zone->present_pages / percpu_pagelist_fraction; | 4665 | high = zone->present_pages / percpu_pagelist_fraction; |