Re: [PATCH] Re: Corrupted inode list?

Stephen C. Tweedie (sct@dcs.ed.ac.uk)
Fri, 29 Nov 1996 21:35:00 GMT


Hi all,

In article <Pine.LNX.3.91.961129141318.3862A-100000@dot.superaje.com> Benjamin C R LaHaise <blah@dot.superaje.com> writes:

> On Thu, 28 Nov 1996, Andrew E. Mileski wrote:

>> I've tracked down my REPEATABLE OOPSes to the inode list getting
>> corrupted...at least that is my take on it. This happens after a
>> lot of activity on an IDE VFAT fs.
>>
>> In fs/inode.c, sync_inodes() will try to de-reference a NULL pointer :-(
>> The real problem is, how is the list getting corrupted in the first place
>>

Ahh, *this* ugly problem rears its head again. I thought we had slain
this three years ago. :)

> Ok, this is still the same bug I've had a patch avail for the past
> month... no more inode corruption. The following patch fixes the
> following:
> a. inode list corrupted if put_inode slept after calling
> clear_inode, inode could be allocated by iget

This shouldn't happen. We found this problem after a long period of
searching, and Linus and I fixed it before 1.0. It is _really_ subtle
--- anybody remember all the "bit already cleared" error reports that
were floating around just prior to 1.0?

The problem hasn't been seen in years, but if you are experiencing it
on a VFAT filesystem then my immediate reaction is that FAT itself is
doing something wrong.

On investigation this appears to be the case --- FAT is ignoring a
totally undocumented requirement of the VFS. :) The reuse of inodes
can't happen as long as the put_inode() operation keeps the inode
in-use flag set right up until the end. Under the ext2fs, for
example, we call clear_inode() (thus clearing inode->i_nlinks) right
before the final unlock and return in ext2_free_inode(). FAT,
however, clears the inode and then continues to iput() a couple of
other inodes, an operation which can block. <Beep> Wrong move, you
lose.

Does this much smaller patch fix your problem?

Cheers,
Stephen.
----------------------------------------------------------------
--- fs/fat/inode.c.~1~ Thu Sep 4 11:22:39 1980
+++ fs/fat/inode.c Fri Nov 29 21:30:48 1996
@@ -48,13 +48,12 @@
}
inode->i_size = 0;
fat_truncate(inode);
- clear_inode(inode);
if (depend) {
if (MSDOS_I(depend)->i_old != inode) {
printk("Invalid link (0x%p): expected 0x%p, got 0x%p\n",
depend, inode, MSDOS_I(depend)->i_old);
fat_fs_panic(sb,"...");
- return;
+ goto done;
}
MSDOS_I(depend)->i_old = NULL;
iput(depend);
@@ -64,11 +63,13 @@
printk("Invalid link (0x%p): expected 0x%p, got 0x%p\n",
linked, inode, MSDOS_I(linked)->i_oldlink);
fat_fs_panic(sb,"...");
- return;
+ goto done;
}
MSDOS_I(linked)->i_oldlink = NULL;
iput(linked);
}
+done:
+ clear_inode(inode);
}