From d3751a41a6b471e235a0ec9e7942d11b331d6d6d Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Fri, 14 Dec 2012 13:05:00 -0800 Subject: [PATCH] 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)." --- sys/vfs/ufs/ffs_softdep.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/sys/vfs/ufs/ffs_softdep.c b/sys/vfs/ufs/ffs_softdep.c index d8a91f638d..58f8925205 100644 --- a/sys/vfs/ufs/ffs_softdep.c +++ b/sys/vfs/ufs/ffs_softdep.c @@ -4524,6 +4524,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; @@ -4572,7 +4573,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. -- 2.41.0