kernel panic

Matthew Dillon dillon at apollo.backplane.com
Sat Oct 29 22:25:47 PDT 2005


    Ok, here is a preliminary patch.  From what I can tell the msync path
    was not locking the underlying vnode across the vnode_pager_putpages()
    call.  If the related pages were filled in via mmap() instead of write(),
    the the FFS balloc code might end up being called without the vnode
    held locked. 

    It is possible that the bug is also responsible for Tomaz and DR's
    dirbad panics.  However, the equivalent FreeBSD-HEAD code *does* lock
    the vnode across the putpages call and they have reported that same
    bug so I just don't know.  If not for that I'd say that your bug report
    would almost be a smoking gun. 

    Please tell me if this stops the panics you've been getting.

					-Matt

Index: kern/vfs_subr.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_subr.c,v
retrieving revision 1.64
diff -u -r1.64 vfs_subr.c
--- kern/vfs_subr.c	17 Sep 2005 07:43:00 -0000	1.64
+++ kern/vfs_subr.c	30 Oct 2005 05:14:02 -0000
@@ -1777,6 +1777,10 @@
  * vnodes whos VM objects no longer contain pages.
  *
  * NOTE: MNT_WAIT still skips vnodes in the VXLOCK state.
+ *
+ * NOTE: XXX VOP_PUTPAGES and friends requires that the vnode be locked,
+ * but vnode_pager_putpages() doesn't lock the vnode.  We have to do it
+ * way up in this high level function.
  */
 static int vfs_msync_scan1(struct mount *mp, struct vnode *vp, void *data);
 static int vfs_msync_scan2(struct mount *mp, struct vnode *vp, void *data);
@@ -1784,7 +1788,12 @@
 void
 vfs_msync(struct mount *mp, int flags) 
 {
-	vmntvnodescan(mp, VMSC_REFVP, vfs_msync_scan1, vfs_msync_scan2,
+	int vmsc_flags;
+
+	vmsc_flags = VMSC_GETVP;
+	if (flags != MNT_WAIT)
+		vmsc_flags |= VMSC_NOWAIT;
+	vmntvnodescan(mp, vmsc_flags, vfs_msync_scan1, vfs_msync_scan2,
 			(void *)flags);
 }
 
@@ -1815,6 +1824,9 @@
 	return(-1);
 }
 
+/*
+ * This callback is handed a locked vnode.
+ */
 static
 int
 vfs_msync_scan2(struct mount *mp, struct vnode *vp, void *data)
@@ -1826,8 +1838,7 @@
 		return(0);
 
 	if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
-	    (vp->v_flag & VOBJDIRTY) &&
-	    (flags == MNT_WAIT || VOP_ISLOCKED(vp, NULL) == 0)) {
+	    (vp->v_flag & VOBJDIRTY)) {
 		if (VOP_GETVOBJECT(vp, &obj) == 0) {
 			vm_object_page_clean(obj, 0, 0, 
 			 flags == MNT_WAIT ? OBJPC_SYNC : OBJPC_NOSYNC);





More information about the Bugs mailing list