Fix a bug in vinvalbuf(). vinvalbuf() is usually called when attempting
authorMatthew Dillon <dillon@apollo.backplane.com>
Mon, 19 Jan 2009 17:38:27 +0000 (09:38 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Mon, 19 Jan 2009 17:38:27 +0000 (09:38 -0800)
to reclaim a vnode but can sometimes be called with V_SAVE when attempting
to make a vnode reclaimable.  In the latter case write races with other
threads can create new dirty buffers after the FSYNC returns.

Only assert that dirty buffers are not present if the vnode is undergoing
reclamation.

Reported-by: "Justin C. Sherrill" <justin@shiningsilence.com>
sys/kern/vfs_subr.c

index 902ff24..8c9f324 100644 (file)
@@ -304,9 +304,18 @@ vinvalbuf(struct vnode *vp, int flags, int slpflag, int slptimeo)
                        if ((error = VOP_FSYNC(vp, MNT_WAIT)) != 0)
                                return (error);
                        crit_enter();
-                       if (vp->v_track_write.bk_active > 0 ||
-                           !RB_EMPTY(&vp->v_rbdirty_tree))
+
+                       /*
+                        * Dirty bufs may be left or generated via races
+                        * in circumstances where vinvalbuf() is called on
+                        * a vnode not undergoing reclamation.   Only
+                        * panic if we are trying to reclaim the vnode.
+                        */
+                       if ((vp->v_flag & VRECLAIMED) &&
+                           (vp->v_track_write.bk_active > 0 ||
+                           !RB_EMPTY(&vp->v_rbdirty_tree))) {
                                panic("vinvalbuf: dirty bufs");
+                       }
                }
                crit_exit();
        }