summaryrefslogtreecommitdiffstats
path: root/sys/ufs
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2007-04-10 09:30:41 +0000
committerkib <kib@FreeBSD.org>2007-04-10 09:30:41 +0000
commit859db1e740e4eadcf0cc20f4394920860b5469f4 (patch)
tree0a3706d9c22c63cbf546166c51e74a259be6eb24 /sys/ufs
parent61f6e27c6233361ae5133ec1cd6e06406bf5ac42 (diff)
downloadFreeBSD-src-859db1e740e4eadcf0cc20f4394920860b5469f4.zip
FreeBSD-src-859db1e740e4eadcf0cc20f4394920860b5469f4.tar.gz
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
Diffstat (limited to 'sys/ufs')
-rw-r--r--sys/ufs/ffs/ffs_softdep.c31
1 files changed, 26 insertions, 5 deletions
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 49c522c..ae422db 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.
OpenPOWER on IntegriCloud