Do not needlessly dirty segment table blocks during lfs_segwrite,

preventing needless disk activity when the filesystem is idle.  (PR #10979.)
This commit is contained in:
perseant 2000-11-12 07:58:36 +00:00
parent 63270df506
commit c4c7b2adbb
4 changed files with 68 additions and 30 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: lfs.h,v 1.32 2000/09/13 00:07:56 perseant Exp $ */
/* $NetBSD: lfs.h,v 1.33 2000/11/12 07:58:36 perseant Exp $ */
/*-
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@ -482,6 +482,18 @@ struct segsum {
(CP) = (CLEANERINFO *)(BP)->b_data; \
}
/* Synchronize the Ifile cleaner info with current avail and bfree */
#define LFS_SYNC_CLEANERINFO(cip, fs, bp, w) do { \
if ((w) || (cip)->bfree != (fs)->lfs_bfree || \
(cip)->avail != (fs)->lfs_avail - (fs)->lfs_ravail) { \
printf("update cleaner info at %s:%d\n", __FILE__, __LINE__); \
(cip)->bfree = (fs)->lfs_bfree; \
(cip)->avail = (fs)->lfs_avail - (fs)->lfs_ravail; \
(void) VOP_BWRITE(bp); /* Ifile */ \
} else \
brelse(bp); \
} while(0)
/* Read in the block with a specific inode from the ifile. */
#define LFS_IENTRY(IP, F, IN, BP) { \
int _e; \

View File

@ -1,4 +1,4 @@
/* $NetBSD: lfs_bio.c,v 1.30 2000/09/13 00:07:56 perseant Exp $ */
/* $NetBSD: lfs_bio.c,v 1.31 2000/11/12 07:58:36 perseant Exp $ */
/*-
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@ -154,9 +154,7 @@ lfs_reserve(fs, vp, nb)
/* Wake up the cleaner */
LFS_CLEANERINFO(cip, fs, bp);
cip->bfree = fs->lfs_bfree;
cip->avail = fs->lfs_avail - fs->lfs_ravail;
(void) VOP_BWRITE(bp); /* Ifile */
LFS_SYNC_CLEANERINFO(cip, fs, bp, 0);
wakeup(&lfs_allclean_wakeup);
wakeup(&fs->lfs_nextseg);
@ -279,9 +277,7 @@ lfs_bwrite_ext(bp, flags)
* so it CANT_WAIT.
*/
LFS_CLEANERINFO(cip, fs, cbp);
cip->bfree = fs->lfs_bfree;
cip->avail = fs->lfs_avail;
(void) VOP_BWRITE(cbp);
LFS_SYNC_CLEANERINFO(cip, fs, cbp, 0);
printf("lfs_bwrite: out of available space, "
"waiting on cleaner\n");

View File

@ -1,4 +1,4 @@
/* $NetBSD: lfs_segment.c,v 1.60 2000/11/12 02:13:51 toshii Exp $ */
/* $NetBSD: lfs_segment.c,v 1.61 2000/11/12 07:58:36 perseant Exp $ */
/*-
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@ -466,10 +466,10 @@ lfs_segwrite(mp, flags)
struct segment *sp;
struct vnode *vp;
SEGUSE *segusep;
CLEANERINFO *cip;
ufs_daddr_t ibno;
int do_ckp, error, i;
int do_ckp, did_ckp, error, i;
int writer_set = 0;
int dirty;
fs = VFSTOUFS(mp)->um_lfs;
@ -478,15 +478,21 @@ lfs_segwrite(mp, flags)
lfs_imtime(fs);
/* printf("lfs_segwrite: ifile flags are 0x%lx\n",
(long)(VTOI(fs->lfs_ivnode)->i_flag)); */
#if 0
/*
* If we are not the cleaner, and there is no space available,
* wait until cleaner writes.
*/
if(!(flags & SEGM_CLEAN)
&& (!fs->lfs_seglock || !(fs->lfs_sp->seg_flags & SEGM_CLEAN)))
if(!(flags & SEGM_CLEAN) && !(fs->lfs_seglock && fs->lfs_sp &&
(fs->lfs_sp->seg_flags & SEGM_CLEAN)))
{
while (fs->lfs_avail <= 0) {
LFS_CLEANERINFO(cip, fs, bp);
LFS_SYNC_CLEANERINFO(cip, fs, bp, 0);
wakeup(&lfs_allclean_wakeup);
wakeup(&fs->lfs_nextseg);
error = tsleep(&fs->lfs_avail, PRIBIO + 1, "lfs_av2",
@ -497,14 +503,6 @@ lfs_segwrite(mp, flags)
}
}
#endif
/*
* Synchronize cleaner information
*/
LFS_CLEANERINFO(cip, fs, bp);
cip->bfree = fs->lfs_bfree;
cip->avail = fs->lfs_avail - fs->lfs_ravail;
(void) VOP_BWRITE(bp); /* Ifile */
/*
* Allocate a segment structure and enough space to hold pointers to
* the maximum possible number of buffers which can be described in a
@ -550,23 +548,34 @@ lfs_segwrite(mp, flags)
if (do_ckp) {
for (ibno = fs->lfs_cleansz + fs->lfs_segtabsz;
--ibno >= fs->lfs_cleansz; ) {
dirty = 0;
if (bread(fs->lfs_ivnode, ibno, fs->lfs_bsize, NOCRED, &bp))
panic("lfs_segwrite: ifile read");
segusep = (SEGUSE *)bp->b_data;
for (i = fs->lfs_sepb; i--; segusep++)
segusep->su_flags &= ~SEGUSE_ACTIVE;
for (i = fs->lfs_sepb; i--; segusep++) {
if (segusep->su_flags & SEGUSE_ACTIVE) {
segusep->su_flags &= ~SEGUSE_ACTIVE;
++dirty;
}
}
/* But the current segment is still ACTIVE */
segusep = (SEGUSE *)bp->b_data;
if (datosn(fs, fs->lfs_curseg) / fs->lfs_sepb ==
(ibno-fs->lfs_cleansz))
(ibno-fs->lfs_cleansz)) {
segusep[datosn(fs, fs->lfs_curseg) %
fs->lfs_sepb].su_flags |= SEGUSE_ACTIVE;
error = VOP_BWRITE(bp); /* Ifile */
--dirty;
}
if (dirty)
error = VOP_BWRITE(bp); /* Ifile */
else
brelse(bp);
}
}
did_ckp = 0;
if (do_ckp || fs->lfs_doifile) {
redo:
vp = fs->lfs_ivnode;
@ -576,12 +585,16 @@ lfs_segwrite(mp, flags)
ip = VTOI(vp);
if (vp->v_dirtyblkhd.lh_first != NULL)
lfs_writefile(fs, sp, vp);
(void)lfs_writeinode(fs, sp, ip);
if (ip->i_flag & IN_ALLMOD)
++did_ckp;
(void) lfs_writeinode(fs, sp, ip);
vput(vp);
if (lfs_writeseg(fs, sp) && do_ckp)
goto redo;
/* The ifile should now be all clear */
LFS_CLR_UINO(ip, IN_ALLMOD);
} else {
(void) lfs_writeseg(fs, sp);
}
@ -595,6 +608,19 @@ lfs_segwrite(mp, flags)
if(writer_set && --fs->lfs_writer==0)
wakeup(&fs->lfs_dirops);
/*
* If we didn't write the Ifile, we didn't really do anything.
* That means that (1) there is a checkpoint on disk and (2)
* nothing has changed since it was written.
*
* Take the flags off of the segment so that lfs_segunlock
* doesn't have to write the superblock either.
*/
if (did_ckp == 0) {
sp->seg_flags &= ~(SEGM_SYNC|SEGM_CKP);
/* if(do_ckp) printf("lfs_segwrite: no checkpoint\n"); */
}
if(lfs_dostats) {
++lfs_stats.nwrites;
if (sp->seg_flags & SEGM_SYNC)
@ -1225,7 +1251,7 @@ lfs_newseg(fs)
--cip->clean;
++cip->dirty;
fs->lfs_nclean = cip->clean;
(void) VOP_BWRITE(bp); /* Ifile */
LFS_SYNC_CLEANERINFO(cip, fs, bp, 1);
fs->lfs_lastseg = fs->lfs_curseg;
fs->lfs_curseg = fs->lfs_nextseg;

View File

@ -1,4 +1,4 @@
/* $NetBSD: lfs_vnops.c,v 1.46 2000/10/14 23:22:14 perseant Exp $ */
/* $NetBSD: lfs_vnops.c,v 1.47 2000/11/12 07:58:36 perseant Exp $ */
/*-
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@ -287,6 +287,10 @@ lfs_fsync(v)
struct proc *a_p;
} */ *ap = v;
/* Ignore the trickle syncer */
if (ap->a_flags & FSYNC_LAZY)
return 0;
return (VOP_UPDATE(ap->a_vp, NULL, NULL,
(ap->a_flags & FSYNC_WAIT) != 0 ? UPDATE_WAIT : 0));
}