diff options
author | bde <bde@FreeBSD.org> | 1998-01-20 14:41:53 +0000 |
---|---|---|
committer | bde <bde@FreeBSD.org> | 1998-01-20 14:41:53 +0000 |
commit | 2a7d26ca78deb853b5d0fc77a67f1a95ad3f8a1b (patch) | |
tree | 40b20bc21f16c5141f3912c00be9f3bacc9461ea | |
parent | 94f39c6b0151af37e999622fae68a2031cd8e1c3 (diff) | |
download | FreeBSD-src-2a7d26ca78deb853b5d0fc77a67f1a95ad3f8a1b.zip FreeBSD-src-2a7d26ca78deb853b5d0fc77a67f1a95ad3f8a1b.tar.gz |
Merged just enough files from Lite2 in lfs_cleanerd to convert from
MOUNT_LFS to "lfs" in one place. The merge was painful because it
conflicted with cosmetic FreeBSD changes. lfs_cleanerd still compiles
cleanly but has aproximately the same chance of working as before (0).
-rw-r--r-- | libexec/lfs_cleanerd/clean.h | 6 | ||||
-rw-r--r-- | libexec/lfs_cleanerd/cleanerd.c | 137 | ||||
-rw-r--r-- | libexec/lfs_cleanerd/library.c | 50 |
3 files changed, 145 insertions, 48 deletions
diff --git a/libexec/lfs_cleanerd/clean.h b/libexec/lfs_cleanerd/clean.h index b28cffe..22bf503 100644 --- a/libexec/lfs_cleanerd/clean.h +++ b/libexec/lfs_cleanerd/clean.h @@ -30,8 +30,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)clean.h 8.1 (Berkeley) 6/4/93 - * $Id$ + * @(#)clean.h 8.2 (Berkeley) 5/4/95 + * $Id: clean.h,v 1.6 1997/02/22 14:21:44 peter Exp $ */ /* @@ -107,7 +107,7 @@ typedef struct fs_info { __BEGIN_DECLS int dump_summary __P((struct lfs *, SEGSUM *, u_long, daddr_t **)); void err __P((const int, const char *, ...)); -int fs_getmntinfo __P((struct statfs **, char *, int)); +int fs_getmntinfo __P((struct statfs **, char *, char *)); int get __P((int, off_t, void *, size_t)); FS_INFO *get_fs_info __P((struct statfs *, int)); int lfs_segmapv __P((FS_INFO *, int, caddr_t, BLOCK_INFO **, int *)); diff --git a/libexec/lfs_cleanerd/cleanerd.c b/libexec/lfs_cleanerd/cleanerd.c index d909107..c429f34 100644 --- a/libexec/lfs_cleanerd/cleanerd.c +++ b/libexec/lfs_cleanerd/cleanerd.c @@ -39,10 +39,10 @@ static const char copyright[] = #ifndef lint #if 0 -static char sccsid[] = "@(#)cleanerd.c 8.2 (Berkeley) 1/13/94"; +static char sccsid[] = "@(#)cleanerd.c 8.5 (Berkeley) 6/10/95"; #endif static const char rcsid[] = - "$Id$"; + "$Id: cleanerd.c,v 1.8 1997/11/24 07:26:59 charnier Exp $"; #endif /* not lint */ #include <sys/param.h> @@ -61,7 +61,10 @@ static const char rcsid[] = #include "clean.h" int do_small = 0; int do_mmap = 0; +int stat_report = 0; struct cleaner_stats { + double util_tot; + double util_sos; int blocks_read; int blocks_written; int segs_cleaned; @@ -72,7 +75,7 @@ struct cleaner_stats { struct seglist { int sl_id; /* segment number */ int sl_cost; /* cleaning cost */ - char sl_empty; /* is segment empty */ + char sl_bytes; /* bytes in segment */ }; struct tossstruct { @@ -80,6 +83,8 @@ struct tossstruct { int seg; }; +#define CLEAN_BYTES 0x1 + /* function prototypes for system calls; not sure where they should go */ int lfs_segwait __P((fsid_t *, struct timeval *)); int lfs_segclean __P((fsid_t *, u_long)); @@ -90,8 +95,8 @@ int lfs_markv __P((fsid_t *, BLOCK_INFO *, int)); int bi_tossold __P((const void *, const void *, const void *)); int choose_segments __P((FS_INFO *, struct seglist *, int (*)(FS_INFO *, SEGUSE *))); -void clean_fs __P((FS_INFO *, int (*)(FS_INFO *, SEGUSE *))); -int clean_loop __P((FS_INFO *)); +void clean_fs __P((FS_INFO *, int (*)(FS_INFO *, SEGUSE *), int, long)); +int clean_loop __P((FS_INFO *, int, long)); int clean_segment __P((FS_INFO *, int)); int cost_benefit __P((FS_INFO *, SEGUSE *)); int cost_compare __P((const void *, const void *)); @@ -157,21 +162,36 @@ main(argc, argv) struct statfs *lstatfsp; /* file system stats */ struct timeval timeout; /* sleep timeout */ fsid_t fsid; - int nodaemon; + long clean_opts; /* cleaning options */ + int nodaemon, segs_per_clean; int opt, cmd_err; char *fs_name; /* name of filesystem to clean */ cmd_err = nodaemon = 0; - while ((opt = getopt(argc, argv, "smd")) != -1) { + clean_opts = 0; + segs_per_clean = 1; + while ((opt = getopt(argc, argv, "bdmn:r:s")) != -1) { switch (opt) { - case 's': /* small writes */ - do_small = 1; + case 'b': /* + * Use live bytes to determine + * how many segs to clean. + */ + clean_opts |= CLEAN_BYTES; + break; + case 'd': /* Debug mode. */ + nodaemon = 1; break; - case 'm': + case 'm': /* Use mmap instead of read/write */ do_mmap = 1; break; - case 'd': - nodaemon = 1; + case 'n': /* How many segs to clean at once */ + segs_per_clean = atoi(optarg); + break; + case 'r': /* Report every stat_report segments */ + stat_report = atoi(optarg); + break; + case 's': /* small writes */ + do_small = 1; break; default: ++cmd_err; @@ -187,7 +207,7 @@ main(argc, argv) signal(SIGINT, sig_report); signal(SIGUSR1, sig_report); signal(SIGUSR2, sig_report); - if (fs_getmntinfo(&lstatfsp, fs_name, MOUNT_LFS) == 0) { + if (fs_getmntinfo(&lstatfsp, fs_name, "lfs") == 0) { /* didn't find the filesystem */ errx(1, "filesystem %s isn't an LFS", fs_name); } @@ -209,7 +229,7 @@ main(argc, argv) * to make sure that some nasty process hasn't just * filled the disk system up. */ - if (clean_loop(fsp)) + if (clean_loop(fsp, segs_per_clean, clean_opts)) continue; #ifdef VERBOSE @@ -232,30 +252,42 @@ usage() /* return the number of segments cleaned */ int -clean_loop(fsp) +clean_loop(fsp, nsegs, options) FS_INFO *fsp; /* file system information */ + int nsegs; + long options; { double loadavg[MAXLOADS]; time_t now; u_long max_free_segs; + u_long db_per_seg; /* * Compute the maximum possible number of free segments, given the * number of free blocks. */ - max_free_segs = fsp->fi_statfsp->f_bfree / fsp->fi_lfs.lfs_ssize; + db_per_seg = fsbtodb(&fsp->fi_lfs, fsp->fi_lfs.lfs_ssize); + max_free_segs = fsp->fi_lfs.lfs_bfree / db_per_seg; /* * We will clean if there are not enough free blocks or total clean * space is less than BUSY_LIM % of possible clean space. */ now = time((time_t *)NULL); - if (fsp->fi_cip->clean < max_free_segs && +#ifdef VERBOSE + printf("db_er_seg = %d max_free_segs = %d, bfree = %d avail = %d ", + db_per_seg, max_free_segs, fsp->fi_lfs.lfs_bfree, + fsp->fi_lfs.lfs_avail); + printf("clean = %d\n", fsp->fi_cip->clean); +#endif + if ((fsp->fi_lfs.lfs_bfree - fsp->fi_lfs.lfs_avail > db_per_seg && + fsp->fi_lfs.lfs_avail < db_per_seg) || + (fsp->fi_cip->clean < max_free_segs && (fsp->fi_cip->clean <= MIN_SEGS(&fsp->fi_lfs) || - fsp->fi_cip->clean < max_free_segs * BUSY_LIM)) { + fsp->fi_cip->clean < max_free_segs * BUSY_LIM))) { printf("Cleaner Running at %s (%d of %ld segments available)\n", ctime(&now), fsp->fi_cip->clean, max_free_segs); - clean_fs(fsp, cost_benefit); + clean_fs(fsp, cost_benefit, nsegs, options); return (1); } else { /* @@ -269,7 +301,7 @@ clean_loop(fsp) } if (loadavg[ONE_MIN] == 0.2 && loadavg[FIVE_MIN] && fsp->fi_cip->clean < max_free_segs * IDLE_LIM) { - clean_fs(fsp, cost_benefit); + clean_fs(fsp, cost_benefit, nsegs, options); printf("Cleaner running (system idle) at %s", ctime(&now)); return (1); @@ -283,11 +315,14 @@ clean_loop(fsp) void -clean_fs(fsp, cost_func) +clean_fs(fsp, cost_func, nsegs, options) FS_INFO *fsp; /* file system information */ int (*cost_func) __P((FS_INFO *, SEGUSE *)); + int nsegs; + long options; { struct seglist *segs, *sp; + int to_clean, cleaned_bytes; int i; if ((segs = @@ -301,15 +336,33 @@ clean_fs(fsp, cost_func) i, fsp->fi_statfsp->f_mntonname); fflush(stdout); #endif - if (i) - for (i = MIN(i, NUM_TO_CLEAN(fsp)), sp = segs; i-- ; ++sp) { - if (clean_segment(fsp, sp->sl_id) < 0) - warn("clean_segment failed"); - else if (lfs_segclean(&fsp->fi_statfsp->f_fsid, - sp->sl_id) < 0) - warn("lfs_segclean failed"); - printf("Completed cleaning segment %d\n", sp->sl_id); - } + if (i) { + /* Check which cleaning algorithm to use. */ + if (options & CLEAN_BYTES) { + cleaned_bytes = 0; + to_clean = nsegs << + (fsp->fi_lfs.lfs_segshift + fsp->fi_lfs.lfs_bshift); + for (sp = segs; i && cleaned_bytes < to_clean; + i--, ++sp) { + if (clean_segment(fsp, sp->sl_id) < 0) + warn("clean_segment failed"); + else if (lfs_segclean(&fsp->fi_statfsp->f_fsid, + sp->sl_id) < 0) + warn("lfs_segclean failed"); + printf("Cleaned segment %d (%d bytes)\n", + sp->sl_id, sp->sl_bytes); + cleaned_bytes += sp->sl_bytes; + } + } else + for (i = MIN(i, nsegs), sp = segs; i-- ; ++sp) { + if (clean_segment(fsp, sp->sl_id) < 0) + warn("clean_segment failed"); + else if (lfs_segclean(&fsp->fi_statfsp->f_fsid, + sp->sl_id) < 0) + warn("lfs_segclean failed"); + printf("Completed cleaning segment %d\n", sp->sl_id); + } + } free(segs); } @@ -362,7 +415,7 @@ choose_segments(fsp, seglist, cost_func) #endif sp->sl_cost = (*cost_func)(fsp, sup); sp->sl_id = i; - sp->sl_empty = sup->su_nbytes ? 0 : 1; + sp->sl_bytes = sup->su_nbytes; ++sp; } nsegs = sp - seglist; @@ -384,6 +437,7 @@ clean_segment(fsp, id) struct lfs *lfsp; struct tossstruct t; caddr_t seg_buf; + double util; int num_blocks, maxblocks, clean_blocks; lfsp = &fsp->fi_lfs; @@ -450,8 +504,14 @@ clean_segment(fsp, id) lp = (u_long *)_bip->bi_bp; } } + #endif + ++cleaner_stats.segs_cleaned; cleaner_stats.blocks_written += num_blocks; + util = ((double)num_blocks / fsp->fi_lfs.lfs_ssize); + cleaner_stats.util_tot += util; + cleaner_stats.util_sos += util * util; + if (do_small) maxblocks = MAXPHYS / fsp->fi_lfs.lfs_bsize - 1; else @@ -470,7 +530,8 @@ clean_segment(fsp, id) free(block_array); munmap_segment(fsp, seg_buf, do_mmap); - ++cleaner_stats.segs_cleaned; + if (stat_report && cleaner_stats.segs_cleaned % stat_report == 0) + sig_report(SIGUSR1); return (0); } @@ -493,18 +554,30 @@ void sig_report(sig) int sig; { + double avg; + printf("lfs_cleanerd:\t%s%d\n\t\t%s%d\n\t\t%s%d\n\t\t%s%d\n\t\t%s%d\n", "blocks_read ", cleaner_stats.blocks_read, "blocks_written ", cleaner_stats.blocks_written, "segs_cleaned ", cleaner_stats.segs_cleaned, "segs_empty ", cleaner_stats.segs_empty, "seg_error ", cleaner_stats.segs_error); + printf("\t\t%s%5.2f\n\t\t%s%5.2f\n", + "util_tot ", cleaner_stats.util_tot, + "util_sos ", cleaner_stats.util_sos); + printf("\t\tavg util: %4.2f std dev: %9.6f\n", + avg = cleaner_stats.util_tot / cleaner_stats.segs_cleaned, + cleaner_stats.util_sos / cleaner_stats.segs_cleaned - avg * avg); + + if (sig == SIGUSR2) { cleaner_stats.blocks_read = 0; cleaner_stats.blocks_written = 0; cleaner_stats.segs_cleaned = 0; cleaner_stats.segs_empty = 0; cleaner_stats.segs_error = 0; + cleaner_stats.util_tot = 0.0; + cleaner_stats.util_sos = 0.0; } if (sig == SIGINT) exit(0); diff --git a/libexec/lfs_cleanerd/library.c b/libexec/lfs_cleanerd/library.c index a7094bb..13132e5 100644 --- a/libexec/lfs_cleanerd/library.c +++ b/libexec/lfs_cleanerd/library.c @@ -33,10 +33,10 @@ #ifndef lint #if 0 -static char sccsid[] = "@(#)library.c 8.1 (Berkeley) 6/4/93"; +static char sccsid[] = "@(#)library.c 8.3 (Berkeley) 5/24/95"; #endif static const char rcsid[] = - "$Id$"; + "$Id: library.c,v 1.9 1997/11/24 07:27:02 charnier Exp $"; #endif /* not lint */ #include <sys/param.h> @@ -79,7 +79,7 @@ int fs_getmntinfo(buf, name, type) struct statfs **buf; char *name; - int type; + char *type; { /* allocate space for the filesystem info */ *buf = (struct statfs *)malloc(sizeof(struct statfs)); @@ -93,7 +93,7 @@ fs_getmntinfo(buf, name, type) } /* check to see if it's the one we want */ - if (((*buf)->f_type != type) || + if (strcmp((*buf)->f_fstypename, type) || strncmp(name, (*buf)->f_mntonname, MNAMELEN)) { /* "this is not the filesystem you're looking for" */ free(*buf); @@ -266,7 +266,7 @@ lfs_segmapv(fsp, seg, seg_buf, blocks, bcount) struct lfs *lfsp; caddr_t s, segend; daddr_t pseg_addr, seg_addr; - int nelem, nblocks; + int nelem, nblocks, nsegs; #ifdef DIAGNOSTIC FINFO *fip; int i, sumsize; @@ -288,19 +288,22 @@ lfs_segmapv(fsp, seg, seg_buf, blocks, bcount) #endif /* VERBOSE */ *bcount = 0; - for (segend = seg_buf + seg_size(lfsp), timestamp = 0; s < segend; ) { + for (nsegs = 0, timestamp = 0; nsegs < sup->su_nsums; nsegs++) { sp = (SEGSUM *)s; + nblocks = pseg_valid(fsp, sp); + if (nblocks <= 0) { + printf("Warning: invalid segment summary at 0x%x\n", + pseg_addr); + break; + } + #ifdef VERBOSE printf("\tpartial at: 0x%x\n", pseg_addr); print_SEGSUM(lfsp, sp); fflush(stdout); #endif /* VERBOSE */ - nblocks = pseg_valid(fsp, sp); - if (nblocks <= 0) - break; - /* Check if we have hit old data */ if (timestamp > ((SEGSUM*)s)->ss_create) break; @@ -310,7 +313,7 @@ lfs_segmapv(fsp, seg, seg_buf, blocks, bcount) /* Verify size of summary block */ sumsize = sizeof(SEGSUM) + (sp->ss_ninos + INOPB(lfsp) - 1) / INOPB(lfsp); - for (fip = (FINFO *)(sp + 1); i < sp->ss_nfinfo; ++i) { + for (i = 0, fip = (FINFO *)(sp + 1); i < sp->ss_nfinfo; ++i) { sumsize += sizeof(FINFO) + (fip->fi_nblocks - 1) * sizeof(daddr_t); fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks]); @@ -372,7 +375,9 @@ add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr) caddr_t bp; daddr_t *dp, *iaddrp; int db_per_block, i, j; + int db_frag; u_long page_size; +long *lp; #ifdef VERBOSE printf("FILE INFOS\n"); @@ -404,8 +409,24 @@ add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr) bip->bi_segcreate = (time_t)(sp->ss_create); bip->bi_bp = bp; bip->bi_version = ifp->if_version; - psegaddr += db_per_block; - bp += page_size; + if (fip->fi_lastlength == page_size) { + bip->bi_size = page_size; + psegaddr += db_per_block; + bp += page_size; + } else { + db_frag = fragstodb(&(fsp->fi_lfs), + numfrags(&(fsp->fi_lfs), + fip->fi_lastlength)); +#ifdef VERBOSE + printf("lastlength, frags: %d, %d, %d\n", + fip->fi_lastlength, temp, + bytetoda(fsp, temp)); + fflush(stdout); +#endif + bip->bi_size = fip->fi_lastlength; + bp += fip->fi_lastlength; + psegaddr += db_frag; + } ++bip; ++(*countp); } @@ -490,6 +511,9 @@ pseg_valid (fsp, ssp) int i, nblocks; u_long *datap; + if (ssp->ss_magic != SS_MAGIC) + return(0); + if ((nblocks = dump_summary(&fsp->fi_lfs, ssp, 0, NULL)) <= 0 || nblocks > fsp->fi_lfs.lfs_ssize - 1) return(0); |