tech-kern archive

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

Re: panic due to lost vnode flag



On Sat, Oct 24, 2009 at 01:58:44PM +0100, Mindaugas Rasiukevicius wrote:
> Hello,
> 
> Manuel Bouyer <bouyer%antioche.eu.org@localhost> wrote:
> > Could all thoses who have the problem try the attached patch (against
> > netbsd-5 but should apply without much problems to HEAD) ?
> 
> >             mutex_exit(&vp->v_interlock);
> > +           cv_broadcast(&vp->v_cv);
> 
> This (and other instances) are wrong i.e. cv_broadcast() must always be
> called with interlock held (in this case v_interlock).

thanks, this will make things easier :)
Here's a new diff.

-- 
Manuel Bouyer <bouyer%antioche.eu.org@localhost>
     NetBSD: 26 ans d'experience feront toujours la difference
--
Index: sys/ufs/ufs/ufs_ihash.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ufs/ufs_ihash.c,v
retrieving revision 1.26.10.1
diff -u -p -u -r1.26.10.1 ufs_ihash.c
--- sys/ufs/ufs/ufs_ihash.c     28 Sep 2009 01:43:02 -0000      1.26.10.1
+++ sys/ufs/ufs/ufs_ihash.c     24 Oct 2009 13:33:23 -0000
@@ -152,6 +152,7 @@ ufs_ihashget(dev_t dev, ino_t inum, int 
                                mutex_exit(&ufs_ihash_lock);
                                if (vget(vp, flags | LK_INTERLOCK))
                                        goto loop;
+#if 0
                                if (VTOI(vp) != ip ||
                                    ip->i_number != inum || ip->i_dev != dev) {
                                        /* lost race against vclean() */
@@ -161,6 +162,7 @@ ufs_ihashget(dev_t dev, ino_t inum, int 
                                        vp = NULL;
                                        goto loop;
                                }
+#endif
                        }
                        return (vp);
                }
Index: sys/kern/vfs_subr.c
===================================================================
RCS file: /cvsroot/src/sys/kern/vfs_subr.c,v
retrieving revision 1.357.4.5
diff -u -p -u -r1.357.4.5 vfs_subr.c
--- sys/kern/vfs_subr.c 21 Jul 2009 00:31:58 -0000      1.357.4.5
+++ sys/kern/vfs_subr.c 24 Oct 2009 13:33:23 -0000
@@ -370,6 +370,17 @@ try_nextlist:
        vp->v_freelisthd = NULL;
        mutex_exit(&vnode_free_list_lock);
 
+       if (vp->v_usecount != 0) {
+               /*
+                * was referenced again before we got the interlock
+                * Don't return to freelist - the holder of the last
+                * reference will destroy it.
+                */
+               vrelel(vp, 0); /* releases vp->v_interlock */
+               mutex_enter(&vnode_free_list_lock);
+               goto retry;
+       }
+
        /*
         * The vnode is still associated with a file system, so we must
         * clean it out before reusing it.  We need to add a reference
@@ -1288,6 +1299,22 @@ vget(vnode_t *vp, int flags)
                vrelel(vp, 0);
                return ENOENT;
        }
+
+       if ((vp->v_iflag & VI_INACTNOW) != 0) {
+               /*
+                * if it's being desactived, wait for it to complete.
+                * Make sure to not return a clean vnode.
+                */
+                if ((flags & LK_NOWAIT) != 0) {
+                       vrelel(vp, 0);
+                       return EBUSY;
+               }
+               vwait(vp, VI_INACTNOW);
+               if ((vp->v_iflag & VI_CLEAN) != 0) {
+                       vrelel(vp, 0);
+                       return ENOENT;
+               }
+       }
        if (flags & LK_TYPE_MASK) {
                error = vn_lock(vp, flags | LK_INTERLOCK);
                if (error != 0) {
@@ -1427,6 +1454,7 @@ vrelel(vnode_t *vp, int flags)
                        if (++vrele_pending > (desiredvnodes >> 8))
                                cv_signal(&vrele_cv); 
                        mutex_exit(&vrele_lock);
+                       cv_broadcast(&vp->v_cv);
                        mutex_exit(&vp->v_interlock);
                        return;
                }
@@ -1451,6 +1479,7 @@ vrelel(vnode_t *vp, int flags)
                VOP_INACTIVE(vp, &recycle);
                mutex_enter(&vp->v_interlock);
                vp->v_iflag &= ~VI_INACTNOW;
+               cv_broadcast(&vp->v_cv);
                if (!recycle) {
                        if (vtryrele(vp)) {
                                mutex_exit(&vp->v_interlock);


Home | Main Index | Thread Index | Old Index