Re: [2.4.17/18pre] VM and swap - it's really unusable

Andrew Morton
2002-01-14T20:36:42Z

Andrea Arcangeli wrote:
>
> > --- linux-2.4.18-pre3/fs/buffer.c Fri Dec 21 11:19:14 2001
> > +++ linux-akpm/fs/buffer.c Sat Jan 12 12:22:29 2002
> > @@ -249,12 +249,19 @@ static int wait_for_buffers(kdev_t dev,
> > struct buffer_head * next;
> > int nr;
> >
> > - next = lru_list[index];
> > nr = nr_buffers_type[index];
> > +repeat:
> > + next = lru_list[index];
> > while (next && --nr >= 0) {
> > struct buffer_head *bh = next;
> > next = bh->b_next_free;
> >
> > + if (dev == NODEV && current->need_resched) {
> > + spin_unlock(&lru_list_lock);
> > + conditional_schedule();
> > + spin_lock(&lru_list_lock);
> > + goto repeat;
> > + }
> > if (!buffer_locke
> > d(bh)) {
>
> this introduces possibility of looping indefinitely, this is why I
> rejected it while I merged the mini-ll other points into -aa, if you
> want to do anything like that at the very least you should roll the head
> of the list as well or something like that.

I ended up deciding that the `NODEV' check here avoids livelocks.
Unless, of course, the scheduling pressure is so high that we can't
even run a few statements. I which case the interrupt load will be so
high that the machine stops anyway. Possibly it needs to check `refile'
as well.

A technique I frequently use in the full-ll patch is to only reschedule
after we've executed the loop (say) 16 times before dropping out. This
assures that forward progress is made. There's a test mode in the full
ll patch - in this mode, it *always* assumes that need_resched is true.
If the patch runs OK in this mode without livelocking, we know that it
can't livelock.

Anyway, I'll revisit this. It is a "must fix". wait_for_buffers() is
possibly the worst cause of latency in the kernel. The usual scenario
is where kupdate has written 10,000 buffers and then sleeps. Next time
it wakes, it has 10,000 clean, unlocked buffers to move from BUF_LOCKED
onto BUF_CLEAN. It does this with lru_list_lock held.

-