From: Matthew Dillon Date: Fri, 14 Dec 2012 21:05:00 +0000 (-0800) Subject: kernel - ufs softdep fix under heavy load X-Git-Tag: v3.4.0rc~672 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/01a04a60873088916e4c5bcd230359c3ca654a9d kernel - ufs softdep fix under heavy load Fix is from OpenBSD ffs_softdep.c v1.79, originally from FreeBSD ffs_softdep.c 1.196. Commit message from OpenBSD: "due to ffs_sync not be able to sync some buffers here is another instance of softdep code that must ensure proper syncing. try harder to flush MKDIR_BODY dependancy if such still exists during pagedep flush (that is by syncing first block of the dir)." --- diff --git a/sys/vfs/ufs/ffs_softdep.c b/sys/vfs/ufs/ffs_softdep.c index 942245cb5f..d2e43b6272 100644 --- a/sys/vfs/ufs/ffs_softdep.c +++ b/sys/vfs/ufs/ffs_softdep.c @@ -4527,6 +4527,7 @@ flush_pagedep_deps(struct vnode *pvp, struct mount *mp, struct inodedep *inodedep; struct ufsmount *ump; struct diradd *dap; + struct worklist *wk; struct vnode *vp; int gotit, error = 0; struct buf *bp; @@ -4575,7 +4576,32 @@ flush_pagedep_deps(struct vnode *pvp, struct mount *mp, break; } drain_output(vp, 0); + /* + * If first block is still dirty with a D_MKDIR + * dependency then it needs to be written now. + */ + error = 0; + ACQUIRE_LOCK(&lk); + bp = findblk(vp, 0, FINDBLK_TEST); + if (bp == NULL) { + FREE_LOCK(&lk); + goto mkdir_body_continue; + } + LIST_FOREACH(wk, &bp->b_dep, wk_list) + if (wk->wk_type == D_MKDIR) { + gotit = getdirtybuf(&bp, MNT_WAIT); + FREE_LOCK(&lk); + if (gotit && (error = bwrite(bp)) != 0) + goto mkdir_body_continue; + break; + } + if (wk == NULL) + FREE_LOCK(&lk); + mkdir_body_continue: vput(vp); + /* Flushing of first block failed. */ + if (error) + break; ACQUIRE_LOCK(&lk); /* * If that cleared dependencies, go on to next.