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.
This commit is contained in:
perseant 2000-07-03 01:45:46 +00:00
parent 9f0522fe59
commit ef2da50400
7 changed files with 208 additions and 98 deletions

View File

@ -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))

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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));

View File

@ -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;i<LFS_THROTTLE;i++)
fs->lfs_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;

View File

@ -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.
*/