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

Reply via email to