Date: Wed, 19 Jul 1995 05:24:07 -0700 From: Matt Dillon <dillon@blob.best.net> To: bugs@freebsd.org Subject: probable race condition in ufs/ffs/ffs_vfsops.c:ffs_vget() Message-ID: <199507191224.FAA26031@blob.best.net>
index | next in thread | raw e-mail
We've been getting the following panic:
panic: ffs_valloc: dup alloc
It took a long while, and I could find no *direct* cause of the panic.
Fortunately I had a debug kernel and a crash dump to work with. I
still have it in case this doesn't turn out to solve the problem.
It would appear that the inode that was allocated from the bitmap
was VERY much in use... a non-zero length REG file with very valid-looking
fields.
The weird thing is that the latest access/modify/change timestamp
on the inode was several HUNDRED seconds earlier then the time of the
crash.
I believe I have found the problem... a race condition in ffs_vget().
Here's a synopsis:
(1) lookup (dev,ino) in hash table, return on success
(2) allocate new vnode and new inode structure MALLOC(..., M_WAITOK)
for the inode
(3) enter new inode into hash table.
The problem is that MALLOC() can block. If it does, you can potentially
have TWO processes attempt to lookup an uncached inode simultaniously
in a low memory situation. The MALLOC() blocks until memory is available,
both processes unblock *AFTER* having determined that the inode
wasn't cached, and *both* processes allocate new vnode/inode structures
representing the *same* inode and enter both of them into the hash table.
At some point in the future the inode is deallocated and the bitmap
for it cleared, but this only removes one of the two cached inode
structures. sync() comes along and commits the other one... poof,
you now have an active inode on the platter whos bitmap entry is
cleared. At some later time someone tries to create a new file and
BANG it hits the screwed inode.
The solution, as far as I can tell, is to check the hash table after
MALLOC returns as well as before to determine if another process beat
us to it. I put the following code just before the ufs_ihashins(). I
do NOT know whether this code fixes the problem yet or even if the
code is valid in terms of freeing the right stuff before returning...
(I'll tell you in a few days re: the crashes... I'll either get
more panics or I will not).
#if 1
if ((*vpp = ufs_ihashget(dev, ino)) != NULL) {
vp->v_data = NULL;
vput(vp);
printf("INODE COLLISION: %d\n", ino);
FREE(ip, type);
return (0);
}
#endif
... ufs_ihashins(ip); ... etc...
-Matt
home |
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199507191224.FAA26031>
