summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordyson <dyson@FreeBSD.org>1998-03-17 06:30:52 +0000
committerdyson <dyson@FreeBSD.org>1998-03-17 06:30:52 +0000
commitca4225334c1231dd0bede79399e15e7b60ec0ec8 (patch)
tree2bf3f718735d8a30295bbb97553e50a9f9531e8b /sys
parente989cc12d5b9f5fe2b46ee9201c126456fe01230 (diff)
downloadFreeBSD-src-ca4225334c1231dd0bede79399e15e7b60ec0ec8.zip
FreeBSD-src-ca4225334c1231dd0bede79399e15e7b60ec0ec8.tar.gz
Correct a severely evil bug in the vtruncbuf code. It didn't cause
me any problems until after the previous commit. This problem then caused a severe case of creeping crud on my diskdrive, and hosed my system so bad, that I needed to do a complete reinstall. Sorry!!! I assume that others have manifest this bug.
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/vfs_export.c36
-rw-r--r--sys/kern/vfs_subr.c36
2 files changed, 68 insertions, 4 deletions
diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c
index e93171b..6014991 100644
--- a/sys/kern/vfs_export.c
+++ b/sys/kern/vfs_export.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95
- * $Id: vfs_subr.c,v 1.141 1998/03/16 01:55:26 dyson Exp $
+ * $Id: vfs_subr.c,v 1.142 1998/03/16 02:13:03 dyson Exp $
*/
/*
@@ -679,7 +679,7 @@ vtruncbuf(vp, cred, p, length, blksize)
{
register struct buf *bp;
struct buf *nbp, *blist;
- int s, error, anyfreed;
+ int s, error, anyfreed, anymetadirty;
vm_object_t object;
int trunclbn;
@@ -687,6 +687,7 @@ vtruncbuf(vp, cred, p, length, blksize)
* Round up to the *next* lbn.
*/
trunclbn = ((length + blksize - 1) / blksize) * blksize;
+ anymetadirty = 0;
s = splbio();
restart:
@@ -738,9 +739,40 @@ restart:
(nbp->b_flags & B_DELWRI) == 0)) {
goto restart;
}
+ } else if (bp->b_lblkno < 0) {
+ anymetadirty++;
}
}
}
+
+rescan:
+ if ((length > 0) && anymetadirty) {
+ for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
+
+ nbp = LIST_NEXT(bp, b_vnbufs);
+
+ if ((bp->b_flags & B_DELWRI) && (bp->b_lblkno < 0)) {
+ if (bp->b_flags & B_BUSY) {
+ bp->b_flags |= B_WANTED;
+ tsleep((caddr_t) bp, PRIBIO, "vtrb3", 0);
+ nbp = bp;
+ continue;
+ } else {
+ bremfree(bp);
+ bp->b_flags |= B_ASYNC | B_BUSY;
+ VOP_BWRITE(bp);
+ goto rescan;
+ }
+ }
+ }
+ }
+
+ while (vp->v_numoutput > 0) {
+ vp->v_flag |= VBWAIT;
+ tsleep(&vp->v_numoutput, PVM, "vbtrunc", 0);
+ }
+
+
splx(s);
vnode_pager_setsize(vp, length);
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index e93171b..6014991 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95
- * $Id: vfs_subr.c,v 1.141 1998/03/16 01:55:26 dyson Exp $
+ * $Id: vfs_subr.c,v 1.142 1998/03/16 02:13:03 dyson Exp $
*/
/*
@@ -679,7 +679,7 @@ vtruncbuf(vp, cred, p, length, blksize)
{
register struct buf *bp;
struct buf *nbp, *blist;
- int s, error, anyfreed;
+ int s, error, anyfreed, anymetadirty;
vm_object_t object;
int trunclbn;
@@ -687,6 +687,7 @@ vtruncbuf(vp, cred, p, length, blksize)
* Round up to the *next* lbn.
*/
trunclbn = ((length + blksize - 1) / blksize) * blksize;
+ anymetadirty = 0;
s = splbio();
restart:
@@ -738,9 +739,40 @@ restart:
(nbp->b_flags & B_DELWRI) == 0)) {
goto restart;
}
+ } else if (bp->b_lblkno < 0) {
+ anymetadirty++;
}
}
}
+
+rescan:
+ if ((length > 0) && anymetadirty) {
+ for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
+
+ nbp = LIST_NEXT(bp, b_vnbufs);
+
+ if ((bp->b_flags & B_DELWRI) && (bp->b_lblkno < 0)) {
+ if (bp->b_flags & B_BUSY) {
+ bp->b_flags |= B_WANTED;
+ tsleep((caddr_t) bp, PRIBIO, "vtrb3", 0);
+ nbp = bp;
+ continue;
+ } else {
+ bremfree(bp);
+ bp->b_flags |= B_ASYNC | B_BUSY;
+ VOP_BWRITE(bp);
+ goto rescan;
+ }
+ }
+ }
+ }
+
+ while (vp->v_numoutput > 0) {
+ vp->v_flag |= VBWAIT;
+ tsleep(&vp->v_numoutput, PVM, "vbtrunc", 0);
+ }
+
+
splx(s);
vnode_pager_setsize(vp, length);
OpenPOWER on IntegriCloud