diff options
author | jeff <jeff@FreeBSD.org> | 2005-05-30 07:04:15 +0000 |
---|---|---|
committer | jeff <jeff@FreeBSD.org> | 2005-05-30 07:04:15 +0000 |
commit | 36b04bf4eadee1d96630fe6addee253d2461b816 (patch) | |
tree | 01a74bfd55c48f21f19962a6151291d3b1ae326b /sys | |
parent | 33b78c31e9736f90432e77668b42d6bea93f0469 (diff) | |
download | FreeBSD-src-36b04bf4eadee1d96630fe6addee253d2461b816.zip FreeBSD-src-36b04bf4eadee1d96630fe6addee253d2461b816.tar.gz |
- Don't set our bio op to be a READ when we've just completed a write. There
are subtle differences in the read and write completion path. Instead,
grab an extra write ref so the write path can drop it when we recursively
call bufdone(). I believe this may be the source of the wrong bufobj
panics.
Reported by: pho, kkenn
Diffstat (limited to 'sys')
-rw-r--r-- | sys/ufs/ffs/ffs_vfsops.c | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index dee50b0..eeaf861 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -1507,15 +1507,19 @@ SYSCTL_INT(_debug, OID_AUTO, dobkgrdwrite, CTLFLAG_RW, &dobkgrdwrite, 0, static void ffs_backgroundwritedone(struct buf *bp) { + struct bufobj *bufobj; struct buf *origbp; /* * Find the original buffer that we are writing. */ - BO_LOCK(bp->b_bufobj); + bufobj = bp->b_bufobj; + BO_LOCK(bufobj); if ((origbp = gbincore(bp->b_bufobj, bp->b_lblkno)) == NULL) panic("backgroundwritedone: lost buffer"); - BO_UNLOCK(bp->b_bufobj); + /* Grab an extra reference to be dropped by the bufdone() below. */ + bufobj_wrefl(bufobj); + BO_UNLOCK(bufobj); /* * Process dependencies then return any unfinished ones. */ @@ -1525,18 +1529,14 @@ ffs_backgroundwritedone(struct buf *bp) if (LIST_FIRST(&bp->b_dep) != NULL) softdep_move_dependencies(bp, origbp); #endif - /* - * This buffer is marked B_NOCACHE, so when it is released - * by biodone, it will be tossed. We mark it with BIO_READ - * to avoid biodone doing a second bufobj_wdrop. + * This buffer is marked B_NOCACHE so when it is released + * by biodone it will be tossed. */ bp->b_flags |= B_NOCACHE; - bp->b_iocmd = BIO_READ; bp->b_flags &= ~(B_CACHE | B_DONE); - bp->b_iodone = 0; bufdone(bp); - BO_LOCK(origbp->b_bufobj); + BO_LOCK(bufobj); /* * Clear the BV_BKGRDINPROG flag in the original buffer * and awaken it if it is waiting for the write to complete. @@ -1550,7 +1550,7 @@ ffs_backgroundwritedone(struct buf *bp) origbp->b_vflags &= ~BV_BKGRDWAIT; wakeup(&origbp->b_xflags); } - BO_UNLOCK(origbp->b_bufobj); + BO_UNLOCK(bufobj); } |