From 737dec82d682ba60bd5c3120d79cacd20d19fd41 Mon Sep 17 00:00:00 2001 From: perseant Date: Fri, 5 May 2000 20:59:20 +0000 Subject: [PATCH] Change the way LFS does block accounting, from trying to infer from the buffer cache flags, to marking the inode and/or indirect blocks with a special disk address UNWRITTEN==-2 when a block is accounted for. (This address is never written to disk, but only used in-core. This is essentially the same method of block accounting as on the UBC branch, where the buffer headers don't exist.) Make sure that truncation is handled properly, especially in the case of holey files. Fixes PR#9994. --- sys/ufs/lfs/lfs.h | 6 +- sys/ufs/lfs/lfs_balloc.c | 78 ++++++++++++++++++++----- sys/ufs/lfs/lfs_bio.c | 15 ++++- sys/ufs/lfs/lfs_inode.c | 120 ++++++++++++++++++++------------------ sys/ufs/lfs/lfs_segment.c | 96 ++++++++++++++++++++++++++---- sys/ufs/lfs/lfs_subr.c | 4 +- sys/ufs/ufs/ufs_vnops.c | 6 +- 7 files changed, 235 insertions(+), 90 deletions(-) diff --git a/sys/ufs/lfs/lfs.h b/sys/ufs/lfs/lfs.h index 178031051a94..ec14be89d091 100644 --- a/sys/ufs/lfs/lfs.h +++ b/sys/ufs/lfs/lfs.h @@ -1,4 +1,4 @@ -/* $NetBSD: lfs.h,v 1.20 2000/01/19 00:03:04 perseant Exp $ */ +/* $NetBSD: lfs.h,v 1.21 2000/05/05 20:59:21 perseant Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -313,6 +313,7 @@ struct lfs { daddr_t lfs_sbactive; /* disk address of in-progress sb write */ #endif struct vnode *lfs_flushvp; /* vnode being flushed */ + struct vnode *lfs_unlockvp; /* being inactivated in lfs_segunlock */ u_int32_t lfs_diropwait; /* # procs waiting on dirop flush */ struct lock lfs_freelock; }; @@ -333,8 +334,9 @@ struct lfs { #define D_INDIR(fs) (S_INDIR(fs) - NINDIR(fs) - 1) #define T_INDIR(fs) (D_INDIR(fs) - NINDIR(fs) * NINDIR(fs) - 1) -/* Unassigned disk address. */ +/* Unassigned disk addresses. */ #define UNASSIGNED -1 +#define UNWRITTEN -2 /* Unused logical block number */ #define LFS_UNUSED_LBN -1 diff --git a/sys/ufs/lfs/lfs_balloc.c b/sys/ufs/lfs/lfs_balloc.c index e2a33397e379..89e681998cd8 100644 --- a/sys/ufs/lfs/lfs_balloc.c +++ b/sys/ufs/lfs/lfs_balloc.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_balloc.c,v 1.15 2000/04/23 21:10:26 perseant Exp $ */ +/* $NetBSD: lfs_balloc.c,v 1.16 2000/05/05 20:59:21 perseant Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -99,6 +99,19 @@ int lfs_fragextend __P((struct vnode *, int, int, ufs_daddr_t, struct buf **)); +/* + * Allocate a block, and to inode and filesystem block accounting for it + * and for any indirect blocks the may need to be created in order for + * this block to be created. + * + * Blocks which have never been accounted for (i.e., which "do not exist") + * have disk address 0, which is translated by ufs_bmap to the special value + * UNASSIGNED == -1, as in the historical UFS. + * + * Blocks which have been accounted for but which have not yet been written + * to disk are given the new special disk address UNWRITTEN == -2, so that + * they can be differentiated from completely new blocks. + */ int lfs_balloc(v) void *v; @@ -118,7 +131,7 @@ lfs_balloc(v) struct buf *ibp, *bp; struct inode *ip; struct lfs *fs; - struct indir indirs[NIADDR+2]; + struct indir indirs[NIADDR+2], *idp; ufs_daddr_t daddr, lastblock; int bb; /* number of disk blocks in a block disk blocks */ int error, frags, i, nsize, osize, num; @@ -171,28 +184,45 @@ lfs_balloc(v) } bb = VFSTOUFS(vp->v_mount)->um_seqinc; - if (daddr == UNASSIGNED) + if (daddr == UNASSIGNED) { + if (num > 0 && ip->i_ffs_ib[indirs[0].in_off] == 0) { + ip->i_ffs_ib[indirs[0].in_off] = UNWRITTEN; + } /* May need to allocate indirect blocks */ - for (i = 1; i < num; ++i) + for (i = 1; i < num; ++i) { + ibp = getblk(vp, indirs[i].in_lbn, fs->lfs_bsize, 0,0); if (!indirs[i].in_exists) { - ibp = getblk(vp, indirs[i].in_lbn, fs->lfs_bsize, - 0, 0); - if ((ibp->b_flags & (B_DONE | B_DELWRI))) +#ifdef DIAGNOSTIC + if ((ibp->b_flags & (B_DONE | B_DELWRI))) panic ("Indirect block should not exist"); +#endif if (!ISSPACE(fs, bb, curproc->p_ucred)){ ibp->b_flags |= B_INVAL; brelse(ibp); + /* XXX might leave some UNWRITTENs hanging, do this better */ return(ENOSPC); } else { ip->i_ffs_blocks += bb; ip->i_lfs->lfs_bfree -= bb; clrbuf(ibp); - if ((error = VOP_BWRITE(ibp))) - return(error); + ((ufs_daddr_t *)ibp->b_data)[indirs[i].in_off] = UNWRITTEN; + ibp->b_blkno = UNWRITTEN; + } + } else { + /* + * This block exists, but the next one may not. + * If that is the case mark it UNWRITTEN to + * keep the accounting straight. + */ + if ( ((ufs_daddr_t *)ibp->b_data)[indirs[i].in_off] == 0) { + ((ufs_daddr_t *)ibp->b_data)[indirs[i].in_off] = UNWRITTEN; } } - + if ((error = VOP_BWRITE(ibp))) + return(error); + } + } /* * If the block we are writing is a direct block, it's the last * block in the file, and offset + iosize is less than a full @@ -239,11 +269,10 @@ lfs_balloc(v) * for free space and update the inode number of blocks. * * We can tell a truly new block because (1) ufs_bmaparray - * will say it is UNASSIGNED; and (2) it will not be marked - * with B_DELWRI. (It might be marked B_DONE, if it was - * read into the cache before it existed on disk.) + * will say it is UNASSIGNED. Once we allocate it we will assign + * it the disk address UNWRITTEN. */ - if ((!(bp->b_flags & B_DELWRI)) && daddr == UNASSIGNED) { + if (daddr == UNASSIGNED) { if (!ISSPACE(fs, bb, curproc->p_ucred)) { bp->b_flags |= B_INVAL; brelse(bp); @@ -253,6 +282,27 @@ lfs_balloc(v) ip->i_lfs->lfs_bfree -= bb; if (iosize != fs->lfs_bsize) clrbuf(bp); + + /* Note the new address */ + bp->b_blkno = UNWRITTEN; + + switch (num) { + case 0: + ip->i_ffs_db[lbn] = UNWRITTEN; + break; + case 1: + ip->i_ffs_ib[indirs[0].in_off] = UNWRITTEN; + break; + default: + idp = &indirs[num - 1]; + if (bread(vp, idp->in_lbn, fs->lfs_bsize, + NOCRED, &ibp)) + panic("lfs_balloc: bread bno %d", + idp->in_lbn); + ((ufs_daddr_t *)ibp->b_data)[idp->in_off] = + UNWRITTEN; + VOP_BWRITE(ibp); + } } } else if (!(bp->b_flags & (B_DONE|B_DELWRI))) { /* diff --git a/sys/ufs/lfs/lfs_bio.c b/sys/ufs/lfs/lfs_bio.c index 5aa143fd8b3f..ebb7ceb9d60b 100644 --- a/sys/ufs/lfs/lfs_bio.c +++ b/sys/ufs/lfs/lfs_bio.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_bio.c,v 1.17 2000/03/30 12:41:13 augustss Exp $ */ +/* $NetBSD: lfs_bio.c,v 1.18 2000/05/05 20:59:21 perseant Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -393,6 +393,19 @@ lfs_check(vp, blkno, flags) #endif error = tsleep(&locked_queue_count, PCATCH | PUSER, "buffers", hz * LFS_BUFWAIT); + /* + * lfs_flush might not flush all the buffers, if some of the + * inodes were locked. Try flushing again to keep us from + * blocking indefinitely. + */ + if (locked_queue_count > LFS_MAX_BUFS + || locked_queue_bytes > LFS_MAX_BYTES) + { + ++fs->lfs_writer; + lfs_flush(fs, flags); + if(--fs->lfs_writer==0) + wakeup(&fs->lfs_dirops); + } } return (error); } diff --git a/sys/ufs/lfs/lfs_inode.c b/sys/ufs/lfs/lfs_inode.c index 68461991d82c..327e06a44920 100644 --- a/sys/ufs/lfs/lfs_inode.c +++ b/sys/ufs/lfs/lfs_inode.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_inode.c,v 1.34 2000/04/24 19:07:16 perseant Exp $ */ +/* $NetBSD: lfs_inode.c,v 1.35 2000/05/05 20:59:21 perseant Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -95,6 +95,8 @@ #include static int lfs_vinvalbuf __P((struct vnode *, struct ucred *, struct proc *, ufs_daddr_t)); +extern int locked_queue_count; +extern long locked_queue_bytes; /* Search a block for a specific dinode. */ struct dinode * @@ -184,7 +186,7 @@ lfs_update(v) } /* Update segment usage information when removing a block. */ -#define UPDATE_SEGUSE \ +#define UPDATE_SEGUSE do { \ if (lastseg != -1) { \ LFS_SEGENTRY(sup, fs, lastseg, sup_bp); \ if (num > sup->su_nbytes) { \ @@ -195,19 +197,22 @@ lfs_update(v) } else \ sup->su_nbytes -= num; \ e1 = VOP_BWRITE(sup_bp); \ - fragsreleased += numfrags(fs, num); \ - } + } \ + fragsreleased += numfrags(fs, num); \ +} while(0) -#define SEGDEC(S) { \ - if (daddr != 0) { \ +#define SEGDEC(S) do { \ + if (daddr > 0) { \ if (lastseg != (seg = datosn(fs, daddr))) { \ UPDATE_SEGUSE; \ num = (S); \ lastseg = seg; \ } else \ num += (S); \ + } else if (daddr == UNWRITTEN) { \ + fragsreleased += numfrags(fs,(S)); \ } \ -} +} while(0) /* * Truncate the inode ip to at most length size. Update segment usage @@ -239,7 +244,7 @@ lfs_truncate(v) SEGUSE *sup; ufs_daddr_t daddr, lastblock, lbn, olastblock; ufs_daddr_t oldsize_lastblock, oldsize_newlast, newsize; - long off, a_released, fragsreleased, i_released; + long off, a_released, fragsreleased; int e1, e2, depth, lastseg, num, offset, seg, freesize, s; if (length < 0) @@ -288,15 +293,18 @@ lfs_truncate(v) uvm_vnp_setsize(vp, length); /* - * Make sure no writes happen while we're truncating. - * Otherwise, blocks which are accounted for on the inode - * *and* which have been created for cleaning can coexist, - * and cause us to overcount, and panic below. + * Make sure no writes to this inode can happen while we're + * truncating. Otherwise, blocks which are accounted for on the + * inode *and* which have been created for cleaning can coexist, + * and cause an overcounting. * - * XXX KS - too restrictive? Maybe only when cleaning? + * (We don't need to *hold* the seglock, though, because we already + * hold the inode lock; draining the seglock is sufficient.) */ - while(fs->lfs_seglock && fs->lfs_lockpid != ap->a_p->p_pid) { - tsleep(&fs->lfs_seglock, (PRIBIO+1), "lfs_truncate", 0); + if (vp != fs->lfs_unlockvp) { + while(fs->lfs_seglock) { + tsleep(&fs->lfs_seglock, PRIBIO+1, "lfs_truncate", 0); + } } /* @@ -339,12 +347,13 @@ lfs_truncate(v) bzero((char *)bp->b_data + offset, (u_int)(newsize - offset)); #ifdef DEBUG if(bp->b_flags & B_CALL) - panic("Can't allocbuf malloced buffer!"); + panic("Can't allocbuf malloced buffer!"); else #endif allocbuf(bp, newsize); - if(oldsize_newlast > newsize) + if(bp->b_blkno != UNASSIGNED && oldsize_newlast > newsize) { ip->i_ffs_blocks -= btodb(oldsize_newlast - newsize); + } if ((e1 = VOP_BWRITE(bp)) != 0) { printf("lfs_truncate: bwrite: %d\n",e1); return (e1); @@ -393,15 +402,15 @@ lfs_truncate(v) panic("lfs_truncate: bread bno %d", inp->in_lbn); daddrp = (ufs_daddr_t *)bp->b_data + inp->in_off; - for (i = inp->in_off; - i++ <= a_end[depth].in_off;) { + for (i = inp->in_off; i++ <= a_end[depth].in_off;) { daddr = *daddrp++; SEGDEC(freesize); } a_end[depth].in_off = NINDIR(fs) - 1; - if (inp->in_off == 0) + if (inp->in_off == 0) { + bp->b_flags |= B_INVAL; brelse (bp); - else { + } else { bzero((ufs_daddr_t *)bp->b_data + inp->in_off, fs->lfs_bsize - inp->in_off * sizeof(ufs_daddr_t)); @@ -436,9 +445,11 @@ lfs_truncate(v) } #ifdef DIAGNOSTIC if (ip->i_ffs_blocks < fragstodb(fs, fragsreleased)) { - panic("lfs_truncate: frag count < 0 (%d<%ld), ino %d\n", + printf("lfs_truncate: frag count < 0 (%d<%ld), ino %d\n", ip->i_ffs_blocks, fragstodb(fs, fragsreleased), ip->i_number); + if (length > 0) + panic("lfs_truncate: frag count < 0"); fragsreleased = dbtofrags(fs, ip->i_ffs_blocks); } #endif @@ -451,59 +462,49 @@ lfs_truncate(v) * field can be updated. */ a_released = 0; - i_released = 0; s = splbio(); for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = bp->b_vnbufs.le_next) { - /* XXX KS - Don't miscount if we're not truncating to zero. */ if(length>0 && !(bp->b_lblkno >= 0 && bp->b_lblkno > lastblock) && !(bp->b_lblkno < 0 && bp->b_lblkno < -lastblock-NIADDR)) continue; - if (bp->b_flags & B_LOCKED) { + if (bp->b_flags & B_LOCKED) a_released += numfrags(fs, bp->b_bcount); - /* - * XXX - * When buffers are created in the cache, their block - * number is set equal to their logical block number. - * If that is still true, we are assuming that the - * blocks are new (not yet on disk) and weren't - * counted above. However, there is a slight chance - * that a block's disk address is equal to its logical - * block number in which case, we'll get an overcounting - * here. - */ - if (bp->b_blkno == bp->b_lblkno) { - i_released += numfrags(fs, bp->b_bcount); - } - } } splx(s); - fragsreleased = i_released; -#ifdef DIAGNOSTIC - if (fragsreleased > dbtofrags(fs, ip->i_ffs_blocks)) { - printf("lfs_inode: %ld frags released > %d in inode %d\n", - fragsreleased, dbtofrags(fs, ip->i_ffs_blocks), - ip->i_number); - fragsreleased = dbtofrags(fs, ip->i_ffs_blocks); - } -#endif - fs->lfs_bfree += fragstodb(fs, fragsreleased); - ip->i_ffs_blocks -= fragstodb(fs, fragsreleased); + #ifdef DIAGNOSTIC if (length == 0 && ip->i_ffs_blocks != 0) { printf("lfs_inode: trunc to zero, but %d blocks left on inode %d\n", ip->i_ffs_blocks, ip->i_number); - panic("lfs_inode\n"); + panic("lfs_inode: trunc to zero\n"); } #endif fs->lfs_avail += fragstodb(fs, a_released); if(length>0) e1 = lfs_vinvalbuf(vp, ap->a_cred, ap->a_p, lastblock-1); - else + else { e1 = vinvalbuf(vp, 0, ap->a_cred, ap->a_p, 0, 0); + lfs_countlocked(&locked_queue_count,&locked_queue_bytes); + } + wakeup(&locked_queue_count); + + if (length > 0) { + /* + * Allocate the new last block to ensure that any previously + * existing indirect blocks invalidated above are valid. + * (Adding the block is not really necessary.) + */ + error = VOP_BALLOC(vp, length - 1, 1, ap->a_cred, 0, &bp); + if (error) + return (error); + VOP_BWRITE(bp); + } + e2 = VOP_UPDATE(vp, NULL, NULL, 0); + if(e1) printf("lfs_truncate: vinvalbuf: %d\n",e1); if(e2) @@ -540,6 +541,8 @@ lfs_vinvalbuf(vp, cred, p, maxblk) nbp = bp->b_vnbufs.le_next; if (bp->b_flags & B_GATHERED) { + printf("lfs_vinvalbuf: gathered block ino %d lbn %d\n", + VTOI(vp)->i_number, bp->b_lblkno); error = tsleep(vp, PRIBIO+1, "lfs_vin2", 0); splx(s); if(error) @@ -550,10 +553,9 @@ lfs_vinvalbuf(vp, cred, p, maxblk) bp->b_flags |= B_WANTED; error = tsleep((caddr_t)bp, (PRIBIO + 1), "lfs_vinval", 0); - if (error) { - splx(s); + splx(s); + if (error) return (error); - } goto top; } @@ -561,10 +563,14 @@ lfs_vinvalbuf(vp, cred, p, maxblk) if((bp->b_lblkno >= 0 && bp->b_lblkno > maxblk) || (bp->b_lblkno < 0 && bp->b_lblkno < -maxblk-(NIADDR-1))) { - bp->b_flags |= B_INVAL | B_VFLUSH; + if(bp->b_flags & B_LOCKED) { + --locked_queue_count; + locked_queue_bytes -= bp->b_bufsize; + } if(bp->b_flags & B_CALL) { lfs_freebuf(bp); } else { + bp->b_flags |= B_INVAL | B_VFLUSH; brelse(bp); } ++dirty; diff --git a/sys/ufs/lfs/lfs_segment.c b/sys/ufs/lfs/lfs_segment.c index cc493b7fcd80..168b84d52f41 100644 --- a/sys/ufs/lfs/lfs_segment.c +++ b/sys/ufs/lfs/lfs_segment.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_segment.c,v 1.42 2000/03/30 12:41:13 augustss Exp $ */ +/* $NetBSD: lfs_segment.c,v 1.43 2000/05/05 20:59:21 perseant Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -343,6 +343,7 @@ lfs_writevnodes(fs, mp, sp, op) struct inode *ip; struct vnode *vp; int inodes_written=0, only_cleaning; + int needs_unlock; #ifndef LFS_NO_BACKVP_HACK /* BEGIN HACK */ @@ -405,6 +406,23 @@ lfs_writevnodes(fs, mp, sp, op) continue; } #endif + + needs_unlock = 0; + if(VOP_ISLOCKED(vp)) { + if (vp != fs->lfs_ivnode && + vp->v_lock.lk_lockholder != curproc->p_pid) { +#ifdef DEBUG_LFS + printf("lfs_writevnodes: not writing ino %d, locked by pid %d\n", + VTOI(vp)->i_number, + vp->v_lock.lk_lockholder); +#endif + continue; + } + } else { + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + needs_unlock = 1; + } + only_cleaning = 0; /* * Write the inode/file if dirty and it's not the @@ -438,6 +456,9 @@ lfs_writevnodes(fs, mp, sp, op) inodes_written++; } + if(needs_unlock) + VOP_UNLOCK(vp,0); + if(lfs_clean_vnhead && only_cleaning) lfs_vunref_head(vp); else @@ -907,6 +928,11 @@ loop: for (bp = vp->v_dirtyblkhd.lh_first; bp && bp->b_vnbufs.le_next != NULL; bwrite(bp); } else { #ifdef DIAGNOSTIC + if ((bp->b_flags & (B_CALL|B_INVAL))==B_INVAL) { + printf("lfs_gather: lbn %d is B_INVAL\n", + bp->b_lblkno); + VOP_PRINT(bp->b_vp); + } if (!(bp->b_flags & B_DELWRI)) panic("lfs_gather: bp not B_DELWRI"); if (!(bp->b_flags & B_LOCKED)) { @@ -940,12 +966,13 @@ lfs_updatemeta(sp) struct segment *sp; { SEGUSE *sup; - struct buf *bp; + struct buf *bp, *ibp; struct lfs *fs; struct vnode *vp; struct indir a[NIADDR + 2], *ap; struct inode *ip; ufs_daddr_t daddr, lbn, off; + daddr_t ooff; int error, i, nblocks, num; vp = sp->vp; @@ -993,10 +1020,26 @@ lfs_updatemeta(sp) ip = VTOI(vp); switch (num) { case 0: - ip->i_ffs_db[lbn] = off; + ooff = ip->i_ffs_db[lbn]; + if(vp != fs->lfs_ivnode && (ooff == 0 || ooff == UNASSIGNED)) { +#ifdef DEBUG_LFS + printf("lfs_updatemeta[1]: warning: writing ino %d lbn %d at 0x%x, was 0x%x\n", ip->i_number, lbn, off, ooff); +#else + ; +#endif + } else + ip->i_ffs_db[lbn] = off; break; case 1: - ip->i_ffs_ib[a[0].in_off] = off; + ooff = ip->i_ffs_ib[a[0].in_off]; + if(vp != fs->lfs_ivnode && (ooff == 0 || ooff == UNASSIGNED)) { +#ifdef DEBUG_LFS + printf("lfs_updatemeta[2]: warning: writing ino %d lbn %d at 0x%x, was 0x%x\n", ip->i_number, lbn, off, ooff); +#else + ; +#endif + } else + ip->i_ffs_ib[a[0].in_off] = off; break; default: ap = &a[num - 1]; @@ -1006,17 +1049,49 @@ lfs_updatemeta(sp) /* * Bread may create a new (indirect) block which needs * to get counted for the inode. + * + * XXX - why would it ever do this (except possibly + * for the Ifile)? lfs_balloc is supposed to take + * care of this. */ - if (/* bp->b_blkno == -1 && */ - !(bp->b_flags & (B_DELWRI|B_DONE))) { + if (bp->b_blkno == UNASSIGNED) { ip->i_ffs_blocks += fsbtodb(fs, 1); fs->lfs_bfree -= fragstodb(fs, fs->lfs_frag); + + /* Note the new address */ + bp->b_blkno = UNWRITTEN; + + if(num == 2) { + ip->i_ffs_ib[a[0].in_off] = UNWRITTEN; + } else { + ap = &a[num - 2]; + if (bread(vp, ap->in_lbn, + fs->lfs_bsize, NOCRED, &ibp)) + panic("lfs_updatemeta: bread bno %d", + ap->in_lbn); + ((ufs_daddr_t *)ibp->b_data)[ap->in_off] = UNWRITTEN; + VOP_BWRITE(ibp); + } + } +#ifdef DEBUG + else if(!(bp->b_flags & (B_DONE|B_DELWRI))) + printf("lfs_updatemeta: unaccounted indirect block ino %d block %d\n", ip->i_number, ap->in_lbn); +#endif + ooff = ((ufs_daddr_t *)bp->b_data)[ap->in_off]; + if(vp != fs->lfs_ivnode && (ooff == 0 || ooff == UNASSIGNED)) { +#ifdef DEBUG_LFS + printf("lfs_updatemeta[3]: warning: writing ino %d lbn %d at 0x%x, was 0x%x\n", ip->i_number, lbn, off, ooff); +#else + ; +#endif + brelse(bp); + } else { + ((ufs_daddr_t *)bp->b_data)[ap->in_off] = off; + VOP_BWRITE(bp); } - ((ufs_daddr_t *)bp->b_data)[ap->in_off] = off; - VOP_BWRITE(bp); } /* Update segment usage information. */ - if (daddr != UNASSIGNED && !(daddr >= fs->lfs_lastpseg && daddr <= off)) { + if (daddr > 0 && !(daddr >= fs->lfs_lastpseg && daddr <= off)) { LFS_SEGENTRY(sup, fs, datosn(fs, daddr), bp); #ifdef DIAGNOSTIC if (sup->su_nbytes < (*sp->start_bpp)->b_bcount) { @@ -1195,9 +1270,6 @@ lfs_writeseg(fs, sp) if ((nblocks = sp->cbpp - sp->bpp) == 1) return (0); -#ifdef DEBUG_LFS - lfs_check_bpp(fs,sp,__FILE__,__LINE__); -#endif i_dev = VTOI(fs->lfs_ivnode)->i_dev; devvp = VTOI(fs->lfs_ivnode)->i_devvp; diff --git a/sys/ufs/lfs/lfs_subr.c b/sys/ufs/lfs/lfs_subr.c index d222cb040f5d..0ba2543adebe 100644 --- a/sys/ufs/lfs/lfs_subr.c +++ b/sys/ufs/lfs/lfs_subr.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_subr.c,v 1.13 2000/03/30 12:41:13 augustss Exp $ */ +/* $NetBSD: lfs_subr.c,v 1.14 2000/05/05 20:59:22 perseant Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -218,7 +218,9 @@ lfs_segunlock(fs) wakeup(&lfs_dirvcount); if(vp->v_usecount == 1) { /* vrele may call VOP_INACTIVE */ + fs->lfs_unlockvp = vp; vrele(vp); + fs->lfs_unlockvp = NULL; } else lfs_vunref(vp); diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index f91a62758a9b..af490c239b81 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -1,4 +1,4 @@ -/* $NetBSD: ufs_vnops.c,v 1.64 2000/03/30 12:41:15 augustss Exp $ */ +/* $NetBSD: ufs_vnops.c,v 1.65 2000/05/05 20:59:20 perseant Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993, 1995 @@ -1639,10 +1639,10 @@ ufs_strategy(v) biodone(bp); return (error); } - if ((long)bp->b_blkno == -1) + if ((long)bp->b_blkno == -1) /* no valid data */ clrbuf(bp); } - if ((long)bp->b_blkno == -1) { + if ((long)bp->b_blkno < 0) { /* block is not on disk */ biodone(bp); return (0); }