Date: Thu, 20 Jul 1995 17:29:43 -0700 From: Matt Dillon <dillon@best.com> To: bugs@freebsd.org Subject: verification of ffs_vget() bug Message-ID: <199507210029.RAA21522@shell1.best.com>
index | next in thread | raw e-mail
Here are some real numbers... the collision occurs much more often
then I would have thought in a heavily loaded system!
I believe this solves the 'dup alloc' panic we were getting in the inode
allocation routines. I still will not know for sure for another day or
two to see if the machine panics again. The panics generally occured
once a day, but it is obvious from the numbers below that the actual
inodes were getting munged much more often then that.
(my temporary ffs_vget() code is included below as well)
-Matt
Jul 20 12:40:09 shell1 /kernel: INODE COLLISION: mount f21a3e00 ino 54994
Jul 20 12:49:00 shell1 /kernel: INODE COLLISION: mount f21a3e00 ino 55046
Jul 20 12:54:24 shell1 /kernel: INODE COLLISION: mount f21a3a00 ino 38675
Jul 20 12:55:58 shell1 /kernel: INODE COLLISION: mount f21a3e00 ino 54978
Jul 20 13:08:39 shell1 /kernel: INODE COLLISION: mount f21a3e00 ino 55135
Jul 20 13:21:34 shell1 /kernel: INODE COLLISION: mount f21a3e00 ino 54978
Jul 20 13:21:43 shell1 /kernel: INODE COLLISION: mount f21a3e00 ino 54984
Jul 20 13:34:21 shell1 /kernel: INODE COLLISION: mount f21a3e00 ino 55177
Jul 20 13:40:50 shell1 /kernel: INODE COLLISION: mount f21a3e00 ino 55001
Jul 20 13:49:44 shell1 /kernel: INODE COLLISION: mount f21a3e00 ino 53837
Jul 20 14:04:19 shell1 /kernel: INODE COLLISION: mount f21a3e00 ino 55045
Jul 20 14:09:02 shell1 /kernel: INODE COLLISION: mount f21a3e00 ino 55169
Jul 20 14:30:16 shell1 /kernel: INODE COLLISION: mount f21a3e00 ino 53837
Jul 20 15:04:44 shell1 /kernel: INODE COLLISION: mount f219f200 ino 39130
Jul 20 17:09:37 shell1 /kernel: INODE COLLISION: mount f219f200 ino 92571
Jul 20 17:11:46 shell1 /kernel: INODE COLLISION: mount f21a3a00 ino 222911
/*
* Look up a FFS dinode number to find its incore vnode, otherwise read it
* in from disk. If it is in core, wait for the lock bit to clear, then
* return the inode locked. Detection and handling of mount points must be
* done by the calling routine.
*/
int ffs_inode_hash_lock = 0;
int
ffs_vget(mp, ino, vpp)
struct mount *mp;
ino_t ino;
struct vnode **vpp;
{
register struct fs *fs;
register struct inode *ip;
struct ufsmount *ump;
struct buf *bp;
struct vnode *vp;
dev_t dev;
int type, error;
ump = VFSTOUFS(mp);
dev = ump->um_dev;
if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
return (0);
/*
* lockout the creation of new entries in the FFS
* hash table in case getnewvnode/MALLOC blocks,
* otherwise a duplicate could occur!
*/
if (ffs_inode_hash_lock) {
while (ffs_inode_hash_lock) {
ffs_inode_hash_lock = -1;
tsleep(&ffs_inode_hash_lock, PVM, "ffsinohs", 0);
}
/*
* someone else allocated (dev,ino) before we could
*/
if ((*vpp = ufs_ihashget(dev, ino)) != NULL) {
printf("INODE COLLISION: mount %08lx ino %d\n",
(u_long)mp,
(int)ino
);
return (0);
}
}
ffs_inode_hash_lock = 1;
/* Allocate a new vnode/inode. */
type = ump->um_devvp->v_tag == VT_MFS ? M_MFSNODE : M_FFSNODE; /* XXX */
if ((error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) != 0) {
if (ffs_inode_hash_lock < 0) {
wakeup(&ffs_inode_hash_lock);
}
ffs_inode_hash_lock = 0;
*vpp = NULL;
return (error);
}
MALLOC(ip, struct inode *, sizeof(struct inode), type, M_WAITOK);
bzero((caddr_t)ip, sizeof(struct inode));
vp->v_data = ip;
ip->i_vnode = vp;
ip->i_fs = fs = ump->um_fs;
ip->i_dev = dev;
ip->i_number = ino;
#ifdef QUOTA
{
int i;
for (i = 0; i < MAXQUOTAS; i++)
ip->i_dquot[i] = NODQUOT;
}
#endif
/*
* Put it onto its hash chain and lock it so that other requests
* for this inode will block if they arrive while we are sleeping
* waiting for old data structures to be purged or for the
* contents of the disk portion of this inode to be read.
*/
ufs_ihashins(ip);
/*
* Wakeup anybody blocked in our lock
*/
if (ffs_inode_hash_lock < 0) {
wakeup(&ffs_inode_hash_lock);
}
ffs_inode_hash_lock = 0;
/* Read in the disk contents for the inode, copy into the inode. */
error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
(int)fs->fs_bsize, NOCRED, &bp);
if (error) {
/*
* The inode does not contain anything useful, so it would
* be misleading to leave it on its hash chain. With mode
* still zero, it will be unlinked and returned to the free
* list by vput().
*/
vput(vp);
brelse(bp);
*vpp = NULL;
return (error);
}
ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
brelse(bp);
/*
* Initialize the vnode from the inode, check for aliases.
* Note that the underlying vnode may have changed.
*/
error = ufs_vinit(mp, ffs_specop_p, FFS_FIFOOPS, &vp);
if (error) {
vput(vp);
*vpp = NULL;
return (error);
}
/*
* Finish inode initialization now that aliasing has been resolved.
*/
ip->i_devvp = ump->um_devvp;
VREF(ip->i_devvp);
/*
* Set up a generation number for this inode if it does not
* already have one. This should only happen on old filesystems.
*/
if (ip->i_gen == 0) {
if (++nextgennumber < (u_long)time.tv_sec)
nextgennumber = time.tv_sec;
ip->i_gen = nextgennumber;
if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
ip->i_flag |= IN_MODIFIED;
}
/*
* Ensure that uid and gid are correct. This is a temporary
* fix until fsck has been changed to do the update.
*/
if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
ip->i_uid = ip->i_din.di_ouid; /* XXX */
ip->i_gid = ip->i_din.di_ogid; /* XXX */
} /* XXX */
*vpp = vp;
return (0);
}
home |
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199507210029.RAA21522>
