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:
parent
a974cefe6e
commit
2094ddb6f0
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user