From 9a38f49c572af130bda08efb8d135200e7660fd6 Mon Sep 17 00:00:00 2001 From: perseant Date: Mon, 3 Jul 2000 01:49:11 +0000 Subject: [PATCH] User-level changes corrseponding to my latest kernel changes. newfs_lfs gives lfs_minfreeseg a value of 1/8 of the total segments on the disk, based on rough empirical data, but this should be refined in the future. --- libexec/lfs_cleanerd/cleanerd.c | 33 ++++++++++++++++++--------------- sbin/newfs_lfs/config.h | 17 ++++++++++------- sbin/newfs_lfs/lfs.c | 24 ++++++++++++++++-------- 3 files changed, 44 insertions(+), 30 deletions(-) diff --git a/libexec/lfs_cleanerd/cleanerd.c b/libexec/lfs_cleanerd/cleanerd.c index 4a62f291ddbc..da4226abc196 100644 --- a/libexec/lfs_cleanerd/cleanerd.c +++ b/libexec/lfs_cleanerd/cleanerd.c @@ -1,4 +1,4 @@ -/* $NetBSD: cleanerd.c,v 1.19 2000/06/21 01:58:52 perseant Exp $ */ +/* $NetBSD: cleanerd.c,v 1.20 2000/07/03 01:49:16 perseant Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -40,7 +40,7 @@ __COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\ #if 0 static char sccsid[] = "@(#)cleanerd.c 8.5 (Berkeley) 6/10/95"; #else -__RCSID("$NetBSD: cleanerd.c,v 1.19 2000/06/21 01:58:52 perseant Exp $"); +__RCSID("$NetBSD: cleanerd.c,v 1.20 2000/07/03 01:49:16 perseant Exp $"); #endif #endif /* not lint */ @@ -312,17 +312,19 @@ clean_loop(fsp, nsegs, options) int nsegs; long options; { + struct lfs *lfsp; double loadavg[MAXLOADS]; time_t now; u_long max_free_segs; u_long db_per_seg; + lfsp = &fsp->fi_lfs; /* * Compute the maximum possible number of free segments, given the * number of free blocks. */ - db_per_seg = fragstodb(&fsp->fi_lfs, fsp->fi_lfs.lfs_ssize); - max_free_segs = (fsp->fi_statfsp->f_bfree / fsp->fi_lfs.lfs_ssize) >> fsp->fi_lfs.lfs_fbshift; + db_per_seg = fsbtodb(lfsp, lfsp->lfs_ssize); + max_free_segs = lfsp->lfs_bfree / db_per_seg + lfsp->lfs_minfreeseg; /* * We will clean if there are not enough free blocks or total clean @@ -331,23 +333,24 @@ clean_loop(fsp, nsegs, options) now = time((time_t *)NULL); if(debug > 1) { - syslog(LOG_DEBUG, "db_per_seg = %lu max_free_segs = %lu, bfree = %u avail = %d ", - db_per_seg, max_free_segs, fsp->fi_lfs.lfs_bfree, - fsp->fi_lfs.lfs_avail); + syslog(LOG_DEBUG, "db_per_seg = %lu bfree = %u avail = %d ", + db_per_seg, lfsp->lfs_bfree, + lfsp->lfs_avail); syslog(LOG_DEBUG, "clean segs = %d, max_free_segs = %ld", fsp->fi_cip->clean, max_free_segs); - syslog(LOG_DEBUG, "clean = %d", fsp->fi_cip->clean); } - if ((fsp->fi_lfs.lfs_bfree - fsp->fi_lfs.lfs_avail > db_per_seg && - fsp->fi_lfs.lfs_avail < db_per_seg) || + if ((lfsp->lfs_bfree - lfsp->lfs_avail > db_per_seg && + lfsp->lfs_avail < (long)db_per_seg) || (fsp->fi_cip->clean < max_free_segs && - (fsp->fi_cip->clean <= MIN_SEGS(&fsp->fi_lfs) || + (fsp->fi_cip->clean <= lfsp->lfs_minfreeseg || fsp->fi_cip->clean < max_free_segs * BUSY_LIM))) { if(debug) - syslog(LOG_DEBUG, "Cleaner Running at %s (%d of %lu segments available)", - ctime(&now), fsp->fi_cip->clean, max_free_segs); + syslog(LOG_DEBUG, "Cleaner Running at %s " + "(%d of %lu segments available, avail = %d)", + ctime(&now), fsp->fi_cip->clean, max_free_segs, + lfsp->lfs_avail); clean_fs(fsp, cost_benefit, nsegs, options); if(do_quit) { if(debug) @@ -448,8 +451,8 @@ clean_fs(fsp, cost_func, nsegs, options) } /* If we relly need to clean a lot, do it now */ - if(fsp->fi_cip->clean < 2*MIN_FREE_SEGS) - nsegs = MAX(nsegs,MIN_FREE_SEGS); + if(fsp->fi_cip->clean < 2 * fsp->fi_lfs.lfs_minfreeseg) + nsegs = MAX(nsegs, fsp->fi_lfs.lfs_minfreeseg); /* But back down if we haven't got that many free to clean into */ if(fsp->fi_cip->clean < nsegs) nsegs = fsp->fi_cip->clean; diff --git a/sbin/newfs_lfs/config.h b/sbin/newfs_lfs/config.h index d451a33956e3..8a495d0cd42b 100644 --- a/sbin/newfs_lfs/config.h +++ b/sbin/newfs_lfs/config.h @@ -1,4 +1,4 @@ -/* $NetBSD: config.h,v 1.2 2000/06/27 21:06:24 perseant Exp $ */ +/* $NetBSD: config.h,v 1.3 2000/07/03 01:49:11 perseant Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -52,16 +52,19 @@ #define DFL_FRAGSIZE 1024 #define DFL_BLKSIZE 8192 +/* + * 1/DFL_MIN_FREE_SEGS gives the fraction of segments to be reserved for + * the cleaner. Experimental data show this number should be around + * 5-10. + */ +#define DFL_MIN_FREE_SEGS 8 + /* * MINFREE gives the minimum acceptable percentage of file system * blocks which may be free. If the freelist drops below this level - * only the superuser may continue to allocate blocks. This may - * be set to 0 if no reserve of free blocks is deemed necessary, - * however throughput drops by (how many?) percent if the file system - * is run at between 80% and 100% full; thus the default value of - * fs_minfree is 20%. + * only the superuser may continue to allocate blocks. */ -#define MINFREE 20 +#define MINFREE 10 /* * The following constants set the default block and segment size for a log diff --git a/sbin/newfs_lfs/lfs.c b/sbin/newfs_lfs/lfs.c index 7a248d10c85d..fb3c2de7b9ac 100644 --- a/sbin/newfs_lfs/lfs.c +++ b/sbin/newfs_lfs/lfs.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs.c,v 1.13 2000/06/27 21:06:25 perseant Exp $ */ +/* $NetBSD: lfs.c,v 1.14 2000/07/03 01:49:12 perseant Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)lfs.c 8.5 (Berkeley) 5/24/95"; #else -__RCSID("$NetBSD: lfs.c,v 1.13 2000/06/27 21:06:25 perseant Exp $"); +__RCSID("$NetBSD: lfs.c,v 1.14 2000/07/03 01:49:12 perseant Exp $"); #endif #endif /* not lint */ @@ -149,6 +149,7 @@ static struct lfs lfs_default = { /* dlfs_fsmnt */ { 0 }, /* dlfs_clean */ 0, /* dlfs_dmeta */ 0, + /* dlfs_minfreeseg */ 0, /* dlfs_pad */ { 0 }, /* dlfs_cksum */ 0 @@ -313,8 +314,11 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size) lfsp->lfs_nseg = lfsp->lfs_dsize / lfsp->lfs_ssize; lfsp->lfs_nclean = lfsp->lfs_nseg - 1; lfsp->lfs_maxfilesize = maxtable[lfsp->lfs_bshift] << lfsp->lfs_bshift; + lfsp->lfs_minfreeseg = lfsp->lfs_nseg / DFL_MIN_FREE_SEGS; + if (lfsp->lfs_minfreeseg < MIN_FREE_SEGS) + lfsp->lfs_minfreeseg = MIN_FREE_SEGS; - if(lfsp->lfs_nseg < MIN_FREE_SEGS + 1 + if(lfsp->lfs_nseg < lfsp->lfs_minfreeseg + 1 || lfsp->lfs_nseg < LFS_MIN_SBINTERVAL + 1) { if(seg_size == 0 && ssize > (bsize<<1)) { @@ -333,12 +337,17 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size) /* * The number of free blocks is set from the number of segments - * times the segment size - MIN_FREE_SEGS (that we never write + * times the segment size - lfs_minfreesegs (that we never write * because we need to make sure the cleaner can run). Then * we'll subtract off the room for the superblocks ifile entries - * and segment usage table. + * and segment usage table, and half a block per segment that can't + * be written due to fragmentation. */ - lfsp->lfs_dsize = fsbtodb(lfsp, (lfsp->lfs_nseg - MIN_FREE_SEGS) * lfsp->lfs_ssize); + lfsp->lfs_dsize = fsbtodb(lfsp, (lfsp->lfs_nseg - + lfsp->lfs_minfreeseg) * + lfsp->lfs_ssize); + lfsp->lfs_dsize -= fsbtodb(lfsp, lfsp->lfs_nseg / 2); + lfsp->lfs_bfree = lfsp->lfs_dsize; lfsp->lfs_segtabsz = SEGTABSIZE_SU(lfsp); lfsp->lfs_cleansz = CLEANSIZE_SU(lfsp); @@ -406,8 +415,7 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size) segp->su_flags = SEGUSE_SUPERBLOCK | SEGUSE_DIRTY; lfsp->lfs_bfree -= LFS_SUMMARY_SIZE / lp->d_secsize; lfsp->lfs_bfree -= - fsbtodb(lfsp, lfsp->lfs_cleansz + lfsp->lfs_segtabsz + 4 + - MIN_FREE_SEGS * lfsp->lfs_ssize); + fsbtodb(lfsp, lfsp->lfs_cleansz + lfsp->lfs_segtabsz + 4); /* * Now figure out the address of the ifile inode. The inode block