summaryrefslogtreecommitdiffstats
path: root/sys/ufs
diff options
context:
space:
mode:
authordg <dg@FreeBSD.org>1995-07-21 03:52:40 +0000
committerdg <dg@FreeBSD.org>1995-07-21 03:52:40 +0000
commitab7b1f1cbf4311e97abb82a8de2d1986ccb004cb (patch)
tree4af364867f767d9e5432fa09668a82182f7f7783 /sys/ufs
parentf369859c3287504df6edba262c6f8a9ba1cc8ce3 (diff)
downloadFreeBSD-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/ufs')
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c38
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);
OpenPOWER on IntegriCloud