buffer wake-up patch for 2.1.56

Bill Hawes (whawes@star.net)
Sat, 20 Sep 1997 14:53:21 -0400


This is a multi-part message in MIME format.
--------------810B48290A08742794EFAF50
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

The attached patch changes the dirty buffer wake-up threshold to include
both a proportional (fraction of buffers dirty) and a fixed limit. The
intent is to eliminate the flood of dirty buffers at sync intervals that
can happen when the system has a large number of buffers.

The patch sets the nr_buffers_to_wake variable whenever a dependent
quantity changes (number of buffers or the bdflush parameters.) This
value is then used in refile_buffer and bdflush. (And refile_buffer
doesn't have to recalculate the wake-up limit each time.)

The wake-up threshold is taken as the smaller of the dirty fraction and
twice the number of buffers to write on each pass; this seems to work
well.

Regards,
Bill
--------------810B48290A08742794EFAF50
Content-Type: text/plain; charset=us-ascii; name="buffer_wake56-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="buffer_wake56-patch"

--- fs/buffer.c.old Sat Sep 20 08:16:13 1997
+++ fs/buffer.c Sat Sep 20 13:03:27 1997
@@ -73,6 +78,7 @@
static int nr_buffers_type[NR_LIST] = {0,};
static int nr_buffer_heads = 0;
static int nr_unused_buffer_heads = 0;
+static int nr_buffers_to_wake = 0;
static int refilled = 0; /* Set NZ when a buffer freelist is refilled
this is used by the loop device */

@@ -922,12 +969,10 @@
if(dispose != buf->b_list) {
file_buffer(buf, dispose);
if(dispose == BUF_DIRTY) {
- int too_many = (nr_buffers * bdf_prm.b_un.nfract/100);
-
- /* This buffer is dirty, maybe we need to start flushing.
- * If too high a percentage of the buffers are dirty...
+ /*
+ * Check whether to start flushing
*/
- if (nr_buffers_type[BUF_DIRTY] > too_many)
+ if (nr_buffers_type[BUF_DIRTY] > nr_buffers_to_wake)
wakeup_bdflush(0);

/* If this is a loop device, and
@@ -1483,6 +1576,21 @@
}

/*
+ * Sets the dirty buffer wake up threshold for bdflush. This limit is
+ * kept in sync with the number of buffers and bdflush parameters.
+ */
+static void set_buffers_to_wake(void)
+{
+ /*
+ * In order to avoid writing massive numbers of buffers at once,
+ * we use the smaller of the percentage and absolute counts.
+ */
+ nr_buffers_to_wake = nr_buffers * bdf_prm.b_un.nfract / 100;
+ if (nr_buffers_to_wake > bdf_prm.b_un.ndirty * 2)
+ nr_buffers_to_wake = bdf_prm.b_un.ndirty * 2;
+}
+
+/*
* Try to increase the number of buffers available: the size argument
* is used to determine what kind of buffers we want.
*/
@@ -1531,6 +1639,7 @@
free_list[isize] = bh;
mem_map[MAP_NR(page)].buffers = bh;
buffermem += PAGE_SIZE;
+ set_buffers_to_wake();
return 1;
}

@@ -1583,6 +1692,7 @@
buffermem -= PAGE_SIZE;
mem_map[MAP_NR(page)].buffers = NULL;
free_page(page);
+ set_buffers_to_wake();
return 1;
}

@@ -1791,6 +1943,7 @@
if (data < bdflush_min[i] || data > bdflush_max[i])
goto out;
bdf_prm.data[i] = data;
+ set_buffers_to_wake();
error = 0;
goto out;
};
@@ -1921,11 +2081,12 @@
continue;
}
run_task_queue(&tq_disk);
wake_up(&bdflush_done);

- /* If there are still a lot of dirty buffers around, skip the sleep
- and flush some more */
- if(nr_buffers_type[BUF_DIRTY] <= nr_buffers * bdf_prm.b_un.nfract/100) {
+ /*
+ * Check whether to sleep or keep flushing.
+ */
+ if(nr_buffers_type[BUF_DIRTY] <= nr_buffers_to_wake) {
current->signal = 0;
interruptible_sleep_on(&bdflush_wait);
}

--------------810B48290A08742794EFAF50--