Single Zone Optimizations V2 V1->V2 Use a config variable setup im mm/KConfig If we only have a single zone then various macros can be optimized. We do not need to protect higher zones, we know that zones are always present, can remove useless data from /proc etc etc. Various code paths become uncessary with a single zone setup. Signed-off-by: Christoph Lameter Index: linux-2.6.19-rc4-mm2/mm/vmstat.c =================================================================== --- linux-2.6.19-rc4-mm2.orig/mm/vmstat.c 2006-11-06 13:50:35.468605875 -0600 +++ linux-2.6.19-rc4-mm2/mm/vmstat.c 2006-11-06 13:51:03.965173269 -0600 @@ -554,15 +554,16 @@ static int zoneinfo_show(struct seq_file for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) seq_printf(m, "\n %-12s %lu", vmstat_text[i], zone_page_state(zone, i)); - - seq_printf(m, - "\n protection: (%lu", - zone->lowmem_reserve[0]); - for (i = 1; i < ARRAY_SIZE(zone->lowmem_reserve); i++) - seq_printf(m, ", %lu", zone->lowmem_reserve[i]); - seq_printf(m, - ")" - "\n pagesets"); + if (CONFIG_MULTI_ZONE) { + seq_printf(m, + "\n protection: (%lu", + zone->lowmem_reserve[0]); + for (i = 1; i < ARRAY_SIZE(zone->lowmem_reserve); i++) + seq_printf(m, ", %lu", zone->lowmem_reserve[i]); + seq_printf(m, + ")" + "\n pagesets"); + } for_each_online_cpu(i) { struct per_cpu_pageset *pageset; int j; Index: linux-2.6.19-rc4-mm2/mm/page_alloc.c =================================================================== --- linux-2.6.19-rc4-mm2.orig/mm/page_alloc.c 2006-11-06 13:51:02.910395944 -0600 +++ linux-2.6.19-rc4-mm2/mm/page_alloc.c 2006-11-06 13:51:03.992519348 -0600 @@ -60,6 +60,7 @@ int percpu_pagelist_fraction; static void __free_pages_ok(struct page *page, unsigned int order); +#if CONFIG_MULTI_ZONE /* * results with 256, 32 in the lowmem_reserve sysctl: * 1G machine -> (16M dma, 800M-16M normal, 1G-800M high) @@ -82,6 +83,7 @@ int sysctl_lowmem_reserve_ratio[MAX_NR_Z 32 #endif }; +#endif EXPORT_SYMBOL(totalram_pages); @@ -925,8 +927,8 @@ int zone_watermark_ok(struct zone *z, in min -= min / 2; if (alloc_flags & ALLOC_HARDER) min -= min / 4; - - if (free_pages <= min + z->lowmem_reserve[classzone_idx]) + if (free_pages <= min + CONFIG_MULTI_ZONE * + z->lowmem_reserve[classzone_idx]) return 0; for (o = 0; o < order; o++) { /* At the next order, this order's pages become unavailable */ @@ -1583,8 +1585,6 @@ void show_free_areas(void) global_page_state(NR_PAGETABLE)); for_each_zone(zone) { - int i; - if (!populated_zone(zone)) continue; @@ -1611,10 +1611,14 @@ void show_free_areas(void) zone->pages_scanned, (zone->all_unreclaimable ? "yes" : "no") ); - printk("lowmem_reserve[]:"); - for (i = 0; i < MAX_NR_ZONES; i++) - printk(" %lu", zone->lowmem_reserve[i]); - printk("\n"); + if (CONFIG_MULTI_ZONE) { + int i; + + printk("lowmem_reserve[]:"); + for (i = 0; i < MAX_NR_ZONES; i++) + printk(" %lu", zone->lowmem_reserve[i]); + printk("\n"); + } } for_each_zone(zone) { @@ -3019,25 +3023,37 @@ void __init page_alloc_init(void) * calculate_totalreserve_pages - called when sysctl_lower_zone_reserve_ratio * or min_free_kbytes changes. */ +static unsigned long calculate_max_lowmem_reserve(struct zone *zone, + enum zone_type start) +{ + unsigned long max; + enum zone_type i; + + if (!CONFIG_MULTI_ZONE) + return 0; + + /* Find valid and maximum lowmem_reserve in the zone */ + for (i = start; i < MAX_NR_ZONES; i++) { + if (zone->lowmem_reserve[i] > max) + max = zone->lowmem_reserve[i]; + } + return max; +} + static void calculate_totalreserve_pages(void) { struct pglist_data *pgdat; unsigned long reserve_pages = 0; - enum zone_type i, j; + enum zone_type i; for_each_online_pgdat(pgdat) { for (i = 0; i < MAX_NR_ZONES; i++) { struct zone *zone = pgdat->node_zones + i; - unsigned long max = 0; - - /* Find valid and maximum lowmem_reserve in the zone */ - for (j = i; j < MAX_NR_ZONES; j++) { - if (zone->lowmem_reserve[j] > max) - max = zone->lowmem_reserve[j]; - } + unsigned long max; /* we treat pages_high as reserved pages. */ - max += zone->pages_high; + max = calculate_max_lowmem_reserve(zone, i) + \ + zone->pages_high; if (max > zone->present_pages) max = zone->present_pages; @@ -3058,6 +3074,9 @@ static void setup_per_zone_lowmem_reserv struct pglist_data *pgdat; enum zone_type j, idx; + if (!CONFIG_MULTI_ZONE) + return 0; + for_each_online_pgdat(pgdat) { for (j = 0; j < MAX_NR_ZONES; j++) { struct zone *zone = pgdat->node_zones + j; @@ -3249,6 +3268,7 @@ int sysctl_min_interleave_ratio_sysctl_h } #endif +#if CONFIG_MULTI_ZONE /* * lowmem_reserve_ratio_sysctl_handler - just a wrapper around * proc_dointvec() so that we can call setup_per_zone_lowmem_reserve() @@ -3265,6 +3285,7 @@ int lowmem_reserve_ratio_sysctl_handler( setup_per_zone_lowmem_reserve(); return 0; } +#endif /* * percpu_pagelist_fraction - changes the pcp->high for each zone on each Index: linux-2.6.19-rc4-mm2/kernel/sysctl.c =================================================================== --- linux-2.6.19-rc4-mm2.orig/kernel/sysctl.c 2006-11-06 13:51:02.871330118 -0600 +++ linux-2.6.19-rc4-mm2/kernel/sysctl.c 2006-11-06 13:51:04.029631883 -0600 @@ -904,6 +904,7 @@ static ctl_table vm_table[] = { .proc_handler = &proc_dointvec, }, #endif +#if CONFIG_MULTI_ZONE { .ctl_name = VM_LOWMEM_RESERVE_RATIO, .procname = "lowmem_reserve_ratio", @@ -913,6 +914,7 @@ static ctl_table vm_table[] = { .proc_handler = &lowmem_reserve_ratio_sysctl_handler, .strategy = &sysctl_intvec, }, +#endif { .ctl_name = VM_DROP_PAGECACHE, .procname = "drop_caches", Index: linux-2.6.19-rc4-mm2/include/linux/mmzone.h =================================================================== --- linux-2.6.19-rc4-mm2.orig/include/linux/mmzone.h 2006-11-06 13:51:02.831287645 -0600 +++ linux-2.6.19-rc4-mm2/include/linux/mmzone.h 2006-11-06 13:51:04.052094734 -0600 @@ -497,11 +497,12 @@ unsigned long __init node_memmap_size_by /* * zone_idx() returns 0 for the ZONE_DMA zone, 1 for the ZONE_NORMAL zone, etc. */ -#define zone_idx(zone) ((zone) - (zone)->zone_pgdat->node_zones) +#define zone_idx(zone) (CONFIG_MULTI_ZONE * \ + ((zone) - (zone)->zone_pgdat->node_zones)) static inline int populated_zone(struct zone *zone) { - return (!!zone->present_pages); + return !CONFIG_MULTI_ZONE || (!!zone->present_pages); } static inline int is_highmem_idx(enum zone_type idx) @@ -515,7 +516,7 @@ static inline int is_highmem_idx(enum zo static inline int is_normal_idx(enum zone_type idx) { - return (idx == ZONE_NORMAL); + return !CONFIG_MULTI_ZONE || (idx == ZONE_NORMAL); } /** @@ -535,7 +536,8 @@ static inline int is_highmem(struct zone static inline int is_normal(struct zone *zone) { - return zone == zone->zone_pgdat->node_zones + ZONE_NORMAL; + return !CONFIG_MULTI_ZONE || + zone == zone->zone_pgdat->node_zones + ZONE_NORMAL; } static inline int is_dma32(struct zone *zone) Index: linux-2.6.19-rc4-mm2/mm/Kconfig =================================================================== --- linux-2.6.19-rc4-mm2.orig/mm/Kconfig 2006-11-06 13:50:35.487162143 -0600 +++ linux-2.6.19-rc4-mm2/mm/Kconfig 2006-11-06 13:51:04.063814482 -0600 @@ -163,6 +163,11 @@ config ZONE_DMA_FLAG default "0" if !ZONE_DMA default "1" +config MULTI_ZONE + int + default "1" + default "0" if !ZONE_DMA && !ZONE_DMA32 && !HIGHMEM + # # Adaptive file readahead #