Hi, On a 4GB SMP box, configured with HIGHMEM support, making a 670G (obviously using a volume manager) ext2 file system takes 12minutes (over 10minutes of sys time). One problem is buffer allocations do not use HIGHMEM, but the nr_free_buffer_pages() doesn't take this into account causing balance_dirty_state() to return the wrong state. The attached patch fixes the worse part of nr_free_buffer_pages() - with HIGHMEM it now only counts free+inactive pages in the NORMAL and DMA zone. It doesn't fix the inactive_dirty calculation. Also, in buffer.c:flush_dirty_buffers(), it is worthwhile to kick the disk queues if it decides to reschedule. With the patch, that 670G filesystem can be created in 5m36secs (under half the time). Patch is against 2.4.1-ac18. Mark
diff -urN -X dontdiff vanilla-2.4.1-ac18/fs/buffer.c markhe-2.4.1-ac18/fs/buffer.c --- vanilla-2.4.1-ac18/fs/buffer.c Sun Feb 18 15:06:26 2001 +++ markhe-2.4.1-ac18/fs/buffer.c Sun Feb 18 19:03:19 2001 @@ -2638,8 +2638,11 @@ ll_rw_block(WRITE, 1, &bh); atomic_dec(&bh->b_count); - if (current->need_resched) + if (current->need_resched) { + /* kick what we've already pushed down */ + run_task_queue(&tq_disk); schedule(); + } goto restart; } out_unlock: diff -urN -X dontdiff vanilla-2.4.1-ac18/include/linux/swap.h markhe-2.4.1-ac18/include/linux/swap.h --- vanilla-2.4.1-ac18/include/linux/swap.h Sun Feb 18 15:06:29 2001 +++ markhe-2.4.1-ac18/include/linux/swap.h Sun Feb 18 18:11:03 2001 @@ -65,7 +65,9 @@ extern int nr_swap_pages; FASTCALL(unsigned int nr_free_pages(void)); +FASTCALL(unsigned int nr_free_pages_zone(int)); FASTCALL(unsigned int nr_inactive_clean_pages(void)); +FASTCALL(unsigned int nr_inactive_clean_pages_zone(int)); FASTCALL(unsigned int nr_free_buffer_pages(void)); extern int nr_active_pages; extern int nr_inactive_dirty_pages; diff -urN -X dontdiff vanilla-2.4.1-ac18/mm/page_alloc.c markhe-2.4.1-ac18/mm/page_alloc.c --- vanilla-2.4.1-ac18/mm/page_alloc.c Sun Feb 18 15:06:29 2001 +++ markhe-2.4.1-ac18/mm/page_alloc.c Sun Feb 18 19:04:36 2001 @@ -547,6 +547,23 @@ } /* + * Total amount of free (allocatable) RAM in a given zone. + */ +unsigned int nr_free_pages_zone (int zone_type) +{ + pg_data_t *pgdat; + unsigned int sum; + + sum = 0; + pgdat = pgdat_list; + while (pgdat) { + sum += (pgdat->node_zones+zone_type)->free_pages; + pgdat = pgdat->node_next; + } + return sum; +} + +/* * Total amount of inactive_clean (allocatable) RAM: */ unsigned int nr_inactive_clean_pages (void) @@ -565,14 +582,43 @@ } /* + * Total amount of inactive_clean (allocatable) RAM in a given zone. + */ +unsigned int nr_inactive_clean_pages_zone (int zone_type) +{ + pg_data_t *pgdat; + unsigned int sum; + + sum = 0; + pgdat = pgdat_list; + while (pgdat) { + sum += (pgdat->node_zones+zone_type)->inactive_clean_pages; + pgdat = pgdat->node_next; + } + return sum; +} + + +/* * Amount of free RAM allocatable as buffer memory: + * + * For HIGHMEM systems don't count HIGHMEM pages. + * This is function is still far from perfect for HIGHMEM systems, but + * it is close enough for the time being. */ unsigned int nr_free_buffer_pages (void) { unsigned int sum; - sum = nr_free_pages(); - sum += nr_inactive_clean_pages(); +#if CONFIG_HIGHMEM + sum = nr_free_pages_zone(ZONE_NORMAL) + + nr_free_pages_zone(ZONE_DMA) + + nr_inactive_clean_pages_zone(ZONE_NORMAL) + + nr_inactive_clean_pages_zone(ZONE_DMA); +#else + sum = nr_free_pages() + + nr_inactive_clean_pages(); +#endif sum += nr_inactive_dirty_pages; /*