From ef2da50400a3f0a16e740178c10bfe6b04fe1ae8 Mon Sep 17 00:00:00 2001 From: perseant Date: Mon, 3 Jul 2000 01:45:46 +0000 Subject: [PATCH] Allow the number of free segments reserved for the cleaner to be parametrized in the filesystem, defaulting to MIN_FREE_SEGS = 2 but set to something more reasonable at newfs_lfs time. Note the number of blocks that have been scheduled for writing but which are not yet on disk in an inode extension, i_lfs_effnblks. Move i_ffs_effnlink out of the ffs extension and onto the main inode, since it's used all over the shared code and the lfs extension would clobber it. At inode write time, indirect blocks and inode-held blocks of inodes that have i_lfs_effnblks != i_ffs_blocks are cleansed of UNWRITTEN disk addresses, so that these never make it to disk. --- sys/ufs/lfs/lfs.h | 12 ++- sys/ufs/lfs/lfs_balloc.c | 6 +- sys/ufs/lfs/lfs_bio.c | 11 +- sys/ufs/lfs/lfs_inode.c | 49 ++++++--- sys/ufs/lfs/lfs_segment.c | 205 +++++++++++++++++++++++++++----------- sys/ufs/lfs/lfs_vfsops.c | 9 +- sys/ufs/ufs/inode.h | 14 +-- 7 files changed, 208 insertions(+), 98 deletions(-) diff --git a/sys/ufs/lfs/lfs.h b/sys/ufs/lfs/lfs.h index f7a2b877dfbd..8e596898c5a6 100644 --- a/sys/ufs/lfs/lfs.h +++ b/sys/ufs/lfs/lfs.h @@ -1,4 +1,4 @@ -/* $NetBSD: lfs.h,v 1.26 2000/06/27 20:57:11 perseant Exp $ */ +/* $NetBSD: lfs.h,v 1.27 2000/07/03 01:45:46 perseant Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -85,7 +85,7 @@ * Parameters and generic definitions */ #define BW_CLEAN 1 -#define MIN_FREE_SEGS 4 +#define MIN_FREE_SEGS 2 #define LFS_MAX_ACTIVE 10 #define LFS_MAXDIROP (desiredvnodes>>2) @@ -221,7 +221,8 @@ struct dlfs { /* XXX this is 2 bytes only to pad to a quad boundary */ u_int16_t dlfs_clean; /* 322: file system is clean flag */ u_int32_t dlfs_dmeta; /* 324: total number of dirty summaries */ - int8_t dlfs_pad[180]; /* 328: round to 512 bytes */ + u_int32_t dlfs_minfreeseg; /* 328: segs reserved for cleaner */ + int8_t dlfs_pad[176]; /* 332: round to 512 bytes */ /* Checksum -- last valid disk field. */ u_int32_t dlfs_cksum; /* 508: checksum for superblock checking */ }; @@ -281,6 +282,7 @@ struct lfs { #define lfs_fsmnt lfs_dlfs.dlfs_fsmnt #define lfs_nclean lfs_dlfs.dlfs_nclean #define lfs_dmeta lfs_dlfs.dlfs_dmeta +#define lfs_minfreeseg lfs_dlfs.dlfs_minfreeseg /* These fields are set at mount time and are meaningless on disk. */ struct segment *lfs_sp; /* current segment being written */ @@ -498,7 +500,7 @@ struct segment { }; /* - * Mecros for determining free space on the disk, with the variable metadata + * Macros for determining free space on the disk, with the variable metadata * of segment summaries and inode blocks taken into account. */ /* Estimate number of clean blocks not available for writing */ @@ -507,7 +509,7 @@ struct segment { ((F)->lfs_nseg - (F)->lfs_nclean))) /* Estimate total size of the disk not including metadata */ -#define LFS_EST_NONMETA(F) ((F)->lfs_dsize - fsbtodb((F), MIN_FREE_SEGS * \ +#define LFS_EST_NONMETA(F) ((F)->lfs_dsize - fsbtodb((F), (F)->lfs_minfreeseg *\ (F)->lfs_ssize) - \ (F)->lfs_dmeta - LFS_EST_CMETA(F)) diff --git a/sys/ufs/lfs/lfs_balloc.c b/sys/ufs/lfs/lfs_balloc.c index 860a43c2fabb..a1346c1e89a5 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.20 2000/06/28 14:16:41 mrg Exp $ */ +/* $NetBSD: lfs_balloc.c,v 1.21 2000/07/03 01:45:48 perseant Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -195,7 +195,7 @@ lfs_balloc(v) frags = numfrags(fs, nsize); bb = fragstodb(fs, frags); *ap->a_bpp = bp = getblk(vp, lbn, nsize, 0, 0); - ip->i_ffs_blocks += bb; + ip->i_lfs_effnblks += bb; ip->i_lfs->lfs_bfree -= bb; ip->i_ffs_db[lbn] = bp->b_blkno = UNWRITTEN; } else { @@ -233,7 +233,7 @@ lfs_balloc(v) } if (ISSPACE(fs, bcount, ap->a_cred)) { ip->i_lfs->lfs_bfree -= bcount; - ip->i_ffs_blocks += bcount; + ip->i_lfs_effnblks += bcount; } else { return ENOSPC; } diff --git a/sys/ufs/lfs/lfs_bio.c b/sys/ufs/lfs/lfs_bio.c index b878e9c7f88b..d43ea695d202 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.24 2000/06/27 20:57:13 perseant Exp $ */ +/* $NetBSD: lfs_bio.c,v 1.25 2000/07/03 01:45:49 perseant Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -159,9 +159,8 @@ lfs_bwrite(v) inline static int lfs_fits(struct lfs *fs, int db) { - if(((db + (fs->lfs_uinodes + INOPB((fs))) / - INOPB(fs) + fsbtodb(fs, 1) + LFS_SUMMARY_SIZE / DEV_BSIZE + - fs->lfs_segtabsz)) >= fs->lfs_avail) + if(((db + fsbtodb(fs, roundup(fs->lfs_uinodes,INOPB(fs)) + 1) + + btodb(LFS_SUMMARY_SIZE) + fs->lfs_segtabsz)) >= fs->lfs_avail) { return 0; } @@ -174,7 +173,7 @@ lfs_fits(struct lfs *fs, int db) * * XXX the old lfs_markv did not have this problem. */ - if (fs->lfs_nclean <= MIN_FREE_SEGS) + if (fs->lfs_nclean <= fs->lfs_minfreeseg) return 0; return 1; @@ -228,7 +227,7 @@ lfs_bwrite_ext(bp, flags) { printf("A"); } - if (fs->lfs_nclean <= MIN_FREE_SEGS-1) + if (fs->lfs_nclean < fs->lfs_minfreeseg) printf("M"); } #endif diff --git a/sys/ufs/lfs/lfs_inode.c b/sys/ufs/lfs/lfs_inode.c index 80f39cf6cab3..a11db5d0e9e5 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.39 2000/06/28 14:16:42 mrg Exp $ */ +/* $NetBSD: lfs_inode.c,v 1.40 2000/07/03 01:45:51 perseant Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -99,7 +99,7 @@ extern long locked_queue_bytes; static int lfs_update_seguse(struct lfs *, long, size_t); static int lfs_indirtrunc (struct inode *, ufs_daddr_t, ufs_daddr_t, - ufs_daddr_t, int, long *, long *, size_t *); + ufs_daddr_t, int, long *, long *, long *, size_t *); static int lfs_blkfree (struct lfs *, daddr_t, size_t, long *, size_t *); static int lfs_vtruncbuf(struct vnode *, daddr_t, int, int); @@ -118,8 +118,10 @@ lfs_ifind(fs, ino, bp) if (ldip->di_inumber == ino) return (ldip); - printf("offset is %d (seg %d)\n", fs->lfs_offset, datosn(fs,fs->lfs_offset)); - printf("block is %d (seg %d)\n", bp->b_blkno, datosn(fs,bp->b_blkno)); + printf("offset is 0x%x (seg %d)\n", fs->lfs_offset, + datosn(fs,fs->lfs_offset)); + printf("block is 0x%x (seg %d)\n", bp->b_blkno, + datosn(fs,bp->b_blkno)); panic("lfs_ifind: dinode %u not found", ino); /* NOTREACHED */ } @@ -223,7 +225,7 @@ lfs_truncate(v) struct lfs *fs; struct buf *bp; int offset, size, level; - long count, nblocks, blocksreleased = 0; + long count, rcount, nblocks, blocksreleased = 0, real_released = 0; int i; int aflags, error, allerror = 0; off_t osize; @@ -374,14 +376,19 @@ lfs_truncate(v) bn = oip->i_ffs_ib[level]; if (bn != 0) { error = lfs_indirtrunc(oip, indir_lbn[level], - bn, lastiblock[level], level, &count, &lastseg, &bc); + bn, lastiblock[level], + level, &count, &rcount, + &lastseg, &bc); if (error) allerror = error; + real_released += rcount; blocksreleased += count; if (lastiblock[level] < 0) { + if (oip->i_ffs_ib[level] > 0) + real_released += nblocks; + blocksreleased += nblocks; oip->i_ffs_ib[level] = 0; lfs_blkfree(fs, bn, fs->lfs_bsize, &lastseg, &bc); - blocksreleased += nblocks; } } if (lastiblock[level] >= 0) @@ -397,10 +404,12 @@ lfs_truncate(v) bn = oip->i_ffs_db[i]; if (bn == 0) continue; - oip->i_ffs_db[i] = 0; bsize = blksize(fs, oip, i); - lfs_blkfree(fs, bn, bsize, &lastseg, &bc); + if (oip->i_ffs_db[i] > 0) + real_released += btodb(bsize); blocksreleased += btodb(bsize); + oip->i_ffs_db[i] = 0; + lfs_blkfree(fs, bn, bsize, &lastseg, &bc); } if (lastblock < 0) goto done; @@ -424,6 +433,7 @@ lfs_truncate(v) panic("itrunc: newspace"); if (oldspace - newspace > 0) { lfs_blkfree(fs, bn, oldspace - newspace, &lastseg, &bc); + real_released += btodb(oldspace - newspace); blocksreleased += btodb(oldspace - newspace); } } @@ -446,7 +456,8 @@ done: * Put back the real size. */ oip->i_ffs_size = length; - oip->i_ffs_blocks -= blocksreleased; + oip->i_lfs_effnblks -= blocksreleased; + oip->i_ffs_blocks -= real_released; fs->lfs_bfree += blocksreleased; #ifdef DIAGNOSTIC if (oip->i_ffs_size == 0 && oip->i_ffs_blocks > 0) { @@ -522,7 +533,7 @@ lfs_update_seguse(struct lfs *fs, long lastseg, size_t num) static int lfs_indirtrunc(struct inode *ip, ufs_daddr_t lbn, daddr_t dbn, ufs_daddr_t lastbn, int level, long *countp, - long *lastsegp, size_t *bcp) + long *rcountp, long *lastsegp, size_t *bcp) { int i; struct buf *bp; @@ -530,8 +541,8 @@ lfs_indirtrunc(struct inode *ip, ufs_daddr_t lbn, daddr_t dbn, ufs_daddr_t *bap; struct vnode *vp; ufs_daddr_t *copy = NULL, nb, nlbn, last; - long blkcount, factor; - int nblocks, blocksreleased = 0; + long blkcount, rblkcount, factor; + int nblocks, blocksreleased = 0, real_released = 0; int error = 0, allerror = 0; /* @@ -571,7 +582,7 @@ lfs_indirtrunc(struct inode *ip, ufs_daddr_t lbn, daddr_t dbn, } if (error) { brelse(bp); - *countp = 0; + *countp = *rcountp = 0; return (error); } @@ -598,12 +609,16 @@ lfs_indirtrunc(struct inode *ip, ufs_daddr_t lbn, daddr_t dbn, if (level > SINGLE) { error = lfs_indirtrunc(ip, nlbn, nb, (ufs_daddr_t)-1, level - 1, - &blkcount, lastsegp, bcp); + &blkcount, &rblkcount, + lastsegp, bcp); if (error) allerror = error; blocksreleased += blkcount; + real_released += rblkcount; } lfs_blkfree(fs, nb, fs->lfs_bsize, lastsegp, bcp); + if (bap[i] > 0) + real_released += nblocks; blocksreleased += nblocks; } @@ -616,9 +631,10 @@ lfs_indirtrunc(struct inode *ip, ufs_daddr_t lbn, daddr_t dbn, if (nb != 0) { error = lfs_indirtrunc(ip, nlbn, nb, last, level - 1, &blkcount, - lastsegp, bcp); + &rblkcount, lastsegp, bcp); if (error) allerror = error; + real_released += rblkcount; blocksreleased += blkcount; } } @@ -631,6 +647,7 @@ lfs_indirtrunc(struct inode *ip, ufs_daddr_t lbn, daddr_t dbn, } *countp = blocksreleased; + *rcountp = real_released; return (allerror); } diff --git a/sys/ufs/lfs/lfs_segment.c b/sys/ufs/lfs/lfs_segment.c index f599e9fe81fc..4397762bad24 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.52 2000/06/27 20:57:15 perseant Exp $ */ +/* $NetBSD: lfs_segment.c,v 1.53 2000/07/03 01:45:52 perseant Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -485,18 +485,21 @@ lfs_segwrite(mp, flags) fs = VFSTOUFS(mp)->um_lfs; + if (fs->lfs_ronly) + return EROFS; + lfs_imtime(fs); /* - * If we are not the cleaner, and we have fewer than MIN_FREE_SEGS + * If we are not the cleaner, and we have fewer than lfs_minfreeseg * clean segments, wait until cleaner writes. */ if(!(flags & SEGM_CLEAN) && (!fs->lfs_seglock || !(fs->lfs_sp->seg_flags & SEGM_CLEAN))) { do { - if (fs->lfs_nclean <= MIN_FREE_SEGS - || fs->lfs_avail <= 0) + if (fs->lfs_nclean <= fs->lfs_minfreeseg || + fs->lfs_avail <= 0) { wakeup(&lfs_allclean_wakeup); wakeup(&fs->lfs_nextseg); @@ -506,7 +509,8 @@ lfs_segwrite(mp, flags) return (error); } } - } while (fs->lfs_nclean <= MIN_FREE_SEGS || fs->lfs_avail <= 0); + } while (fs->lfs_nclean <= fs->lfs_minfreeseg || + fs->lfs_avail <= 0); } /* @@ -706,9 +710,11 @@ lfs_writeinode(fs, sp, ip) struct inode *ip; { struct buf *bp, *ibp; + struct dinode *cdp; IFILE *ifp; SEGUSE *sup; ufs_daddr_t daddr; + daddr_t *daddrp; ino_t ino; int error, i, ndx; int redo_ifile = 0; @@ -773,11 +779,30 @@ lfs_writeinode(fs, sp, ip) } bp = sp->ibp; - ((struct dinode *)bp->b_data)[sp->ninodes % INOPB(fs)] = - ip->i_din.ffs_din; + cdp = ((struct dinode *)bp->b_data) + (sp->ninodes % INOPB(fs)); + *cdp = ip->i_din.ffs_din; + + /* + * If we are cleaning, ensure that we don't write UNWRITTEN disk + * addresses to disk. + */ + if (ip->i_lfs_effnblks != ip->i_ffs_blocks) { + printf("lfs_writeinode: cleansing ino %d (%d != %d)\n", + ip->i_number, ip->i_lfs_effnblks, ip->i_ffs_blocks); + for (daddrp = cdp->di_db; daddrp < cdp->di_ib + NIADDR; + daddrp++) { + if (*daddrp == UNWRITTEN) { +#ifdef DEBUG + printf("lfs_writeinode: wiping UNWRITTEN\n"); +#endif + *daddrp = 0; + } + } + } if(ip->i_number == LFS_IFILE_INUM) /* We know sp->idp == NULL */ - sp->idp = ((struct dinode *)bp->b_data)+(sp->ninodes % INOPB(fs)); + sp->idp = ((struct dinode *)bp->b_data) + + (sp->ninodes % INOPB(fs)); if(gotblk) { bp->b_flags |= B_LOCKED; brelse(bp); @@ -813,19 +838,21 @@ lfs_writeinode(fs, sp, ip) } /* - * No need to update segment usage if there was no former inode address - * or if the last inode address is in the current partial segment. + * No need to update segment usage if there was no former inode + * address or if the last inode address is in the current + * partial segment. */ if (daddr >= fs->lfs_lastpseg && daddr <= bp->b_blkno) printf("lfs_writeinode: last inode addr in current pseg " - "(ino %d daddr 0x%x)\n" /* XXX ANSI */, ino, daddr); + "(ino %d daddr 0x%x)\n", ino, daddr); if (daddr != LFS_UNUSED_DADDR) { LFS_SEGENTRY(sup, fs, datosn(fs, daddr), bp); #ifdef DIAGNOSTIC if (sup->su_nbytes < DINODE_SIZE) { - /* XXX -- Change to a panic. */ - printf("lfs_writeinode: negative bytes (segment %d short by %d)\n", - datosn(fs, daddr), (int)DINODE_SIZE - sup->su_nbytes); + printf("lfs_writeinode: negative bytes " + "(segment %d short by %d)\n", + datosn(fs, daddr), + (int)DINODE_SIZE - sup->su_nbytes); panic("lfs_writeinode: negative bytes"); sup->su_nbytes = DINODE_SIZE; } @@ -981,6 +1008,7 @@ lfs_updatemeta(sp) ufs_daddr_t daddr, lbn, off; daddr_t ooff; int error, i, nblocks, num; + int bb; vp = sp->vp; nblocks = &sp->fip->fi_blocks[sp->fip->fi_nblocks] - sp->start_lbp; @@ -1019,8 +1047,8 @@ lfs_updatemeta(sp) if((*sp->start_bpp)->b_blkno == (*sp->start_bpp)->b_lblkno) { printf("lfs_updatemeta: ino %d blk %d has same lbn and daddr\n", VTOI(vp)->i_number, off); } - fs->lfs_offset += - fragstodb(fs, numfrags(fs, (*sp->start_bpp)->b_bcount)); + bb = fragstodb(fs, numfrags(fs, (*sp->start_bpp)->b_bcount)); + fs->lfs_offset += bb; error = ufs_bmaparray(vp, lbn, &daddr, a, &num, NULL); if (error) panic("lfs_updatemeta: ufs_bmaparray %d", error); @@ -1028,21 +1056,31 @@ lfs_updatemeta(sp) switch (num) { case 0: ooff = ip->i_ffs_db[lbn]; - if(vp != fs->lfs_ivnode && (ooff == 0 || ooff == UNASSIGNED)) { + if(vp != fs->lfs_ivnode && ooff == 0) { #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); + printf("lfs_updatemeta[1]: warning: writing " + "ino %d lbn %d at 0x%x, was 0x%x\n", + ip->i_number, lbn, off, ooff); #endif - } else + } else { + if (ooff == UNWRITTEN) + ip->i_ffs_blocks += bb; ip->i_ffs_db[lbn] = off; + } break; case 1: ooff = ip->i_ffs_ib[a[0].in_off]; - if(vp != fs->lfs_ivnode && (ooff == 0 || ooff == UNASSIGNED)) { + if(vp != fs->lfs_ivnode && ooff == 0) { #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); + printf("lfs_updatemeta[2]: warning: writing " + "ino %d lbn %d at 0x%x, was 0x%x\n", + ip->i_number, lbn, off, ooff); #endif - } else + } else { + if (ooff == UNWRITTEN) + ip->i_ffs_blocks += bb; ip->i_ffs_ib[a[0].in_off] = off; + } break; default: ap = &a[num - 1]; @@ -1058,8 +1096,10 @@ lfs_updatemeta(sp) * care of this. */ if (bp->b_blkno == UNASSIGNED) { - ip->i_ffs_blocks += fsbtodb(fs, 1); - fs->lfs_bfree -= fragstodb(fs, fs->lfs_frag); + printf("lfs_updatemeta: creating lbn %d for " + "ino %d", ap->in_lbn, ip->i_number); + ip->i_lfs_effnblks += fsbtodb(fs, 1); + fs->lfs_bfree -= fsbtodb(fs, 1); /* Note the new address */ bp->b_blkno = UNWRITTEN; @@ -1076,17 +1116,17 @@ lfs_updatemeta(sp) 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)) { + if(vp != fs->lfs_ivnode && ooff == 0) { #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); + printf("lfs_updatemeta[3]: warning: writing " + "ino %d lbn %d at 0x%x, was 0x%x\n", + ip->i_number, lbn, off, ooff); #endif brelse(bp); } else { + if (ooff == UNWRITTEN) + ip->i_ffs_blocks += bb; ((ufs_daddr_t *)bp->b_data)[ap->in_off] = off; VOP_BWRITE(bp); } @@ -1243,7 +1283,7 @@ lfs_writeseg(fs, sp) { extern int locked_queue_count; extern long locked_queue_bytes; - struct buf **bpp, *bp, *cbp; + struct buf **bpp, *bp, *cbp, *newbp; SEGUSE *sup; SEGSUM *ssp; dev_t i_dev; @@ -1259,6 +1299,7 @@ lfs_writeseg(fs, sp) char *p; struct vnode *vn; struct inode *ip; + daddr_t *daddrp; #if defined(DEBUG) && defined(LFS_PROPELLER) static int propeller; char propstring[4] = "-\\|/"; @@ -1300,6 +1341,75 @@ lfs_writeseg(fs, sp) do_again = !(bp->b_flags & B_GATHERED); (void)VOP_BWRITE(bp); + /* + * Mark blocks B_BUSY, to prevent then from being changed between + * the checksum computation and the actual write. + * + * If we are cleaning, check indirect blocks for UNWRITTEN, and if + * there are any, replace them with copies that have UNASSIGNED + * instead. + */ + for (bpp = sp->bpp, i = nblocks - 1; i--;) { + ++bpp; + if((*bpp)->b_flags & B_CALL) + continue; + bp = *bpp; + again: + s = splbio(); + if(bp->b_flags & B_BUSY) { +#ifdef DEBUG + printf("lfs_writeseg: avoiding potential data " + "summary corruption for ino %d, lbn %d\n", + VTOI(bp->b_vp)->i_number, bp->b_lblkno); +#endif + bp->b_flags |= B_WANTED; + tsleep(bp, (PRIBIO + 1), "lfs_writeseg", 0); + splx(s); + goto again; + } + bp->b_flags |= B_BUSY; + splx(s); + /* Check and replace indirect block UNWRITTEN bogosity */ + if(bp->b_lblkno < 0 && bp->b_vp != devvp && bp->b_vp && + VTOI(bp->b_vp)->i_ffs_blocks != + VTOI(bp->b_vp)->i_lfs_effnblks) { + printf("lfs_writeseg: cleansing ino %d (%d != %d)\n", + VTOI(bp->b_vp)->i_number, + VTOI(bp->b_vp)->i_lfs_effnblks, + VTOI(bp->b_vp)->i_ffs_blocks); + /* Make a copy we'll make changes to */ + newbp = lfs_newbuf(bp->b_vp, bp->b_lblkno, + bp->b_bcount); + newbp->b_blkno = bp->b_blkno; + memcpy(newbp->b_data, bp->b_data, + newbp->b_bcount); + *bpp = newbp; + + /* Get rid of the old buffer */ + bp->b_flags &= ~(B_ERROR | B_READ | B_DELWRI | + B_LOCKED | B_GATHERED); + if (bp->b_flags & B_CALL) + lfs_freebuf(bp); + else { + bremfree(bp); + bp->b_flags |= B_DONE; + if(bp->b_vp) + reassignbuf(bp, bp->b_vp); + brelse(bp); + } + + for (daddrp = (daddr_t *)(newbp->b_data); + daddrp < (daddr_t *)(newbp->b_data + + newbp->b_bcount); daddrp++) { + if (*daddrp == UNWRITTEN) { +#ifdef DEBUG + printf("lfs_segwrite: replacing UNWRITTEN\n"); +#endif + *daddrp = 0; + } + } + } + } /* * Compute checksum across data and then across summary; the first * block (the summary block) is skipped. Set the create time here @@ -1312,35 +1422,12 @@ lfs_writeseg(fs, sp) for (bpp = sp->bpp, i = nblocks - 1; i--;) { if (((*++bpp)->b_flags & (B_CALL|B_INVAL)) == (B_CALL|B_INVAL)) { if (copyin((*bpp)->b_saveaddr, dp++, sizeof(u_long))) - panic("lfs_writeseg: copyin failed [1]: ino %d blk %d", VTOI((*bpp)->b_vp)->i_number, (*bpp)->b_lblkno); - } else { - if( !((*bpp)->b_flags & B_CALL) ) { - /* - * Before we record data for a checksm, - * make sure the data won't change in between - * the checksum calculation and the write, - * by marking the buffer B_BUSY. It will - * be freed later by brelse(). - */ - again: - s = splbio(); - if((*bpp)->b_flags & B_BUSY) { -#ifdef DEBUG - printf("lfs_writeseg: avoiding potential data summary corruption for ino %d, lbn %d\n", - VTOI((*bpp)->b_vp)->i_number, - bp->b_lblkno); -#endif - (*bpp)->b_flags |= B_WANTED; - tsleep((*bpp), (PRIBIO + 1), - "lfs_writeseg", 0); - splx(s); - goto again; - } - (*bpp)->b_flags |= B_BUSY; - splx(s); - } + panic("lfs_writeseg: copyin failed [1]: " + "ino %d blk %d", + VTOI((*bpp)->b_vp)->i_number, + (*bpp)->b_lblkno); + } else *dp++ = ((u_long *)(*bpp)->b_data)[0]; - } } ssp->ss_create = time.tv_sec; ssp->ss_datasum = cksum(datap, (nblocks - 1) * sizeof(u_long)); diff --git a/sys/ufs/lfs/lfs_vfsops.c b/sys/ufs/lfs/lfs_vfsops.c index 88efec4e0644..886a6e1aed5a 100644 --- a/sys/ufs/lfs/lfs_vfsops.c +++ b/sys/ufs/lfs/lfs_vfsops.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_vfsops.c,v 1.55 2000/06/30 20:45:40 fvdl Exp $ */ +/* $NetBSD: lfs_vfsops.c,v 1.56 2000/07/03 01:45:54 perseant Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -146,7 +146,7 @@ void lfs_init() { ufs_init(); - + /* * XXX Same structure as FFS inodes? Should we share a common pool? */ @@ -429,6 +429,8 @@ lfs_mountfs(devvp, mp, p) for (i=0;ilfs_pending[i] = LFS_UNUSED_DADDR; #endif + if (fs->lfs_minfreeseg == 0) + fs->lfs_minfreeseg = MIN_FREE_SEGS; /* Set up the ifile and lock aflags */ fs->lfs_doifile = 0; @@ -617,6 +619,8 @@ lfs_sync(mp, waitfor, cred, p) struct lfs *fs; fs = ((struct ufsmount *)mp->mnt_data)->ufsmount_u.lfs; + if (fs->lfs_ronly) + return 0; while(fs->lfs_dirops) error = tsleep(&fs->lfs_dirops, PRIBIO + 1, "lfs_dirops", 0); fs->lfs_writer++; @@ -729,6 +733,7 @@ lfs_vget(mp, ino, vpp) } ip->i_din.ffs_din = *lfs_ifind(fs, ino, bp); ip->i_ffs_effnlink = ip->i_ffs_nlink; + ip->i_lfs_effnblks = ip->i_ffs_blocks; #ifdef LFS_ATIME_IFILE ip->i_ffs_atime = ts.tv_sec; ip->i_ffs_atimensec = ts.tv_nsec; diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h index a18183642fbc..50f48830c82a 100644 --- a/sys/ufs/ufs/inode.h +++ b/sys/ufs/ufs/inode.h @@ -1,4 +1,4 @@ -/* $NetBSD: inode.h,v 1.19 2000/05/29 18:41:07 mycroft Exp $ */ +/* $NetBSD: inode.h,v 1.20 2000/07/03 01:45:58 perseant Exp $ */ /* * Copyright (c) 1982, 1989, 1993 @@ -52,8 +52,8 @@ struct ext2fs_inode_ext { ufs_daddr_t ext2fs_last_blk; /* last block allocated on disk */ }; -struct ffs_inode_ext { - int ffs_effnlink; /* i_nlink when I/O completes */ +struct lfs_inode_ext { + u_int32_t lfs_effnblocks; /* number of blocks when i/o completes */ }; /* @@ -61,7 +61,7 @@ struct ffs_inode_ext { * UFS filesystem. It is composed of two types of information. The first part * is the information that is needed only while the file is active (such as * the identity of the file and linkage to speed its lookup). The second part - * is * the permanent meta-data associated with the file which is read in + * is the permanent meta-data associated with the file which is read in * from the permanent dinode from long term storage when the file becomes * active, and is put back when the file is no longer being used. */ @@ -94,18 +94,18 @@ struct inode { doff_t i_offset; /* Offset of free space in directory. */ ino_t i_ino; /* Inode number of found directory. */ u_int32_t i_reclen; /* Size of found directory entry. */ + int i_ffs_effnlink; /* i_nlink when I/O completes */ /* * Inode extensions */ union { /* Other extensions could go here... */ struct ext2fs_inode_ext e2fs; - struct ffs_inode_ext ffs; + struct lfs_inode_ext lfs; } inode_ext; #define i_e2fs_last_lblk inode_ext.e2fs.ext2fs_last_lblk #define i_e2fs_last_blk inode_ext.e2fs.ext2fs_last_blk -#define i_ffs_effnlink inode_ext.ffs.ffs_effnlink - +#define i_lfs_effnblks inode_ext.lfs.lfs_effnblocks /* * The on-disk dinode itself. */