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