Messages in this thread Patch in this message | | | Date | Fri, 5 Feb 1999 21:16:04 GMT | From | "Stephen C. Tweedie" <> | Subject | Re: Linux-2.2.0 bad VM behaviour "dd if=/dev/zero of=/dev/hdc bs=256k" |
| |
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/
| |