From 859db1e740e4eadcf0cc20f4394920860b5469f4 Mon Sep 17 00:00:00 2001 From: kib Date: Tue, 10 Apr 2007 09:30:41 +0000 Subject: [PATCH] Recalculate the NEWBLOCK flag for pagedep structure after the softdep lock is dropped, since pagedep may be already processed and deallocated. Found and tested by: kris MFC after: 2 weeks --- sys/ufs/ffs/ffs_softdep.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index 49c522c5f747..ae422dbfe16b 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -5008,7 +5008,7 @@ softdep_fsync(vp) struct buf *bp; struct fs *fs; struct thread *td = curthread; - int error, flushparent; + int error, flushparent, pagedep_new_block; ino_t parentino; ufs_lbn_t lbn; @@ -5086,15 +5086,36 @@ softdep_fsync(vp) * then we do the slower ffs_syncvnode of the directory. */ if (flushparent) { + int locked; + if ((error = ffs_update(pvp, 1)) != 0) { vput(pvp); return (error); } - if ((pagedep->pd_state & NEWBLOCK) && - (error = ffs_syncvnode(pvp, MNT_WAIT))) { - vput(pvp); - return (error); + ACQUIRE_LOCK(&lk); + locked = 1; + if (inodedep_lookup(mp, ip->i_number, 0, &inodedep) != 0) { + if ((wk = LIST_FIRST(&inodedep->id_pendinghd)) != NULL) { + if (wk->wk_type != D_DIRADD) + panic("softdep_fsync: Unexpected type %s", + TYPENAME(wk->wk_type)); + dap = WK_DIRADD(wk); + if (dap->da_state & DIRCHG) + pagedep = dap->da_previous->dm_pagedep; + else + pagedep = dap->da_pagedep; + pagedep_new_block = pagedep->pd_state & NEWBLOCK; + FREE_LOCK(&lk); + locked = 0; + if (pagedep_new_block && + (error = ffs_syncvnode(pvp, MNT_WAIT))) { + vput(pvp); + return (error); + } + } } + if (locked) + FREE_LOCK(&lk); } /* * Flush directory page containing the inode's name.