Implement a lock in ffs_vget to prevent a race condition where two processes

try allocate the same inode/vnode, causing a duplicate.

Submitted by:	Matt Dillon, slightly reworked by me.
This commit is contained in:
David Greenman 1995-07-21 03:52:40 +00:00
parent a974cefe6e
commit 2094ddb6f0

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_vfsops.c 8.8 (Berkeley) 4/18/94
* $Id: ffs_vfsops.c,v 1.22 1995/06/28 12:01:08 davidg Exp $
* $Id: ffs_vfsops.c,v 1.23 1995/07/13 08:48:05 davidg Exp $
*/
#include <sys/param.h>
@ -737,6 +737,9 @@ ffs_sync(mp, waitfor, cred, p)
* 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;
@ -756,9 +759,28 @@ ffs_vget(mp, ino, vpp)
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
* may occur!
*/
if (ffs_inode_hash_lock) {
while (ffs_inode_hash_lock) {
ffs_inode_hash_lock = -1;
tsleep(&ffs_inode_hash_lock, PVM, "ffsvgt", 0);
}
if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
return (0);
}
ffs_inode_hash_lock = 1;
/* Allocate a new vnode/inode. */
error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp);
if (error) {
if (ffs_inode_hash_lock < 0) {
wakeup(&ffs_inode_hash_lock);
}
ffs_inode_hash_lock = 0;
*vpp = NULL;
return (error);
}
@ -772,9 +794,9 @@ ffs_vget(mp, ino, vpp)
ip->i_number = ino;
#ifdef QUOTA
{
int i;
for (i = 0; i < MAXQUOTAS; i++)
ip->i_dquot[i] = NODQUOT;
int i;
for (i = 0; i < MAXQUOTAS; i++)
ip->i_dquot[i] = NODQUOT;
}
#endif
/*
@ -785,6 +807,14 @@ ffs_vget(mp, ino, vpp)
*/
ufs_ihashins(ip);
/*
* Wakeup anybody blocked on 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);