Re: Linux-2.2.0 bad VM behaviour "dd if=/dev/zero of=/dev/hdc

Stephen C. Tweedie (sct@redhat.com)
Fri, 5 Feb 1999 21:16:04 GMT


Hi,

On Wed, 27 Jan 1999 19:06:57 +0200, Petri Mattila <petri@prihateam.fi>
said:

>> I guess there is something wrong with the 2.2.0 vm... when I try this:
>>
>> dd if=/dev/zero of=/dev/hdc bs=256k
>>
>> the system becomes very lazy...

> I guess I found something: this unfortunate behaviour disappears
> if I turn off IDE DMA mode. With PIO modes there is hardly any
> swapping.

Can you try the patch below (made against 2.2.2-pre2)? The key is to
recognise that when we wake up bdflush, we need to take into account how
many dirty buffers there are; but when we decide whether or not to wait
for the bdflush pass to complete, it is BUF_LOCKED, not BUF_DIRTY,
buffers which are important. If we don't wait for bdflush once
BUF_LOCKED grows too high, then we will simply continue to create more
locked IO buffers until the request queues are completely saturated.

For low memory configurations, triggering the flush purely on the
percentage of dirty buffers makes no sense at all, so the patch also
starts a wakeup when the total locked+dirty memory exceeds a certain
threshold (currently 15% of memory).

The patch also includes the previously posted code to allow both sync
and bdflush to refile unlocked buffers on the locked list back onto the
clean list, to tidy up after async IO.

Only with all three of these items in place can I sustain decent
performance on a 16MB box while doing a background heavy
file/block-device write, as well as on a large 64MB configuration.

--Stephen

----------------------------------------------------------------
--- fs/buffer.c.~1~ Mon Jan 18 08:03:43 1999
+++ fs/buffer.c Fri Feb 5 21:00:33 1999
@@ -74,6 +74,7 @@

static int nr_buffers = 0;
static int nr_buffers_type[NR_LIST] = {0,};
+static int size_buffers_type[NR_LIST] = {0,};
static int nr_buffer_heads = 0;
static int nr_unused_buffer_heads = 0;

@@ -99,7 +100,8 @@
each time we call refill */
int nref_dirt; /* Dirty buffer threshold for activating bdflush
when trying to refill buffers. */
- int dummy1; /* unused */
+ int pct_dirt; /* Max %age of mem for dirty buffers before
+ activating bdflush */
int age_buffer; /* Time for normal buffer to age before
we flush it */
int age_super; /* Time for superblock to age before we
@@ -478,6 +480,7 @@
return;
}
nr_buffers_type[bh->b_list]--;
+ size_buffers_type[bh->b_list] -= bh->b_size;
remove_from_hash_queue(bh);
remove_from_lru_list(bh);
}
@@ -551,6 +554,7 @@
(*bhp)->b_prev_free = bh;

nr_buffers_type[bh->b_list]++;
+ size_buffers_type[bh->b_list] += bh->b_size;

/* Put the buffer in new hash-queue if it has a device. */
bh->b_next = NULL;
@@ -802,13 +806,19 @@
file_buffer(buf, dispose);
if(dispose == BUF_DIRTY) {
int too_many = (nr_buffers * bdf_prm.b_un.nfract/100);
+ int too_large = (num_physpages * bdf_prm.b_un.pct_dirt/100);

/* This buffer is dirty, maybe we need to start flushing.
* If too high a percentage of the buffers are dirty...
*/
- if (nr_buffers_type[BUF_DIRTY] > too_many)
- wakeup_bdflush(0);
-
+ if (nr_buffers_type[BUF_DIRTY] > too_many ||
+ (size_buffers_type[BUF_DIRTY] + size_buffers_type[BUF_LOCKED])/PAGE_SIZE > too_large) {
+ if (nr_buffers_type[BUF_LOCKED] > 2 * bdf_prm.b_un.ndirty)
+ wakeup_bdflush(1);
+ else
+ wakeup_bdflush(0);
+ }
+
/* If this is a loop device, and
* more than half of the buffers are dirty...
* (Prevents no-free-buffers deadlock with loop device.)
@@ -1604,7 +1614,7 @@
#ifdef DEBUG
for(nlist = 0; nlist < NR_LIST; nlist++)
#else
- for(nlist = BUF_DIRTY; nlist <= BUF_DIRTY; nlist++)
+ for(nlist = BUF_LOCKED; nlist <= BUF_DIRTY; nlist++)
#endif
{
ndirty = 0;
@@ -1623,8 +1633,13 @@
}

/* Clean buffer on dirty list? Refile it */
- if (nlist == BUF_DIRTY && !buffer_dirty(bh) && !buffer_locked(bh))
- {
+ if (nlist == BUF_DIRTY && !buffer_dirty(bh) && !buffer_locked(bh)) {
+ refile_buffer(bh);
+ continue;
+ }
+
+ /* Unlocked buffer on locked list? Refile it */
+ if (nlist == BUF_LOCKED && !buffer_locked(bh)) {
refile_buffer(bh);
continue;
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/