Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-1-5]: src/sys pullup from trunk:



details:   https://anonhg.NetBSD.org/src/rev/cb68836d2523
branches:  netbsd-1-5
changeset: 488368:cb68836d2523
user:      fvdl <fvdl%NetBSD.org@localhost>
date:      Mon Jul 03 17:34:49 2000 +0000

description:
pullup from trunk:

Fix a "locking against myself" problem; holding ufs_hashlock
across getnewvnode() could cause a recursive lock if it resulted in
recycling a vnode that was using softdeps.

diffstat:

 sys/kern/vfs_subr.c            |  32 +++++++++++++++++++++++++++++++-
 sys/sys/vnode.h                |   3 ++-
 sys/ufs/ext2fs/ext2fs_vfsops.c |  18 ++++++++++++------
 sys/ufs/ffs/ffs_vfsops.c       |  22 ++++++++++++++++------
 4 files changed, 61 insertions(+), 14 deletions(-)

diffs (143 lines):

diff -r 85fadb45f10d -r cb68836d2523 sys/kern/vfs_subr.c
--- a/sys/kern/vfs_subr.c       Mon Jul 03 08:34:44 2000 +0000
+++ b/sys/kern/vfs_subr.c       Mon Jul 03 17:34:49 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vfs_subr.c,v 1.128 2000/06/10 18:44:44 sommerfeld Exp $        */
+/*     $NetBSD: vfs_subr.c,v 1.128.2.1 2000/07/03 17:36:02 fvdl Exp $  */
 
 /*-
  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
@@ -542,6 +542,36 @@
 }
 
 /*
+ * This is really just the reverse of getnewvnode(). Needed for
+ * VFS_VGET functions who may need to push back a vnode in case
+ * of a locking race.
+ */
+void
+ungetnewvnode(vp)
+       struct vnode *vp;
+{
+#ifdef DIAGNOSTIC
+       if (vp->v_usecount != 1)
+               panic("ungetnewvnode: busy vnode");
+#endif
+       vp->v_usecount--;
+       insmntque(vp, NULL);
+       vp->v_type = VBAD;
+
+       simple_lock(&vp->v_interlock);
+       /* 
+        * Insert at head of LRU list
+        */
+       simple_lock(&vnode_free_list_slock);
+       if (vp->v_holdcnt > 0)
+               TAILQ_INSERT_HEAD(&vnode_hold_list, vp, v_freelist);
+       else
+               TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
+       simple_unlock(&vnode_free_list_slock); 
+       simple_unlock(&vp->v_interlock);
+}
+
+/*
  * Move a vnode from one mount queue to another.
  */
 void
diff -r 85fadb45f10d -r cb68836d2523 sys/sys/vnode.h
--- a/sys/sys/vnode.h   Mon Jul 03 08:34:44 2000 +0000
+++ b/sys/sys/vnode.h   Mon Jul 03 17:34:49 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vnode.h,v 1.77 2000/06/10 18:27:05 assar Exp $ */
+/*     $NetBSD: vnode.h,v 1.77.2.1 2000/07/03 17:34:49 fvdl Exp $      */
 
 /*
  * Copyright (c) 1989, 1993
@@ -487,6 +487,7 @@
 int    cdevvp __P((dev_t dev, struct vnode **vpp));
 int    getnewvnode __P((enum vtagtype tag, struct mount *mp,
                         int (**vops) __P((void *)), struct vnode **vpp));
+void   ungetnewvnode __P((struct vnode *));
 int    getvnode __P((struct filedesc *fdp, int fd, struct file **fpp));
 void   vfs_getnewfsid __P((struct mount *));
 int    speedup_syncer __P((void));
diff -r 85fadb45f10d -r cb68836d2523 sys/ufs/ext2fs/ext2fs_vfsops.c
--- a/sys/ufs/ext2fs/ext2fs_vfsops.c    Mon Jul 03 08:34:44 2000 +0000
+++ b/sys/ufs/ext2fs/ext2fs_vfsops.c    Mon Jul 03 17:34:49 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ext2fs_vfsops.c,v 1.36 2000/05/29 18:34:36 mycroft Exp $       */
+/*     $NetBSD: ext2fs_vfsops.c,v 1.36.2.1 2000/07/03 17:44:02 fvdl Exp $      */
 
 /*
  * Copyright (c) 1997 Manuel Bouyer.
@@ -836,17 +836,23 @@
 
        ump = VFSTOUFS(mp);
        dev = ump->um_dev;
-       do {
-               if ((*vpp = ufs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL)
-                       return (0);
-       } while (lockmgr(&ufs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0));
+
+       if ((*vpp = ufs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL)
+               return (0);
 
        /* Allocate a new vnode/inode. */
        if ((error = getnewvnode(VT_EXT2FS, mp, ext2fs_vnodeop_p, &vp)) != 0) {
                *vpp = NULL;
-               lockmgr(&ufs_hashlock, LK_RELEASE, 0);
                return (error);
        }
+
+       do {
+               if ((*vpp = ufs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL) {
+                       ungetnewvnode(vp);
+                       return (0);
+               }
+       } while (lockmgr(&ufs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0));
+
        ip = pool_get(&ext2fs_inode_pool, PR_WAITOK);
        memset((caddr_t)ip, 0, sizeof(struct inode));
        vp->v_data = ip;
diff -r 85fadb45f10d -r cb68836d2523 sys/ufs/ffs/ffs_vfsops.c
--- a/sys/ufs/ffs/ffs_vfsops.c  Mon Jul 03 08:34:44 2000 +0000
+++ b/sys/ufs/ffs/ffs_vfsops.c  Mon Jul 03 17:34:49 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ffs_vfsops.c,v 1.67 2000/06/16 05:45:14 perseant Exp $ */
+/*     $NetBSD: ffs_vfsops.c,v 1.67.2.1 2000/07/03 17:44:03 fvdl Exp $ */
 
 /*
  * Copyright (c) 1989, 1991, 1993, 1994
@@ -1008,17 +1008,27 @@
 
        ump = VFSTOUFS(mp);
        dev = ump->um_dev;
-       do {
-               if ((*vpp = ufs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL)
-                       return (0);
-       } while (lockmgr(&ufs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0));
+
+       if ((*vpp = ufs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL)
+               return (0);
 
        /* Allocate a new vnode/inode. */
        if ((error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) != 0) {
                *vpp = NULL;
-               lockmgr(&ufs_hashlock, LK_RELEASE, 0);
                return (error);
        }
+
+       /*
+        * If someone beat us to it while sleeping in getnewvnode(),
+        * push back the freshly allocated vnode we don't need, and return.
+        */
+       do {
+               if ((*vpp = ufs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL) {
+                       ungetnewvnode(vp);
+                       return (0);
+               }
+       } while (lockmgr(&ufs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0));
+
        /*
         * XXX MFS ends up here, too, to allocate an inode.  Should we
         * XXX create another pool for MFS inodes?



Home | Main Index | Thread Index | Old Index