Cleaner changes corresponding to in-kernel LFS changes. In particular, the
cleaner understands fragments; and it knows to change bi_bp to reflect a change in bi_daddr, if lfs_bmapv says that there is one.
This commit is contained in:
parent
97bbd0e85a
commit
2c952176c1
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: clean.h,v 1.6 1998/10/07 15:00:34 christos Exp $ */
|
||||
/* $NetBSD: clean.h,v 1.7 1999/03/10 00:57:16 perseant Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
@ -73,6 +73,8 @@
|
||||
#define FIVE_MIN 1
|
||||
#define FIFTEEN_MIN 2
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
typedef struct fs_info {
|
||||
struct statfs *fi_statfsp; /* fsstat info from getfsstat */
|
||||
struct lfs fi_lfs; /* superblock */
|
||||
@ -82,6 +84,7 @@ typedef struct fs_info {
|
||||
u_long fi_daddr_shift; /* shift to get byte offset of daddr */
|
||||
u_long fi_ifile_count; /* # entries in the ifile table */
|
||||
off_t fi_ifile_length; /* length of the ifile */
|
||||
time_t fi_fs_tstamp; /* last fs activity, per ifile */
|
||||
} FS_INFO;
|
||||
|
||||
/*
|
||||
@ -106,8 +109,9 @@ typedef struct fs_info {
|
||||
(i) % (fs)->lfs_sepb)
|
||||
|
||||
__BEGIN_DECLS
|
||||
int dump_summary __P((struct lfs *, SEGSUM *, u_long, daddr_t **));
|
||||
int dump_summary __P((struct lfs *, SEGSUM *, u_long, daddr_t **, daddr_t));
|
||||
void err __P((const int, const char *, ...));
|
||||
void warn __P((const char *, ...));
|
||||
int fs_getmntinfo __P((struct statfs **, char *, const char *));
|
||||
void get __P((int, off_t, void *, size_t));
|
||||
FS_INFO *get_fs_info __P((struct statfs *, int));
|
||||
@ -141,7 +145,7 @@ void toss __P((void *, int *, size_t,
|
||||
}
|
||||
|
||||
#define PRINT_SEGUSE(sup, n) if(debug > 1) { \
|
||||
syslog(LOG_DEBUG,"Segment %d nbytes=%lu\tflags=%c%c%c ninos=%d nsums=%d lastmod: %s\n", \
|
||||
syslog(LOG_DEBUG,"Segment %d nbytes=%lu\tflags=%c%c%c ninos=%d nsums=%d lastmod: %s", \
|
||||
n, (unsigned long)(sup)->su_nbytes, \
|
||||
(sup)->su_flags & SEGUSE_DIRTY ? 'D' : 'C', \
|
||||
(sup)->su_flags & SEGUSE_ACTIVE ? 'A' : ' ', \
|
||||
@ -152,6 +156,6 @@ void toss __P((void *, int *, size_t,
|
||||
|
||||
void dump_super __P((struct lfs *));
|
||||
void dump_cleaner_info __P((void *));
|
||||
void print_SEGSUM __P(( struct lfs *, SEGSUM *));
|
||||
void print_SEGSUM __P(( struct lfs *, SEGSUM *, daddr_t));
|
||||
void print_CLEANERINFO __P((CLEANERINFO *));
|
||||
__END_DECLS
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: cleanerd.c,v 1.11 1998/10/07 15:00:34 christos Exp $ */
|
||||
/* $NetBSD: cleanerd.c,v 1.12 1999/03/10 00:57:16 perseant Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
@ -40,13 +40,16 @@ __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.11 1998/10/07 15:00:34 christos Exp $");
|
||||
__RCSID("$NetBSD: cleanerd.c,v 1.12 1999/03/10 00:57:16 perseant Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <ufs/ufs/dinode.h>
|
||||
#include <ufs/lfs/lfs.h>
|
||||
@ -63,8 +66,12 @@ __RCSID("$NetBSD: cleanerd.c,v 1.11 1998/10/07 15:00:34 christos Exp $");
|
||||
char *special = "cleanerd";
|
||||
int do_small = 0;
|
||||
int do_mmap = 0;
|
||||
int do_quit = 0;
|
||||
int stat_report = 0;
|
||||
int debug = 0;
|
||||
int segwait_timeout = 5*60; /* Five minutes */
|
||||
double load_threshold = 0.2;
|
||||
int use_fs_idle = 0;
|
||||
struct cleaner_stats {
|
||||
double util_tot;
|
||||
double util_sos;
|
||||
@ -100,7 +107,7 @@ int choose_segments __P((FS_INFO *, struct seglist *,
|
||||
int (*)(FS_INFO *, SEGUSE *)));
|
||||
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 clean_segment __P((FS_INFO *, struct seglist *));
|
||||
int cost_benefit __P((FS_INFO *, SEGUSE *));
|
||||
int cost_compare __P((const void *, const void *));
|
||||
void sig_report __P((int));
|
||||
@ -149,8 +156,12 @@ cost_benefit(fsp, su)
|
||||
syslog(LOG_NOTICE,"bad segusage count: %d", live);
|
||||
live = 0;
|
||||
}
|
||||
#if 0
|
||||
return lblkno(lfsp, seg_size(lfsp) - live);
|
||||
#else
|
||||
return (lblkno(lfsp, seg_size(lfsp) - live) * age)
|
||||
/ lblkno(lfsp, seg_size(lfsp) + live);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,12 +177,13 @@ main(argc, argv)
|
||||
long clean_opts; /* cleaning options */
|
||||
int segs_per_clean;
|
||||
int opt, cmd_err;
|
||||
pid_t childpid;
|
||||
char *fs_name; /* name of filesystem to clean */
|
||||
|
||||
cmd_err = debug = 0;
|
||||
cmd_err = debug = do_quit = 0;
|
||||
clean_opts = 0;
|
||||
segs_per_clean = 1;
|
||||
while ((opt = getopt(argc, argv, "bdmn:r:s")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "bdfl:mn:qr:st:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'b':
|
||||
/*
|
||||
@ -183,18 +195,30 @@ main(argc, argv)
|
||||
case 'd': /* Debug mode. */
|
||||
debug++;
|
||||
break;
|
||||
case 'f':
|
||||
use_fs_idle = 1;
|
||||
break;
|
||||
case 'l': /* Load below which to clean */
|
||||
load_threshold = atof(optarg);
|
||||
break;
|
||||
case 'm':
|
||||
do_mmap = 1;
|
||||
break;
|
||||
case 'n': /* How many segs to clean at once */
|
||||
segs_per_clean = atoi(optarg);
|
||||
break;
|
||||
case 'q': /* Quit after one run */
|
||||
do_quit = 1;
|
||||
break;
|
||||
case 'r': /* Report every stat_report segments */
|
||||
stat_report = atoi(optarg);
|
||||
break;
|
||||
case 's': /* small writes */
|
||||
do_small = 1;
|
||||
break;
|
||||
case 't':
|
||||
segwait_timeout = atoi(optarg);
|
||||
break;
|
||||
default:
|
||||
++cmd_err;
|
||||
}
|
||||
@ -202,13 +226,10 @@ main(argc, argv)
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (cmd_err || (argc != 1))
|
||||
err(1, "usage: lfs_cleanerd [-bdms] [-n nsegs] [-r report_freq] fs_name");
|
||||
err(1, "usage: lfs_cleanerd [-bdms] [-l load] [-n nsegs] [-r report_freq] [-t timeout] fs_name");
|
||||
|
||||
fs_name = argv[0];
|
||||
|
||||
signal(SIGINT, sig_report);
|
||||
signal(SIGUSR1, sig_report);
|
||||
signal(SIGUSR2, sig_report);
|
||||
if (fs_getmntinfo(&lstatfsp, fs_name, MOUNT_LFS) == 0) {
|
||||
/* didn't find the filesystem */
|
||||
err(1, "lfs_cleanerd: filesystem %s isn't an LFS!", fs_name);
|
||||
@ -218,13 +239,34 @@ main(argc, argv)
|
||||
if (debug == 0) {
|
||||
if (daemon(0, 0) == -1)
|
||||
err(1, "lfs_cleanerd: couldn't become a daemon!");
|
||||
loop:
|
||||
if((childpid=fork())<0) {
|
||||
syslog(LOG_NOTICE,"lfs_cleanerd: couldn't fork, exiting: %m");
|
||||
exit(1);
|
||||
}
|
||||
if(childpid != 0) {
|
||||
wait(NULL);
|
||||
if (fs_getmntinfo(&lstatfsp, fs_name, MOUNT_LFS) == 0) {
|
||||
/* fs has been unmounted(?); exit quietly */
|
||||
syslog(LOG_INFO,"lfs_cleanerd: fs %s unmounted, exiting", fs_name);
|
||||
exit(0);
|
||||
}
|
||||
goto loop;
|
||||
}
|
||||
openlog("lfs_cleanerd", LOG_NDELAY|LOG_PID, LOG_DAEMON);
|
||||
} else {
|
||||
openlog("lfs_cleanerd", LOG_NDELAY|LOG_PID|LOG_PERROR,
|
||||
LOG_DAEMON);
|
||||
}
|
||||
|
||||
timeout.tv_sec = 5*60; /* five minutes */
|
||||
signal(SIGINT, sig_report);
|
||||
signal(SIGUSR1, sig_report);
|
||||
signal(SIGUSR2, sig_report);
|
||||
|
||||
if(debug)
|
||||
syslog(LOG_INFO,"Cleaner starting on filesystem %s", fs_name);
|
||||
|
||||
timeout.tv_sec = segwait_timeout;
|
||||
timeout.tv_usec = 0;
|
||||
fsid.val[0] = 0;
|
||||
fsid.val[1] = 0;
|
||||
@ -240,12 +282,13 @@ main(argc, argv)
|
||||
if (clean_loop(fsp, segs_per_clean, clean_opts))
|
||||
continue;
|
||||
|
||||
fsid = lstatfsp->f_fsid;
|
||||
if(debug > 1)
|
||||
syslog(LOG_DEBUG,"Cleaner going to sleep.\n");
|
||||
syslog(LOG_DEBUG,"Cleaner going to sleep.");
|
||||
if (lfs_segwait(&fsid, &timeout) < 0)
|
||||
syslog(LOG_WARNING,"lfs_segwait returned error\n");
|
||||
syslog(LOG_WARNING,"lfs_segwait returned error.");
|
||||
if(debug > 1)
|
||||
syslog(LOG_DEBUG,"Cleaner waking up.\n");
|
||||
syslog(LOG_DEBUG,"Cleaner waking up.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,22 +319,50 @@ clean_loop(fsp, nsegs, options)
|
||||
|
||||
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, "clean = %d\n", fsp->fi_cip->clean);
|
||||
db_per_seg, max_free_segs, fsp->fi_lfs.lfs_bfree,
|
||||
fsp->fi_lfs.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) ||
|
||||
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 <= MIN_SEGS(&fsp->fi_lfs) ||
|
||||
fsp->fi_cip->clean < max_free_segs * BUSY_LIM)))
|
||||
{
|
||||
if(debug)
|
||||
syslog(LOG_DEBUG, "Cleaner Running at %s (%d of %lu segments available)\n",
|
||||
ctime(&now), fsp->fi_cip->clean, max_free_segs);
|
||||
syslog(LOG_DEBUG, "Cleaner Running at %s (%d of %lu segments available)",
|
||||
ctime(&now), fsp->fi_cip->clean, max_free_segs);
|
||||
clean_fs(fsp, cost_benefit, nsegs, options);
|
||||
if(do_quit) {
|
||||
if(debug)
|
||||
syslog(LOG_INFO,"Cleaner shutting down");
|
||||
exit(0);
|
||||
}
|
||||
return (1);
|
||||
} else if(use_fs_idle) {
|
||||
/*
|
||||
* If we're using "filesystem idle" instead of system idle,
|
||||
* clean if the fs has not been modified in segwait_timeout
|
||||
* seconds.
|
||||
*/
|
||||
if(now-fsp->fi_fs_tstamp > segwait_timeout
|
||||
&& fsp->fi_cip->clean < max_free_segs * IDLE_LIM) {
|
||||
if(debug) {
|
||||
syslog(LOG_DEBUG, "Cleaner Running at %s: fs idle time %ld sec; %d of %lu segments available)",
|
||||
ctime(&now), now-fsp->fi_fs_tstamp, fsp->fi_cip->clean, max_free_segs);
|
||||
syslog(LOG_DEBUG, " filesystem idle since %s", ctime(&(fsp->fi_fs_tstamp)));
|
||||
}
|
||||
clean_fs(fsp, cost_benefit, nsegs, options);
|
||||
if(do_quit) {
|
||||
if(debug)
|
||||
syslog(LOG_INFO,"Cleaner shutting down");
|
||||
exit(0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* We will also clean if the system is reasonably idle and
|
||||
@ -302,16 +373,23 @@ clean_loop(fsp, nsegs, options)
|
||||
perror("getloadavg: failed\n");
|
||||
return (-1);
|
||||
}
|
||||
if (loadavg[ONE_MIN] == 0.0 && loadavg[FIVE_MIN] &&
|
||||
fsp->fi_cip->clean < max_free_segs * IDLE_LIM) {
|
||||
clean_fs(fsp, cost_benefit, nsegs, options);
|
||||
if (loadavg[ONE_MIN] < load_threshold
|
||||
&& fsp->fi_cip->clean < max_free_segs * IDLE_LIM)
|
||||
{
|
||||
if(debug)
|
||||
syslog(LOG_DEBUG, "Cleaner Running at %s (system idle)\n",
|
||||
ctime(&now));
|
||||
syslog(LOG_DEBUG, "Cleaner Running at %s (system load %.1f, %d of %lu segments available)",
|
||||
ctime(&now), loadavg[ONE_MIN],
|
||||
fsp->fi_cip->clean, max_free_segs);
|
||||
clean_fs(fsp, cost_benefit, nsegs, options);
|
||||
if(do_quit) {
|
||||
if(debug)
|
||||
syslog(LOG_INFO,"Cleaner shutting down");
|
||||
exit(0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
if(debug)
|
||||
}
|
||||
if(debug > 1)
|
||||
syslog(LOG_DEBUG, "Cleaner Not Running at %s", ctime(&now));
|
||||
return (0);
|
||||
}
|
||||
@ -325,50 +403,75 @@ clean_fs(fsp, cost_func, nsegs, options)
|
||||
long options;
|
||||
{
|
||||
struct seglist *segs, *sp;
|
||||
int to_clean, cleaned_bytes;
|
||||
int i;
|
||||
long int to_clean, cleaned_bytes;
|
||||
int i, total;
|
||||
|
||||
if ((segs =
|
||||
malloc(fsp->fi_lfs.lfs_nseg * sizeof(struct seglist))) == NULL) {
|
||||
syslog(LOG_WARNING,"malloc failed: %m");
|
||||
return;
|
||||
}
|
||||
i = choose_segments(fsp, segs, cost_func);
|
||||
total = i = choose_segments(fsp, segs, cost_func);
|
||||
|
||||
/* 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);
|
||||
/* 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;
|
||||
|
||||
if(debug > 1)
|
||||
syslog(LOG_DEBUG, "clean_fs: found %d segments to clean in file system %s\n",
|
||||
i, fsp->fi_statfsp->f_mntonname);
|
||||
syslog(LOG_DEBUG, "clean_fs: found %d segments to clean in file system %s",
|
||||
i, fsp->fi_statfsp->f_mntonname);
|
||||
|
||||
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);
|
||||
to_clean = nsegs << fsp->fi_lfs.lfs_segshift;
|
||||
for (sp = segs; i && cleaned_bytes < to_clean;
|
||||
i--, ++sp) {
|
||||
if (clean_segment(fsp, sp->sl_id) < 0)
|
||||
perror("clean_segment failed");
|
||||
if (clean_segment(fsp, sp) < 0)
|
||||
syslog(LOG_NOTICE,"clean_segment failed segment %d: %m", sp->sl_id);
|
||||
else if (lfs_segclean(&fsp->fi_statfsp->f_fsid,
|
||||
sp->sl_id) < 0)
|
||||
perror("lfs_segclean failed");
|
||||
if(debug)
|
||||
syslog(LOG_DEBUG, "Cleaned segment %d (%d bytes)\n",
|
||||
sp->sl_id, sp->sl_bytes);
|
||||
cleaned_bytes += sp->sl_bytes;
|
||||
sp->sl_id) < 0)
|
||||
syslog(LOG_NOTICE,"lfs_segclean failed segment %d: %m", sp->sl_id);
|
||||
else {
|
||||
if(debug) {
|
||||
syslog(LOG_DEBUG,
|
||||
"Cleaned segment %d (%d->%ld/%ld)",
|
||||
sp->sl_id,
|
||||
(1<<fsp->fi_lfs.lfs_segshift) - sp->sl_bytes,
|
||||
cleaned_bytes + (1<<fsp->fi_lfs.lfs_segshift) - sp->sl_bytes,
|
||||
to_clean);
|
||||
}
|
||||
cleaned_bytes += (1<<fsp->fi_lfs.lfs_segshift) - sp->sl_bytes;
|
||||
}
|
||||
}
|
||||
} else
|
||||
for (i = MIN(i, nsegs), sp = segs; i-- ; ++sp) {
|
||||
if (clean_segment(fsp, sp->sl_id) < 0)
|
||||
perror("clean_segment failed");
|
||||
total--;
|
||||
syslog(LOG_DEBUG,"Cleaning segment %d (of %d choices)", sp->sl_id, i+1);
|
||||
if (clean_segment(fsp, sp) < 0) {
|
||||
syslog(LOG_NOTICE,"clean_segment failed segment %d: %m", sp->sl_id);
|
||||
if(total)
|
||||
i++;
|
||||
}
|
||||
else if (lfs_segclean(&fsp->fi_statfsp->f_fsid,
|
||||
sp->sl_id) < 0)
|
||||
perror("lfs_segclean failed");
|
||||
if(debug)
|
||||
syslog(LOG_DEBUG,"Completed cleaning segment %d\n", sp->sl_id);
|
||||
syslog(LOG_NOTICE,"lfs_segclean failed segment %d: %m", sp->sl_id);
|
||||
else if(debug)
|
||||
syslog(LOG_DEBUG,"Completed cleaning segment %d (of %d choices)", sp->sl_id, i+1);
|
||||
}
|
||||
}
|
||||
free(segs);
|
||||
if(debug) {
|
||||
struct rusage ru;
|
||||
|
||||
getrusage(RUSAGE_SELF,&ru);
|
||||
syslog(LOG_DEBUG,"Current usage: maxrss=%ld, idrss=%ld",
|
||||
ru.ru_maxrss,ru.ru_idrss);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -404,18 +507,19 @@ choose_segments(fsp, seglist, cost_func)
|
||||
lfsp = &fsp->fi_lfs;
|
||||
|
||||
if(debug > 1)
|
||||
syslog(LOG_DEBUG,"Entering choose_segments\n");
|
||||
syslog(LOG_DEBUG,"Entering choose_segments");
|
||||
dump_super(lfsp);
|
||||
dump_cleaner_info(fsp->fi_cip);
|
||||
|
||||
for (sp = seglist, i = 0; i < lfsp->lfs_nseg; ++i) {
|
||||
sup = SEGUSE_ENTRY(lfsp, fsp->fi_segusep, i);
|
||||
PRINT_SEGUSE(sup, i);
|
||||
if(debug > 1)
|
||||
PRINT_SEGUSE(sup, i);
|
||||
if (!(sup->su_flags & SEGUSE_DIRTY) ||
|
||||
sup->su_flags & SEGUSE_ACTIVE)
|
||||
continue;
|
||||
if(debug > 1)
|
||||
syslog(LOG_DEBUG, "\tchoosing segment %d\n", i);
|
||||
syslog(LOG_DEBUG, "\tchoosing segment %d", i);
|
||||
sp->sl_cost = (*cost_func)(fsp, sup);
|
||||
sp->sl_id = i;
|
||||
sp->sl_bytes = sup->su_nbytes;
|
||||
@ -425,38 +529,44 @@ choose_segments(fsp, seglist, cost_func)
|
||||
qsort(seglist, nsegs, sizeof(struct seglist), cost_compare);
|
||||
|
||||
if(debug > 1)
|
||||
syslog(LOG_DEBUG,"Returning %d segments\n", nsegs);
|
||||
syslog(LOG_DEBUG,"Returning %d segments", nsegs);
|
||||
|
||||
return (nsegs);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
clean_segment(fsp, id)
|
||||
clean_segment(fsp, slp)
|
||||
FS_INFO *fsp; /* file system information */
|
||||
int id; /* segment number */
|
||||
struct seglist *slp; /* segment info */
|
||||
{
|
||||
int id=slp->sl_id;
|
||||
BLOCK_INFO *block_array, *bp, *_bip;
|
||||
SEGUSE *sp;
|
||||
struct lfs *lfsp;
|
||||
struct tossstruct t;
|
||||
struct dinode *dip;
|
||||
double util;
|
||||
caddr_t seg_buf;
|
||||
int num_blocks, maxblocks, clean_blocks, i;
|
||||
daddr_t seg_addr;
|
||||
int num_blocks, maxblocks, clean_blocks, i, j;
|
||||
unsigned long *lp;
|
||||
|
||||
lfsp = &fsp->fi_lfs;
|
||||
sp = SEGUSE_ENTRY(lfsp, fsp->fi_segusep, id);
|
||||
seg_addr = sntoda(lfsp,id);
|
||||
|
||||
if(debug > 1)
|
||||
syslog(LOG_DEBUG, "cleaning segment %d: contains %lu bytes\n", id,
|
||||
(unsigned long)sp->su_nbytes);
|
||||
syslog(LOG_DEBUG, "cleaning segment %d: contains %lu bytes", id,
|
||||
(unsigned long)sp->su_nbytes);
|
||||
|
||||
#if 0
|
||||
/* XXX could add debugging to verify that segment is really empty */
|
||||
if (sp->su_nbytes == sp->su_nsums * LFS_SUMMARY_SIZE) {
|
||||
++cleaner_stats.segs_empty;
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* map the segment into a buffer */
|
||||
if (mmap_segment(fsp, id, &seg_buf, do_mmap) < 0) {
|
||||
@ -466,19 +576,20 @@ clean_segment(fsp, id)
|
||||
}
|
||||
/* get a list of blocks that are contained by the segment */
|
||||
if (lfs_segmapv(fsp, id, seg_buf, &block_array, &num_blocks) < 0) {
|
||||
syslog(LOG_WARNING,"clean_segment: lfs_segmapv failed");
|
||||
syslog(LOG_WARNING,"clean_segment: lfs_segmapv failed for segment %d",id);
|
||||
++cleaner_stats.segs_error;
|
||||
return (-1);
|
||||
}
|
||||
cleaner_stats.blocks_read += fsp->fi_lfs.lfs_ssize;
|
||||
|
||||
if(debug > 1)
|
||||
syslog(LOG_DEBUG, "lfs_segmapv returned %d blocks\n", num_blocks);
|
||||
syslog(LOG_DEBUG, "lfs_segmapv returned %d blocks", num_blocks);
|
||||
|
||||
/* get the current disk address of blocks contained by the segment */
|
||||
if (lfs_bmapv(&fsp->fi_statfsp->f_fsid, block_array, num_blocks) < 0) {
|
||||
perror("clean_segment: lfs_bmapv failed\n");
|
||||
++cleaner_stats.segs_error;
|
||||
free(block_array); /* XXX KS */
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -486,21 +597,74 @@ clean_segment(fsp, id)
|
||||
t.lfs = lfsp;
|
||||
t.seg = id;
|
||||
toss(block_array, &num_blocks, sizeof(BLOCK_INFO), bi_tossold, &t);
|
||||
|
||||
/* Check if last element should be tossed */
|
||||
if (num_blocks && bi_tossold(&t, block_array + num_blocks - 1, NULL))
|
||||
--num_blocks;
|
||||
|
||||
if(debug > 1) {
|
||||
syslog(LOG_DEBUG, "after bmapv still have %d blocks\n", num_blocks);
|
||||
if (num_blocks)
|
||||
syslog(LOG_DEBUG, "BLOCK INFOS\n");
|
||||
for (_bip = block_array, i=0; i < num_blocks; ++_bip, ++i) {
|
||||
PRINT_BINFO(_bip);
|
||||
lp = (u_long *)_bip->bi_bp;
|
||||
/* XXX KS - check for misplaced blocks */
|
||||
for(i=0; i<num_blocks; i++) {
|
||||
if(block_array[i].bi_daddr
|
||||
&& ((char *)(block_array[i].bi_bp) - seg_buf) != (block_array[i].bi_daddr - seg_addr) * DEV_BSIZE
|
||||
&& datosn(&(fsp->fi_lfs),block_array[i].bi_daddr) == id)
|
||||
{
|
||||
if(debug > 1) {
|
||||
syslog(LOG_DEBUG,"seg %d, ino %d lbn %d, 0x%x != 0x%x (fixed)",
|
||||
block_array[i].bi_inode,
|
||||
block_array[i].bi_lbn,
|
||||
id, block_array[i].bi_daddr,
|
||||
seg_addr + ((char *)(block_array[i].bi_bp) - seg_buf)/DEV_BSIZE);
|
||||
}
|
||||
/*
|
||||
* XXX KS - have to be careful here about Inodes;
|
||||
* if lfs_bmapv shows them somewhere else in the
|
||||
* segment from where we thought, we need to reload
|
||||
* the *right* inode, not the first one in the block.
|
||||
*/
|
||||
if(block_array[i].bi_lbn == LFS_UNUSED_LBN) {
|
||||
dip = (struct dinode *)(seg_buf + (block_array[i].bi_daddr - seg_addr) * DEV_BSIZE);
|
||||
for(j=INOPB(lfsp)-1;j>=0;j--) {
|
||||
if(dip[j].di_u.inumber == block_array[i].bi_inode) {
|
||||
block_array[i].bi_bp = (char *)(dip+j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(j<0) {
|
||||
syslog(LOG_NOTICE, "lost inode %d in the shuffle! (blk %d)", block_array[i].bi_inode, block_array[i].bi_daddr);
|
||||
syslog(LOG_DEBUG, "inode numbers found were:");
|
||||
for(j=INOPB(lfsp)-1;j>=0;j--) {
|
||||
syslog(LOG_DEBUG, "%d", dip[j].di_u.inumber);
|
||||
}
|
||||
err(1,"lost inode");
|
||||
} else if(debug>1) {
|
||||
syslog(LOG_DEBUG,"Ino %d corrected to 0x%x+%d",
|
||||
block_array[i].bi_inode,
|
||||
block_array[i].bi_daddr,
|
||||
(int)((caddr_t)(block_array[i].bi_bp) - (caddr_t)seg_addr) % DEV_BSIZE);
|
||||
}
|
||||
} else {
|
||||
block_array[i].bi_bp = seg_buf + (block_array[i].bi_daddr - seg_addr) * DEV_BSIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update live bytes calc - XXX KS */
|
||||
slp->sl_bytes = 0;
|
||||
for(i=0; i<num_blocks; i++)
|
||||
if(block_array[i].bi_lbn == LFS_UNUSED_LBN)
|
||||
slp->sl_bytes += sizeof(struct dinode);
|
||||
else
|
||||
slp->sl_bytes += block_array[i].bi_size;
|
||||
|
||||
if(debug > 1) {
|
||||
syslog(LOG_DEBUG, "after bmapv still have %d blocks", num_blocks);
|
||||
if (num_blocks)
|
||||
syslog(LOG_DEBUG, "BLOCK INFOS");
|
||||
for (_bip = block_array, i=0; i < num_blocks; ++_bip, ++i) {
|
||||
PRINT_BINFO(_bip);
|
||||
lp = (u_long *)_bip->bi_bp;
|
||||
}
|
||||
}
|
||||
|
||||
++cleaner_stats.segs_cleaned;
|
||||
cleaner_stats.blocks_written += num_blocks;
|
||||
util = ((double)num_blocks / fsp->fi_lfs.lfs_ssize);
|
||||
@ -517,6 +681,7 @@ clean_segment(fsp, id)
|
||||
bp, clean_blocks) < 0) {
|
||||
syslog(LOG_WARNING,"clean_segment: lfs_markv failed: %m");
|
||||
++cleaner_stats.segs_error;
|
||||
free(block_array); /* XXX KS */
|
||||
return (-1);
|
||||
}
|
||||
num_blocks -= clean_blocks;
|
||||
@ -550,16 +715,16 @@ sig_report(sig)
|
||||
{
|
||||
double avg = 0.0;
|
||||
|
||||
syslog(LOG_DEBUG, "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",
|
||||
syslog(LOG_DEBUG, "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",
|
||||
"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);
|
||||
syslog(LOG_DEBUG, "\t\t%s%5.2f\n\t\t%s%5.2f\n",
|
||||
syslog(LOG_DEBUG, "\t\t%s%5.2f\n\t\t%s%5.2f",
|
||||
"util_tot ", cleaner_stats.util_tot,
|
||||
"util_sos ", cleaner_stats.util_sos);
|
||||
syslog(LOG_DEBUG, "\t\tavg util: %4.2f std dev: %9.6f\n",
|
||||
syslog(LOG_DEBUG, "\t\tavg util: %4.2f std dev: %9.6f",
|
||||
avg = cleaner_stats.util_tot / cleaner_stats.segs_cleaned,
|
||||
cleaner_stats.util_sos / cleaner_stats.segs_cleaned - avg * avg);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: library.c,v 1.10 1998/10/15 00:29:51 ross Exp $ */
|
||||
/* $NetBSD: library.c,v 1.11 1999/03/10 00:57:16 perseant Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
@ -38,7 +38,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)library.c 8.3 (Berkeley) 5/24/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: library.c,v 1.10 1998/10/15 00:29:51 ross Exp $");
|
||||
__RCSID("$NetBSD: library.c,v 1.11 1999/03/10 00:57:16 perseant Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -70,12 +70,16 @@ int bi_compare __P((const void *, const void *));
|
||||
int bi_toss __P((const void *, const void *, const void *));
|
||||
void get_ifile __P((FS_INFO *, int));
|
||||
int get_superblock __P((FS_INFO *, struct lfs *));
|
||||
int pseg_valid __P((FS_INFO *, SEGSUM *));
|
||||
void print_SEGSUM __P((struct lfs *, SEGSUM *));
|
||||
int pseg_valid __P((FS_INFO *, SEGSUM *, daddr_t));
|
||||
int pseg_size __P((daddr_t, FS_INFO *, SEGSUM *));
|
||||
void print_SEGSUM __P((struct lfs *, SEGSUM *, daddr_t));
|
||||
|
||||
extern int debug;
|
||||
extern u_long cksum __P((void *, size_t)); /* XXX */
|
||||
|
||||
static int ifile_fd;
|
||||
static int dev_fd;
|
||||
|
||||
/*
|
||||
* This function will get information on a a filesystem which matches
|
||||
* the name and type given. If a "name" is in a filesystem of the given
|
||||
@ -94,15 +98,20 @@ fs_getmntinfo(buf, name, type)
|
||||
return 0;
|
||||
|
||||
/* grab the filesystem info */
|
||||
if (statfs(name, *buf) < 0) {
|
||||
if (ifile_fd <= 0) {
|
||||
if (statfs(name, *buf) < 0) {
|
||||
free(*buf);
|
||||
return 0;
|
||||
}
|
||||
} else if(fstatfs(ifile_fd, *buf) < 0) {
|
||||
free(*buf);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* check to see if it's the one we want */
|
||||
if (strncmp(type, (*buf)->f_fstypename, MFSNAMELEN) ||
|
||||
strncmp(name, (*buf)->f_mntonname, MNAMELEN)) {
|
||||
/* "this is not the filesystem you're looking for */
|
||||
/* "this is not the filesystem you're looking for" */
|
||||
free(*buf);
|
||||
return 0;
|
||||
}
|
||||
@ -147,8 +156,12 @@ reread_fs_info(fsp, use_mmap)
|
||||
FS_INFO *fsp; /* IN: prointer fs_infos to reread */
|
||||
int use_mmap;
|
||||
{
|
||||
|
||||
if (statfs(fsp->fi_statfsp->f_mntonname, fsp->fi_statfsp)) {
|
||||
if (ifile_fd <= 0) {
|
||||
if (fstatfs(ifile_fd, fsp->fi_statfsp)) {
|
||||
syslog(LOG_ERR, "Exiting: reread_fs_info: fstatfs failed: %m");
|
||||
exit(1);
|
||||
}
|
||||
} else if (statfs(fsp->fi_statfsp->f_mntonname, fsp->fi_statfsp)) {
|
||||
syslog(LOG_ERR, "Exiting: reread_fs_info: statfs failed: %m");
|
||||
exit(1);
|
||||
}
|
||||
@ -165,19 +178,21 @@ get_superblock (fsp, sbp)
|
||||
{
|
||||
char mntfromname[MNAMELEN+1];
|
||||
char buf[LFS_SBPAD];
|
||||
int fid;
|
||||
|
||||
strcpy(mntfromname, "/dev/r");
|
||||
strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5);
|
||||
|
||||
if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) {
|
||||
syslog(LOG_WARNING,"get_superblock: bad open: %m");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
get(fid, LFS_LABELPAD, buf, LFS_SBPAD);
|
||||
if(dev_fd <= 0) {
|
||||
if ((dev_fd = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) {
|
||||
syslog(LOG_WARNING,"get_superblock: bad open: %m");
|
||||
return (-1);
|
||||
}
|
||||
} else
|
||||
lseek(dev_fd, 0, SEEK_SET);
|
||||
|
||||
get(dev_fd, LFS_LABELPAD, buf, LFS_SBPAD);
|
||||
memcpy(&(sbp->lfs_dlfs), buf, sizeof(struct dlfs));
|
||||
close (fid);
|
||||
/* close (fid); */
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -195,7 +210,7 @@ get_ifile (fsp, use_mmap)
|
||||
struct stat file_stat;
|
||||
caddr_t ifp;
|
||||
char *ifile_name;
|
||||
int count, fid;
|
||||
int count;
|
||||
|
||||
ifp = NULL;
|
||||
ifile_name = malloc(strlen(fsp->fi_statfsp->f_mntonname) +
|
||||
@ -203,27 +218,34 @@ get_ifile (fsp, use_mmap)
|
||||
strcat(strcat(strcpy(ifile_name, fsp->fi_statfsp->f_mntonname), "/"),
|
||||
IFILE_NAME);
|
||||
|
||||
if ((fid = open(ifile_name, O_RDWR, (mode_t)0)) < 0) {
|
||||
syslog(LOG_ERR, "Exiting: get_ifile: bad open: %m");
|
||||
exit(1);
|
||||
}
|
||||
if(ifile_fd <= 0) {
|
||||
/* XXX KS - Do we ever *write* to the ifile? */
|
||||
if ((ifile_fd = open(ifile_name, O_RDONLY, (mode_t)0)) < 0) {
|
||||
syslog(LOG_ERR, "Exiting: get_ifile: bad open: %m");
|
||||
exit(1);
|
||||
}
|
||||
} else
|
||||
lseek(ifile_fd, 0, SEEK_SET);
|
||||
|
||||
if (fstat (fid, &file_stat)) {
|
||||
if (fstat (ifile_fd, &file_stat)) {
|
||||
syslog(LOG_ERR, "Exiting: get_ifile: fstat failed: %m");
|
||||
exit(1);
|
||||
}
|
||||
fsp->fi_fs_tstamp = file_stat.st_mtimespec.tv_sec;
|
||||
|
||||
if (use_mmap && file_stat.st_size == fsp->fi_ifile_length) {
|
||||
(void) close(fid);
|
||||
/* (void) close(fid); */
|
||||
free(ifile_name); /* XXX KS */
|
||||
return;
|
||||
}
|
||||
|
||||
/* get the ifile */
|
||||
if (use_mmap) {
|
||||
if (fsp->fi_cip)
|
||||
munmap((caddr_t)fsp->fi_cip, fsp->fi_ifile_length);
|
||||
munmap((caddr_t)fsp->fi_cip, fsp->fi_ifile_length);
|
||||
/* XXX KS - Do we ever *write* to the ifile? */
|
||||
ifp = mmap ((caddr_t)0, file_stat.st_size,
|
||||
PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE, fid, (off_t)0);
|
||||
PROT_READ, MAP_FILE|MAP_PRIVATE, ifile_fd, (off_t)0);
|
||||
if (ifp == (caddr_t)(-1)) {
|
||||
syslog(LOG_ERR, "Exiting: get_ifile: mmap failed: %m");
|
||||
exit(1);
|
||||
@ -236,7 +258,7 @@ get_ifile (fsp, use_mmap)
|
||||
exit(1);
|
||||
}
|
||||
redo_read:
|
||||
count = read (fid, ifp, (size_t) file_stat.st_size);
|
||||
count = read (ifile_fd, ifp, (size_t) file_stat.st_size);
|
||||
|
||||
if (count < 0) {
|
||||
syslog(LOG_ERR, "Exiting: get_ifile: bad ifile read: %m");
|
||||
@ -244,7 +266,7 @@ redo_read:
|
||||
}
|
||||
else if (count < file_stat.st_size) {
|
||||
syslog(LOG_WARNING, "get_ifile: %m");
|
||||
if (lseek(fid, 0, SEEK_SET) < 0) {
|
||||
if (lseek(ifile_fd, 0, SEEK_SET) < 0) {
|
||||
syslog(LOG_ERR, "Exiting: get_ifile: bad ifile lseek: %m");
|
||||
exit(1);
|
||||
}
|
||||
@ -252,7 +274,7 @@ redo_read:
|
||||
}
|
||||
}
|
||||
fsp->fi_ifile_length = file_stat.st_size;
|
||||
close (fid);
|
||||
/* close (fid); */
|
||||
|
||||
fsp->fi_cip = (CLEANERINFO *)ifp;
|
||||
fsp->fi_segusep = (SEGUSE *)(ifp + CLEANSIZE(fsp));
|
||||
@ -271,6 +293,32 @@ redo_read:
|
||||
free (ifile_name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the size of the partial segment, in bytes.
|
||||
*/
|
||||
int
|
||||
pseg_size(pseg_addr, fsp, sp)
|
||||
daddr_t pseg_addr; /* base address of the segsum */
|
||||
FS_INFO *fsp; /* Filesystem info */
|
||||
SEGSUM *sp; /* the segsum */
|
||||
{
|
||||
int i, ssize = 0;
|
||||
struct lfs *lfsp;
|
||||
FINFO *fp;
|
||||
|
||||
lfsp = &fsp->fi_lfs;
|
||||
ssize = LFS_SUMMARY_SIZE
|
||||
+ howmany(sp->ss_ninos, INOPB(lfsp)) * lfsp->lfs_bsize;
|
||||
for (fp = (FINFO *)(sp + 1), i = 0; i < sp->ss_nfinfo; ++i) {
|
||||
ssize += (fp->fi_nblocks-1) * lfsp->lfs_bsize
|
||||
+ fp->fi_lastlength;
|
||||
fp = (FINFO *)(&fp->fi_blocks[fp->fi_nblocks]);
|
||||
}
|
||||
|
||||
return ssize;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will scan a segment and return a list of
|
||||
* <inode, blocknum> pairs which indicate which blocks were
|
||||
@ -293,7 +341,7 @@ lfs_segmapv(fsp, seg, seg_buf, blocks, bcount)
|
||||
struct lfs *lfsp;
|
||||
caddr_t s;
|
||||
daddr_t pseg_addr, seg_addr;
|
||||
int nelem, nblocks, nsegs, sumsize, i;
|
||||
int nelem, nblocks, nsegs, sumsize, i, ssize;
|
||||
time_t timestamp;
|
||||
|
||||
i = 0;
|
||||
@ -308,27 +356,29 @@ lfs_segmapv(fsp, seg, seg_buf, blocks, bcount)
|
||||
pseg_addr = seg_addr + (sup->su_flags & SEGUSE_SUPERBLOCK ? btodb(LFS_SBPAD) : 0);
|
||||
|
||||
if(debug > 1)
|
||||
syslog(LOG_DEBUG, "\tsegment buffer at: %p\tseg_addr 0x%x\n", s, seg_addr);
|
||||
syslog(LOG_DEBUG, "\tsegment buffer at: %p\tseg_addr 0x%x", s, seg_addr);
|
||||
|
||||
|
||||
*bcount = 0;
|
||||
for (nsegs = 0, timestamp = 0; nsegs < sup->su_nsums; nsegs++) {
|
||||
sp = (SEGSUM *)s;
|
||||
|
||||
nblocks = pseg_valid(fsp, sp);
|
||||
nblocks = pseg_valid(fsp, sp, pseg_addr);
|
||||
if (nblocks <= 0) {
|
||||
syslog(LOG_DEBUG, "Warning: invalid segment summary at 0x%x\n",
|
||||
syslog(LOG_DEBUG, "Warning: invalid segment summary at 0x%x",
|
||||
pseg_addr);
|
||||
break;
|
||||
*bcount = 0;
|
||||
return -1;
|
||||
/* break; */
|
||||
}
|
||||
|
||||
/* Check if we have hit old data */
|
||||
if (timestamp > ((SEGSUM*)s)->ss_create)
|
||||
if (timestamp > sp->ss_create)
|
||||
break;
|
||||
timestamp = ((SEGSUM*)s)->ss_create;
|
||||
timestamp = sp->ss_create;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
/* Verfiy size of summary block */
|
||||
/* Verify size of summary block */
|
||||
sumsize = sizeof(SEGSUM) +
|
||||
(sp->ss_ninos + INOPB(lfsp) - 1) / INOPB(lfsp);
|
||||
for (i = 0, fip = (FINFO *)(sp + 1); i < sp->ss_nfinfo; ++i) {
|
||||
@ -338,7 +388,7 @@ lfs_segmapv(fsp, seg, seg_buf, blocks, bcount)
|
||||
}
|
||||
if (sumsize > LFS_SUMMARY_SIZE) {
|
||||
syslog(LOG_ERR,
|
||||
"Segment %d summary block too big: %d\n",
|
||||
"Exiting: Segment %d summary block too big: %d\n",
|
||||
seg, sumsize);
|
||||
exit(1);
|
||||
}
|
||||
@ -352,18 +402,24 @@ lfs_segmapv(fsp, seg, seg_buf, blocks, bcount)
|
||||
}
|
||||
add_blocks(fsp, bip, bcount, sp, seg_buf, seg_addr, pseg_addr);
|
||||
add_inodes(fsp, bip, bcount, sp, seg_buf, seg_addr);
|
||||
pseg_addr += fsbtodb(lfsp, nblocks) +
|
||||
bytetoda(fsp, LFS_SUMMARY_SIZE);
|
||||
s += (nblocks << lfsp->lfs_bshift) + LFS_SUMMARY_SIZE;
|
||||
|
||||
ssize = pseg_size(pseg_addr, fsp, sp);
|
||||
s += ssize;
|
||||
pseg_addr += btodb(ssize); /* XXX was bytetoda(fsp,ssize) */
|
||||
}
|
||||
if(nsegs < sup->su_nsums) {
|
||||
syslog(LOG_NOTICE,"only %d segment summaries in seg %d (expected %d)",
|
||||
nsegs, seg, sup->su_nsums);
|
||||
goto err0;
|
||||
}
|
||||
qsort(bip, *bcount, sizeof(BLOCK_INFO), bi_compare);
|
||||
toss(bip, bcount, sizeof(BLOCK_INFO), bi_toss, NULL);
|
||||
|
||||
if(debug > 1) {
|
||||
syslog(LOG_DEBUG, "BLOCK INFOS\n");
|
||||
for (_bip = bip, i=0; i < *bcount; ++_bip, ++i)
|
||||
PRINT_BINFO(_bip);
|
||||
}
|
||||
syslog(LOG_DEBUG, "BLOCK INFOS");
|
||||
for (_bip = bip, i=0; i < *bcount; ++_bip, ++i)
|
||||
PRINT_BINFO(_bip);
|
||||
}
|
||||
|
||||
*blocks = bip;
|
||||
return (0);
|
||||
@ -397,7 +453,7 @@ add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr)
|
||||
u_long page_size;
|
||||
|
||||
if(debug > 1)
|
||||
syslog(LOG_DEBUG, "FILE INFOS\n");
|
||||
syslog(LOG_DEBUG, "FILE INFOS");
|
||||
|
||||
db_per_block = fsbtodb(&fsp->fi_lfs, 1);
|
||||
page_size = fsp->fi_lfs.lfs_bsize;
|
||||
@ -415,6 +471,7 @@ add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr)
|
||||
continue;
|
||||
dp = &(fip->fi_blocks[0]);
|
||||
for (j = 0; j < fip->fi_nblocks; j++, dp++) {
|
||||
/* Skip over intervening inode blocks */
|
||||
while (psegaddr == *iaddrp) {
|
||||
psegaddr += db_per_block;
|
||||
bp += page_size;
|
||||
@ -426,7 +483,10 @@ 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;
|
||||
if (fip->fi_lastlength == page_size) {
|
||||
|
||||
if (j < fip->fi_nblocks-1
|
||||
|| fip->fi_lastlength == page_size)
|
||||
{
|
||||
bip->bi_size = page_size;
|
||||
psegaddr += db_per_block;
|
||||
bp += page_size;
|
||||
@ -435,10 +495,10 @@ add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr)
|
||||
numfrags(&(fsp->fi_lfs),
|
||||
fip->fi_lastlength));
|
||||
|
||||
if(debug > 1)
|
||||
syslog(LOG_DEBUG, "lastlength, frags: %d, %d, %d\n",
|
||||
fip->fi_lastlength, db_frag,
|
||||
bytetoda(fsp, db_frag));
|
||||
if(debug > 1) {
|
||||
syslog(LOG_DEBUG, "lastlength, frags: %d, %d",
|
||||
fip->fi_lastlength, db_frag);
|
||||
}
|
||||
|
||||
bip->bi_size = fip->fi_lastlength;
|
||||
bp += fip->fi_lastlength;
|
||||
@ -479,7 +539,7 @@ add_inodes (fsp, bip, countp, sp, seg_buf, seg_addr)
|
||||
lfsp = &fsp->fi_lfs;
|
||||
|
||||
if(debug > 1)
|
||||
syslog(LOG_DEBUG, "INODES:\n");
|
||||
syslog(LOG_DEBUG, "INODES:");
|
||||
|
||||
daddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE);
|
||||
for (i = 0; i < sp->ss_ninos; ++i) {
|
||||
@ -496,6 +556,7 @@ add_inodes (fsp, bip, countp, sp, seg_buf, seg_addr)
|
||||
bp->bi_daddr = *daddrp;
|
||||
bp->bi_bp = di;
|
||||
bp->bi_segcreate = sp->ss_create;
|
||||
bp->bi_size = i; /* XXX KS - kludge */
|
||||
|
||||
if (inum == LFS_IFILE_INUM) {
|
||||
bp->bi_version = 1; /* Ifile version should be 1 */
|
||||
@ -517,25 +578,32 @@ add_inodes (fsp, bip, countp, sp, seg_buf, seg_addr)
|
||||
/*
|
||||
* Checks the summary checksum and the data checksum to determine if the
|
||||
* segment is valid or not. Returns the size of the partial segment if it
|
||||
* is valid, * and 0 otherwise. Use dump_summary to figure out size of the
|
||||
* is valid, and 0 otherwise. Use dump_summary to figure out size of the
|
||||
* the partial as well as whether or not the checksum is valid.
|
||||
*/
|
||||
int
|
||||
pseg_valid (fsp, ssp)
|
||||
pseg_valid (fsp, ssp, addr)
|
||||
FS_INFO *fsp; /* pointer to file system info */
|
||||
SEGSUM *ssp; /* pointer to segment summary block */
|
||||
daddr_t addr; /* address of the summary block on disk */
|
||||
{
|
||||
int nblocks;
|
||||
#if 0
|
||||
caddr_t p;
|
||||
int i, nblocks;
|
||||
int i;
|
||||
u_long *datap;
|
||||
#endif
|
||||
|
||||
if (ssp->ss_magic != SS_MAGIC)
|
||||
if (ssp->ss_magic != SS_MAGIC) {
|
||||
syslog(LOG_DEBUG, "Bad magic number: 0x%x instead of 0x%x", ssp->ss_magic, SS_MAGIC);
|
||||
return(0);
|
||||
}
|
||||
|
||||
if ((nblocks = dump_summary(&fsp->fi_lfs, ssp, 0, NULL)) <= 0 ||
|
||||
if ((nblocks = dump_summary(&fsp->fi_lfs, ssp, 0, NULL, addr)) <= 0 ||
|
||||
nblocks > fsp->fi_lfs.lfs_ssize - 1)
|
||||
return(0);
|
||||
|
||||
#if 0
|
||||
/* check data/inode block(s) checksum too */
|
||||
datap = (u_long *)malloc(nblocks * sizeof(u_long));
|
||||
p = (caddr_t)ssp + LFS_SUMMARY_SIZE;
|
||||
@ -543,9 +611,11 @@ pseg_valid (fsp, ssp)
|
||||
datap[i] = *((u_long *)p);
|
||||
p += fsp->fi_lfs.lfs_bsize;
|
||||
}
|
||||
if (cksum ((void *)datap, nblocks * sizeof(u_long)) != ssp->ss_datasum)
|
||||
return (0);
|
||||
|
||||
if (cksum ((void *)datap, nblocks * sizeof(u_long)) != ssp->ss_datasum) {
|
||||
syslog(LOG_DEBUG, "Bad data checksum");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return (nblocks);
|
||||
}
|
||||
|
||||
@ -562,7 +632,6 @@ mmap_segment (fsp, segment, segbuf, use_mmap)
|
||||
int use_mmap; /* mmap instead of read */
|
||||
{
|
||||
struct lfs *lfsp;
|
||||
int fid; /* fildes for file system device */
|
||||
daddr_t seg_daddr; /* base disk address of segment */
|
||||
off_t seg_byte;
|
||||
size_t ssize;
|
||||
@ -578,24 +647,25 @@ mmap_segment (fsp, segment, segbuf, use_mmap)
|
||||
strcpy(mntfromname, "/dev/r");
|
||||
strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5);
|
||||
|
||||
if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) {
|
||||
syslog(LOG_WARNING,"mmap_segment: bad open: %m");
|
||||
return (-1);
|
||||
}
|
||||
if(dev_fd <= 0) {
|
||||
if ((dev_fd = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) {
|
||||
syslog(LOG_WARNING,"mmap_segment: bad open: %m");
|
||||
return (-1);
|
||||
}
|
||||
} else
|
||||
lseek(dev_fd, 0, SEEK_SET);
|
||||
|
||||
if (use_mmap) {
|
||||
*segbuf = mmap ((caddr_t)0, seg_size(lfsp), PROT_READ,
|
||||
MAP_FILE|MAP_SHARED, fid, seg_byte);
|
||||
MAP_FILE|MAP_SHARED, dev_fd, seg_byte);
|
||||
if (*(long *)segbuf < 0) {
|
||||
syslog(LOG_WARNING,"mmap_segment: mmap failed: %m");
|
||||
return (0);
|
||||
}
|
||||
} else {
|
||||
if(debug > 1)
|
||||
syslog(LOG_DEBUG, "mmap_segment\tseg_daddr: %lu\t"
|
||||
"seg_size: %lu\tseg_offset: %qu\n",
|
||||
(u_long)seg_daddr, (u_long)ssize,
|
||||
(long long)seg_byte);
|
||||
syslog(LOG_DEBUG, "mmap_segment\tseg_daddr: %lu\tseg_size: %lu\tseg_offset: %qu",
|
||||
(u_long)seg_daddr, (u_long)ssize, seg_byte);
|
||||
|
||||
/* malloc the space for the buffer */
|
||||
*segbuf = malloc(ssize);
|
||||
@ -605,19 +675,18 @@ mmap_segment (fsp, segment, segbuf, use_mmap)
|
||||
}
|
||||
|
||||
/* read the segment data into the buffer */
|
||||
if (lseek (fid, seg_byte, SEEK_SET) != seg_byte) {
|
||||
if (lseek (dev_fd, seg_byte, SEEK_SET) != seg_byte) {
|
||||
syslog(LOG_WARNING,"mmap_segment: bad lseek: %m");
|
||||
free(*segbuf);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (read (fid, *segbuf, ssize) != ssize) {
|
||||
if (read (dev_fd, *segbuf, ssize) != ssize) {
|
||||
syslog(LOG_WARNING,"mmap_segment: bad read: %m");
|
||||
free(*segbuf);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
close (fid);
|
||||
/* close (fid); */
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -638,12 +707,13 @@ munmap_segment (fsp, seg_buf, use_mmap)
|
||||
* USEFUL DEBUGGING TOOLS:
|
||||
*/
|
||||
void
|
||||
print_SEGSUM (lfsp, p)
|
||||
print_SEGSUM (lfsp, p, addr)
|
||||
struct lfs *lfsp;
|
||||
SEGSUM *p;
|
||||
daddr_t addr;
|
||||
{
|
||||
if (p)
|
||||
(void) dump_summary(lfsp, p, DUMP_ALL, NULL);
|
||||
(void) dump_summary(lfsp, p, DUMP_ALL, NULL, addr);
|
||||
else
|
||||
syslog(LOG_DEBUG, "0x0");
|
||||
}
|
||||
@ -675,8 +745,12 @@ bi_compare(a, b)
|
||||
}
|
||||
if ((diff = (int)(ba->bi_segcreate - bb->bi_segcreate)))
|
||||
return (diff);
|
||||
diff = (int)(ba->bi_daddr - bb->bi_daddr);
|
||||
return (diff);
|
||||
if ((diff = (int)(ba->bi_daddr - bb->bi_daddr)))
|
||||
return (diff);
|
||||
if(ba->bi_inode != LFS_IFILE_INUM)
|
||||
syslog(LOG_DEBUG,"bi_compare: using kludge on ino %d!", ba->bi_inode);
|
||||
diff = ba->bi_size - bb->bi_size;
|
||||
return diff;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: misc.c,v 1.4 1998/10/15 00:29:51 ross Exp $ */
|
||||
/* $NetBSD: misc.c,v 1.5 1999/03/10 00:57:16 perseant Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
@ -38,7 +38,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "from: @(#)misc.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: misc.c,v 1.4 1998/10/15 00:29:51 ross Exp $");
|
||||
__RCSID("$NetBSD: misc.c,v 1.5 1999/03/10 00:57:16 perseant Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -77,8 +77,7 @@ get(fd, off, p, len)
|
||||
exit(1);
|
||||
}
|
||||
if (rbytes != len) {
|
||||
syslog(LOG_ERR, "Exiting: %s: short read (%d, not %d)",
|
||||
special, rbytes, (int)len);
|
||||
syslog(LOG_ERR, "Exiting: %s: short read (%d, not %d)", special, rbytes, len);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: print.c,v 1.6 1998/10/15 00:29:51 ross Exp $ */
|
||||
/* $NetBSD: print.c,v 1.7 1999/03/10 00:57:16 perseant Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
@ -38,7 +38,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "from: @(#)print.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: print.c,v 1.6 1998/10/15 00:29:51 ross Exp $");
|
||||
__RCSID("$NetBSD: print.c,v 1.7 1999/03/10 00:57:16 perseant Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -65,18 +65,24 @@ extern u_long cksum __P((void *, size_t)); /* XXX */
|
||||
* for empty segment or corrupt segment.
|
||||
* Returns a pointer to the array of inode addresses.
|
||||
*/
|
||||
|
||||
int
|
||||
dump_summary(lfsp, sp, flags, iaddrp)
|
||||
dump_summary(lfsp, sp, flags, iaddrp, addr)
|
||||
struct lfs *lfsp;
|
||||
SEGSUM *sp;
|
||||
u_long flags;
|
||||
daddr_t **iaddrp;
|
||||
daddr_t addr;
|
||||
{
|
||||
int i, j, numblocks;
|
||||
daddr_t *dp;
|
||||
|
||||
int i, j, blk, numblocks, accino=0;
|
||||
daddr_t *dp, ddp, *idp;
|
||||
u_long *datap;
|
||||
int size;
|
||||
FINFO *fp;
|
||||
int ck;
|
||||
u_long ck;
|
||||
|
||||
blk=0;
|
||||
datap = (u_long *)malloc((lfsp->lfs_ssize*lfsp->lfs_frag) * sizeof(u_long));
|
||||
|
||||
if (sp->ss_sumsum != (ck = cksum(&sp->ss_datasum,
|
||||
LFS_SUMMARY_SIZE - sizeof(sp->ss_sumsum))))
|
||||
@ -98,16 +104,39 @@ dump_summary(lfsp, sp, flags, iaddrp)
|
||||
if (flags & DUMP_INODE_ADDRS)
|
||||
syslog(LOG_DEBUG, " Inode addresses:");
|
||||
|
||||
dp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE);
|
||||
for (--dp, i = 0; i < sp->ss_ninos; --dp)
|
||||
if (flags & DUMP_INODE_ADDRS) {
|
||||
idp = dp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE);
|
||||
--idp;
|
||||
for (--dp, i = 0; i < howmany(sp->ss_ninos,INOPB(lfsp)); --dp) {
|
||||
if (flags & DUMP_INODE_ADDRS)
|
||||
syslog(LOG_DEBUG, "\t0x%lx", (u_long)*dp);
|
||||
} else
|
||||
++i;
|
||||
if (iaddrp)
|
||||
*iaddrp = ++dp;
|
||||
++i;
|
||||
}
|
||||
if (iaddrp) {
|
||||
*iaddrp = dp;
|
||||
}
|
||||
|
||||
ddp = addr + LFS_SUMMARY_SIZE/DEV_BSIZE;
|
||||
for (fp = (FINFO *)(sp + 1), i = 0; i < sp->ss_nfinfo; ++i) {
|
||||
/* Add any intervening Inode blocks to our checksum array */
|
||||
/* printf("finfo %d: ddp=%lx, *idp=%lx\n",i,ddp,*idp); */
|
||||
while(ddp == *idp) {
|
||||
/* printf(" [ino %lx]",ddp); */
|
||||
datap[blk++] = *(u_long*)((caddr_t)sp + (ddp-addr)*DEV_BSIZE);
|
||||
--idp;
|
||||
ddp += lfsp->lfs_bsize/DEV_BSIZE;
|
||||
accino++;
|
||||
}
|
||||
for(j=0;j<fp->fi_nblocks;j++) {
|
||||
if(j==fp->fi_nblocks-1) {
|
||||
size = fp->fi_lastlength/DEV_BSIZE;
|
||||
/* printf(" %lx:%d",ddp,size); */
|
||||
} else {
|
||||
size = lfsp->lfs_bsize/DEV_BSIZE;
|
||||
/* printf(" %lx/%d",ddp,size); */
|
||||
}
|
||||
datap[blk++] = *(u_long*)((caddr_t)sp + (ddp-addr)*DEV_BSIZE);
|
||||
ddp += size;
|
||||
}
|
||||
numblocks += fp->fi_nblocks;
|
||||
if (flags & DUMP_FINFOS) {
|
||||
syslog(LOG_DEBUG, " %s%d version %d nblocks %d\n",
|
||||
@ -117,11 +146,37 @@ dump_summary(lfsp, sp, flags, iaddrp)
|
||||
for (j = 0; j < fp->fi_nblocks; j++, dp++) {
|
||||
syslog(LOG_DEBUG, "\t%d", *dp);
|
||||
}
|
||||
fp = (FINFO *)dp;
|
||||
} else {
|
||||
fp = (FINFO *)(&fp->fi_blocks[fp->fi_nblocks]);
|
||||
}
|
||||
} else
|
||||
dp = &fp->fi_blocks[fp->fi_nblocks];
|
||||
fp = (FINFO *)dp;
|
||||
/* printf("\n"); */
|
||||
}
|
||||
/* Add lagging inode blocks too */
|
||||
/* printf("end: ddp=%lx, *idp=%lx\n",ddp,*idp); */
|
||||
while(*idp >= ddp && accino < howmany(sp->ss_ninos,INOPB(lfsp))) {
|
||||
ddp = *idp;
|
||||
/* printf(" [ino %lx]",ddp); */
|
||||
datap[blk++] = *(u_long*)((caddr_t)sp + (ddp-addr)*DEV_BSIZE);
|
||||
--idp;
|
||||
accino++;
|
||||
}
|
||||
/* printf("\n"); */
|
||||
|
||||
if(accino != howmany(sp->ss_ninos,lfsp->lfs_inopb)) {
|
||||
syslog(LOG_DEBUG,"Oops, given %d inodes got %d\n", howmany(sp->ss_ninos,lfsp->lfs_inopb), accino);
|
||||
}
|
||||
if(blk!=numblocks) {
|
||||
syslog(LOG_DEBUG,"Oops, blk=%d numblocks=%d\n",blk,numblocks);
|
||||
}
|
||||
/* check data/inode block(s) checksum too */
|
||||
if ((ck=cksum ((void *)datap, numblocks * sizeof(u_long))) != sp->ss_datasum) {
|
||||
syslog(LOG_DEBUG, "Bad data checksum: given %lu, got %lu",
|
||||
(unsigned long)sp->ss_datasum, ck);
|
||||
free(datap);
|
||||
return 0;
|
||||
}
|
||||
free(datap);
|
||||
|
||||
return (numblocks);
|
||||
}
|
||||
|
||||
@ -145,6 +200,9 @@ dump_super(lfsp)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(debug < 2)
|
||||
return;
|
||||
|
||||
syslog(LOG_DEBUG,"%s0x%X\t%s0x%X\t%s%d\t%s%d\n",
|
||||
"magic ", lfsp->lfs_magic,
|
||||
"version ", lfsp->lfs_version,
|
||||
|
Loading…
Reference in New Issue
Block a user