summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2005-05-30 07:04:15 +0000
committerjeff <jeff@FreeBSD.org>2005-05-30 07:04:15 +0000
commit36b04bf4eadee1d96630fe6addee253d2461b816 (patch)
tree01a74bfd55c48f21f19962a6151291d3b1ae326b /sys
parent33b78c31e9736f90432e77668b42d6bea93f0469 (diff)
downloadFreeBSD-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.c20
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);
}
OpenPOWER on IntegriCloud