diff options
author | dg <dg@FreeBSD.org> | 1995-07-21 03:52:40 +0000 |
---|---|---|
committer | dg <dg@FreeBSD.org> | 1995-07-21 03:52:40 +0000 |
commit | ab7b1f1cbf4311e97abb82a8de2d1986ccb004cb (patch) | |
tree | 4af364867f767d9e5432fa09668a82182f7f7783 /sys | |
parent | f369859c3287504df6edba262c6f8a9ba1cc8ce3 (diff) | |
download | FreeBSD-src-ab7b1f1cbf4311e97abb82a8de2d1986ccb004cb.zip FreeBSD-src-ab7b1f1cbf4311e97abb82a8de2d1986ccb004cb.tar.gz |
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.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/ufs/ffs/ffs_vfsops.c | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index f1fdb16..a3595d4 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -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 @@ loop: * 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); |