Re: [PATCH] 2.2.9: block_read bug

Stephen C. Tweedie (sct@redhat.com)
Fri, 28 May 1999 05:55:07 +0100 (BST)


Hi,

Linus, this patch looks as if it fixes a rather nasty
readahead/end-of-device bug lurking in the block read code.

On Mon, 24 May 1999 18:54:12 +0100 (GMT), Tim Waugh
<tim@cyberelk.demon.co.uk> said:

> There is a problem with block_read. While running badblocks on a
> particular partition on a particular machine, I've seen control fall out
> of the inner loop here with bhe equal to bhb, but with left still
> 1024.

That's perfectly OK. bhe==bhb just means that we have processed the
entire readahead buffer already. That buffer is a fixed length, so if
we request more data than will fit into it, we will still have non-zero
IO left at this point.

The problem only occurs if we go back round the loop with blocks==0. In
that case, we'll not submit any new IO requests but will treat the
readahead list as if it were full, not empty. Things go horribly wrong
at this point.

As far as I can tell, this can only occur if we truncated the requested
blocks count due to encountering the end of the device, but it does look
like a problem.

> The code is a little hard to follow. Here is a patch that prevents the
> bug from causing the otherwise inevitable oopses. Does someone who knows
> that code a little better than me want to take a closer look and see why
> this is happening in the first place?

Your patch looks perfectly good. We only get into difficulty if several
conditions are all met:

* last is non-zero: there is still space in the user buffer
* blocks is zero (we hit end-of-device)
* the readahead buffer has been emptied in this pass

In this case, we know for sure that there is nothing useful left to be
done: !blocks indicates no more IO left to submit, and (bhe == bhb)
indicates no more readahead buffer left to process. If the patch you
suggest not only looks correct but also actually fixes the problem, then
I think we have a winner.

--Stephen

----------------------------------------------------------------
--- block_dev.c.orig Mon May 24 18:41:04 1999
+++ block_dev.c Mon May 24 18:41:07 1999
@@ -273,6 +273,8 @@
if (++bhe == &buflist[NBUF])
bhe = buflist;
} while (left > 0 && bhe != bhb && (!*bhe || !buffer_locked(*bhe)));
+ if (bhe == bhb && !blocks)
+ break;
} while (left > 0);

/* Release the read-ahead blocks */

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