diff -urN linux-2.4.20/arch/i386/mm/init.c linux/arch/i386/mm/init.c --- linux-2.4.20/arch/i386/mm/init.c 2003-02-20 16:12:34.000000000 +0100 +++ linux/arch/i386/mm/init.c 2003-02-20 16:20:20.000000000 +0100 @@ -282,14 +282,35 @@ flush_tlb_all(); } +#if CONFIG_HIGHMEM64G +#define MIN_ZONE_DMA_PAGES 1024 +#else +#define MIN_ZONE_DMA_PAGES 4096 +#endif + static void __init zone_sizes_init(void) { unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; - unsigned int max_dma, high, low; + unsigned int max_dma, ratio_maxdma, high, low; max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; low = max_low_pfn; high = highend_pfn; + + /* + * Make the DMA zone 5% of memory, with a minimum of 4Mb + * and a maximum of 16Mb. + */ + #if MAX_ORDER != 10 + #error fix this + #endif + ratio_maxdma = (highend_pfn / 20) & ~((1 << MAX_ORDER)-1); + if (ratio_maxdma > max_dma) + ratio_maxdma = max_dma; + if (ratio_maxdma < MIN_ZONE_DMA_PAGES) + ratio_maxdma = MIN_ZONE_DMA_PAGES; + + max_dma = ratio_maxdma; if (low < max_dma) zones_size[ZONE_DMA] = low; diff -urN linux-2.4.20/mm/page_alloc.c linux/mm/page_alloc.c --- linux-2.4.20/mm/page_alloc.c 2003-02-20 16:12:29.000000000 +0100 +++ linux/mm/page_alloc.c 2003-02-20 16:22:54.000000000 +0100 @@ -38,11 +38,19 @@ EXPORT_SYMBOL(zone_table); static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" }; +#ifdef CONFIG_HIGHMEM64G +static int zone_balance_ratio[MAX_NR_ZONES] __initdata = { 4097, 128, 128, }; +static int zone_balance_min[MAX_NR_ZONES] __initdata = { 0 , 20, 20, }; +static int zone_balance_max[MAX_NR_ZONES] __initdata = { 0 , 255, 255, }; +static int zone_extrafree_ratio[MAX_NR_ZONES] __initdata = { 4097, 512, 0, }; +static int zone_extrafree_max[MAX_NR_ZONES] __initdata = { 0 , 1024, 0, }; +#else static int zone_balance_ratio[MAX_NR_ZONES] __initdata = { 128, 128, 128, }; static int zone_balance_min[MAX_NR_ZONES] __initdata = { 20 , 20, 20, }; static int zone_balance_max[MAX_NR_ZONES] __initdata = { 255 , 255, 255, }; static int zone_extrafree_ratio[MAX_NR_ZONES] __initdata = { 128, 512, 0, }; static int zone_extrafree_max[MAX_NR_ZONES] __initdata = { 1024 , 1024, 0, }; +#endif /* * Temporary debugging check. @@ -843,6 +851,9 @@ zone = pgdat->node_zones + ZONE_NORMAL; if (zone->size) zonelist->zones[j++] = zone; +#ifdef CONFIG_HIGHMEM64G + break; +#endif case ZONE_DMA: zone = pgdat->node_zones + ZONE_DMA; if (zone->size) diff -urN linux-2.4.20/mm/vmscan.c linux/mm/vmscan.c --- linux-2.4.20/mm/vmscan.c 2003-02-20 16:12:33.000000000 +0100 +++ linux/mm/vmscan.c 2003-02-20 16:16:12.000000000 +0100 @@ -945,9 +945,16 @@ */ rebalance_inactive(gfp_mask, 5); - for_each_zone(zone) - while (need_rebalance_dirty(zone)) + for_each_zone(zone) { + int maxloops; + + maxloops = zone->active_anon_pages + + zone->active_cache_pages + + zone->inactive_dirty_pages; + maxloops = maxloops / (16 * BATCH_WORK_AMOUNT) + 1; + while (need_rebalance_dirty(zone) && maxloops--) rebalance_dirty_zone(zone, 16 * BATCH_WORK_AMOUNT, gfp_mask); + } for_each_zone(zone) if (free_high(zone)>0) @@ -1201,12 +1208,12 @@ * no VM pressure at all it shouldn't age stuff either otherwise everything * ends up at the maximum age. */ -#define MAX_AGING_INTERVAL ((unsigned long)5*HZ) -#define MIN_AGING_INTERVAL ((unsigned long)HZ/2) -int kscand(void *unused) +#define MAX_AGING_INTERVAL ((unsigned long)25*HZ) +#define MIN_AGING_INTERVAL ((unsigned long)HZ+1) +int kscand(void *param_zone) { struct task_struct *tsk = current; - struct zone_struct * zone; + struct zone_struct * zone = (struct zone_struct*)param_zone; unsigned long pause = MAX_AGING_INTERVAL; int total_needscan = 0; int age_faster = 0; @@ -1214,59 +1221,56 @@ int age; daemonize(); - strcpy(tsk->comm, "kscand"); + snprintf(tsk->comm, 20, "kscand/%s",zone->name); sigfillset(&tsk->blocked); for (;;) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(pause); - + if (signal_pending(current)) { flush_signals(current); printk(KERN_CRIT "kscand received a signal and is confused\n"); } - for_each_zone(zone) { - if (need_active_anon_scan(zone)) { - for (age = 0; age < MAX_AGE; age++) { - scan_active_list(zone, age, 1); - if (current->need_resched) - schedule(); - } + + if (need_active_anon_scan(zone)) { + for (age = 0; age < MAX_AGE; age++) { + scan_active_list(zone, age, 1); + if (current->need_resched) + schedule(); } + } - if (need_active_cache_scan(zone)) { - for (age = 0; age < MAX_AGE; age++) { - scan_active_list(zone, age, 0); - if (current->need_resched) - schedule(); - } + if (need_active_cache_scan(zone)) { + for (age = 0; age < MAX_AGE; age++) { + scan_active_list(zone, age, 0); + if (current->need_resched) + schedule(); } - - /* Check if we've been aging quickly enough */ - if (zone->need_scan >= 2) - age_faster++; - total_needscan += zone->need_scan; - zone->need_scan = 0; - num_zones++; } - if (age_faster) + + /* Check if we've been scanning quickly enough + * If we had two or more age events, we need to scan faster, + * but if there were none, we can try to go to a lower frequency again + */ + if (zone->need_scan >= 2) pause = max(pause / 2, MIN_AGING_INTERVAL); - else if (total_needscan < num_zones) + else if (zone->need_scan == 0) pause = min(pause + pause / 2, MAX_AGING_INTERVAL); - total_needscan = 0; - age_faster = 0; - num_zones = 0; + zone->need_scan = 0; } } static int __init kswapd_init(void) { + struct zone_struct * zone; printk("Starting kswapd\n"); swap_setup(); kernel_thread(kswapd, NULL, CLONE_KERNEL); - kernel_thread(kscand, NULL, CLONE_KERNEL); + for_each_zone(zone) + kernel_thread(kscand, zone, CLONE_KERNEL); return 0; }