Skip site navigation (1)Skip section navigation (2)
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>

next in thread | raw e-mail | index | archive | help
    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);
}




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199507210029.RAA21522>