diff options
author | dyson <dyson@FreeBSD.org> | 1998-03-17 06:30:52 +0000 |
---|---|---|
committer | dyson <dyson@FreeBSD.org> | 1998-03-17 06:30:52 +0000 |
commit | ca4225334c1231dd0bede79399e15e7b60ec0ec8 (patch) | |
tree | 2bf3f718735d8a30295bbb97553e50a9f9531e8b /sys | |
parent | e989cc12d5b9f5fe2b46ee9201c126456fe01230 (diff) | |
download | FreeBSD-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.c | 36 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 36 |
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); |