This may or may not be related. In tracking down the sched_sync() panic I found two bugs.
First, a couple of places where the worklist was not being protected at splbio(). I'm not 100% sure that this is a problem but the code is complex enough that it's just too dangerous not to do it. Second, a double LIST_REMOVE() was being performed in the case where VOP_FSYNC() would fail to sync all the dirty pages. This can occur legally for both NFS and filesystems with SOFTUPDATES set. I'd appreciate it if someone could verify the double LIST_REMOVE() bug. vn_syncer_add_to_worklist() already removes the vn from the list ( assuming the VONWORKLIST v_flag is set, which it should be in this case ). -Matt Matthew Dillon <dil...@backplane.com> Index: kern/vfs_subr.c =================================================================== RCS file: /home/ncvs/src/sys/kern/vfs_subr.c,v retrieving revision 1.186 diff -u -r1.186 vfs_subr.c --- vfs_subr.c 1999/02/04 18:25:39 1.186 +++ vfs_subr.c 1999/02/19 10:40:17 @@ -881,10 +881,8 @@ /* * Add an item to the syncer work queue. */ -void -vn_syncer_add_to_worklist(vp, delay) - struct vnode *vp; - int delay; +static void +vn_syncer_add_to_worklist(struct vnode *vp, int delay) { int s, slot; @@ -928,7 +926,8 @@ starttime = time_second; /* - * Push files whose dirty time has expired. + * Push files whose dirty time has expired. Be careful + * of interrupt race on slp queue. */ s = splbio(); slp = &syncer_workitem_pending[syncer_delayno]; @@ -941,16 +940,20 @@ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); (void) VOP_FSYNC(vp, p->p_ucred, MNT_LAZY, p); VOP_UNLOCK(vp, 0, p); + s = splbio(); if (LIST_FIRST(slp) == vp) { if (TAILQ_EMPTY(&vp->v_dirtyblkhd) && vp->v_type != VBLK) - panic("sched_sync: fsync failed"); + panic("sched_sync: fsync failed vp %p type %d tag %d", vp, vp->v_type, vp->v_tag); /* * Move ourselves to the back of the sync list. + * vn_syncer_*worklist() will remove and re-add + * the node. */ - LIST_REMOVE(vp, v_synclist); + /*LIST_REMOVE(vp, v_synclist);*/ vn_syncer_add_to_worklist(vp, syncdelay); } + splx(s); } /* @@ -2841,6 +2844,8 @@ /* * The syncer vnode is no longer needed and is being decommissioned. + * + * Modifications to the worklist must be protected at splbio(). */ static int sync_reclaim(ap) @@ -2849,12 +2854,15 @@ } */ *ap; { struct vnode *vp = ap->a_vp; + int s; + s = splbio(); vp->v_mount->mnt_syncer = NULL; if (vp->v_flag & VONWORKLST) { LIST_REMOVE(vp, v_synclist); vp->v_flag &= ~VONWORKLST; } + splx(s); return (0); } To Unsubscribe: send mail to majord...@freebsd.org with "unsubscribe freebsd-current" in the body of the message