Messages in this thread Patch in this message |  | | Date | Fri, 29 Nov 1996 21:35:00 GMT | From | "Stephen C. Tweedie" <> | Subject | Re: [PATCH] Re: Corrupted inode list? |
| |
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); }
|  |