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;
/*