Qing Liu wrote:>
> Hi,
>
> With kernel 2.4.10, when I do
>
> $ mkdir foo; cd foo; rmdir ../foo; ls
>
> then ls becomes zombie.
>
You oopsed. When I do it the machine instantaneously reboots.
Oh Dear.
It's an error in the new directory readhead optimisation. When
it's dealing with a zero-length directory it overindexes the
local array `bh_use[]' and uses an uninitialised variable as
a buffer-head pointer and dies in this code:
if ((bh = bh_use[ra_ptr++]) == NULL)
goto next;
wait_on_buffer(bh);
in ext3_find_entry().
I think in fact this overindexing happens quite often, but it is
only with zero-length directories that the zeroeth entry of the
local array contains uninitialised garbage. For other directory
sizes, it will conveniently contain a pointer to a previously-read
buffer and the error won't be noticed.
Thanks for the report. This patch should fix it. Does it
look OK to you, Ted?
--- fs/ext3/namei.c.orig Sun Oct 7 21:15:27 2001
+++ fs/ext3/namei.c Sun Oct 7 21:41:08 2001
@@ -112,7 +112,11 @@
struct buffer_head * bh_use[NAMEI_RA_SIZE];
struct buffer_head * bh, *ret = NULL;
unsigned long start, block, b;
- int ra_ptr = 0, ra_max = 0, num = 0;
+ int ra_max = 0; /* Number of bh's in the readahead
+ buffer, bh_use[] */
+ int ra_ptr = 0; /* Current index into readahead
+ buffer */
+ int num = 0;
int nblocks, i, err;
struct inode *dir = dentry->d_parent->d_inode;
@@ -130,12 +134,19 @@
* We deal with the read-ahead logic here.
*/
if (ra_ptr >= ra_max) {
+ /* Refill the readahead buffer */
ra_ptr = 0;
b = block;
for (ra_max = 0; ra_max < NAMEI_RA_SIZE; ra_max++) {
- if (b >= nblocks ||
- (num && block == start))
+ /*
+ * Terminate if we reach the end of the
+ * directory and must wrap, or if our
+ * search has finished at this block.
+ */
+ if (b >= nblocks || (num && block == start)) {
+ bh_use[ra_max] = NULL;
break;
+ }
num++;
bh = ext3_getblk(NULL, dir, b++, 0, &err);
bh_use[ra_max] = bh;