diff options
39 files changed, 2550 insertions, 1874 deletions
diff --git a/libexec/lfs_cleanerd/clean.h b/libexec/lfs_cleanerd/clean.h index bb258dc0559..64361c91c56 100644 --- a/libexec/lfs_cleanerd/clean.h +++ b/libexec/lfs_cleanerd/clean.h @@ -1,4 +1,4 @@ -/* $NetBSD: clean.h,v 1.10 2001/02/04 22:12:47 christos Exp $ */ +/* $NetBSD: clean.h,v 1.11 2001/07/13 20:30:21 perseant Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -84,7 +84,6 @@ typedef struct fs_info { CLEANERINFO *fi_cip; /* Cleaner info from ifile */ SEGUSE *fi_segusep; /* segment usage table (from ifile) */ IFILE *fi_ifilep; /* ifile table (from ifile) */ - 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 */ @@ -94,34 +93,26 @@ typedef struct fs_info { * XXX: size (in bytes) of a segment * should lfs_bsize be fsbtodb(fs,1), blksize(fs), or lfs_dsize? */ -#define seg_size(fs) ((fs)->lfs_ssize << (fs)->lfs_bshift) - -/* daddr -> byte offset */ -#define datobyte(fs, da) (((off_t)(da)) << (fs)->fi_daddr_shift) -#define bytetoda(fs, byte) ((byte) >> (fs)->fi_daddr_shift) +#define seg_size(fs) fsbtob((fs), segtod((fs), 1)) #define CLEANSIZE(fsp) (fsp->fi_lfs.lfs_cleansz << fsp->fi_lfs.lfs_bshift) #define SEGTABSIZE(fsp) (fsp->fi_lfs.lfs_segtabsz << fsp->fi_lfs.lfs_bshift) -#define IFILE_ENTRY(fs, if, i) \ - ((IFILE *)((caddr_t)(if) + ((i) / (fs)->lfs_ifpb << (fs)->lfs_bshift)) \ - + (i) % (fs)->lfs_ifpb) - -#define SEGUSE_ENTRY(fs, su, i) \ - ((SEGUSE *)((caddr_t)(su) + (fs)->lfs_bsize * ((i) / (fs)->lfs_sepb)) +\ - (i) % (fs)->lfs_sepb) - -__BEGIN_DECLS -int dump_summary __P((struct lfs *, SEGSUM *, u_long, daddr_t **, daddr_t)); -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)); -int lfs_segmapv __P((FS_INFO *, int, caddr_t, BLOCK_INFO **, int *)); -int mmap_segment __P((FS_INFO *, int, caddr_t *, int)); -void munmap_segment __P((FS_INFO *, caddr_t, int)); -void reread_fs_info __P((FS_INFO *, int)); -void toss __P((void *, int *, size_t, - int (*)(const void *, const void *, const void *), void *)); +#define IFILE_ENTRY(fs, ife, i) \ + ((fs)->lfs_version == 1 ? \ + (IFILE *)((IFILE_V1 *)((caddr_t)(ife) + ((i) / (fs)->lfs_ifpb <<\ + (fs)->lfs_bshift)) + (i) % (fs)->lfs_ifpb) : \ + ((IFILE *)((caddr_t)(ife) + ((i) / (fs)->lfs_ifpb << \ + (fs)->lfs_bshift)) + (i) % (fs)->lfs_ifpb)) + +#define SEGUSE_ENTRY(fs, su, i) \ + ((fs)->lfs_version == 1 ? \ + (SEGUSE *)((SEGUSE_V1 *)((caddr_t)(su) + (fs)->lfs_bsize * \ + ((i) / (fs)->lfs_sepb)) + \ + (i) % (fs)->lfs_sepb) : \ + ((SEGUSE *)((caddr_t)(su) + (fs)->lfs_bsize * \ + ((i) / (fs)->lfs_sepb)) + \ + (i) % (fs)->lfs_sepb)) /* * USEFUL DEBUGGING FUNCTIONS: @@ -155,8 +146,20 @@ void toss __P((void *, int *, size_t, ctime((time_t *)&(sup)->su_lastmod)); \ } -void dump_super __P((struct lfs *)); -void dump_cleaner_info __P((void *)); -void print_SEGSUM __P(( struct lfs *, SEGSUM *, daddr_t)); -void print_CLEANERINFO __P((CLEANERINFO *)); +__BEGIN_DECLS +int dump_summary(struct lfs *, SEGSUM *, u_long, daddr_t **, daddr_t); +int fs_getmntinfo(struct statfs **, char *, const char *); +void get(int, off_t, void *, size_t); +FS_INFO *get_fs_info(struct statfs *, int); +int lfs_segmapv(FS_INFO *, int, caddr_t, BLOCK_INFO **, int *); +int mmap_segment(FS_INFO *, int, caddr_t *, int); +void munmap_segment(FS_INFO *, caddr_t, int); +void reread_fs_info(FS_INFO *, int); +void toss __P((void *, int *, size_t, + int (*)(const void *, const void *, const void *), void *)); + +void dump_super(struct lfs *); +void dump_cleaner_info(void *); +void print_SEGSUM(struct lfs *, SEGSUM *, daddr_t); +void print_CLEANERINFO(CLEANERINFO *); __END_DECLS diff --git a/libexec/lfs_cleanerd/cleanerd.c b/libexec/lfs_cleanerd/cleanerd.c index 988589e4a78..c55506cb88c 100644 --- a/libexec/lfs_cleanerd/cleanerd.c +++ b/libexec/lfs_cleanerd/cleanerd.c @@ -1,4 +1,4 @@ -/* $NetBSD: cleanerd.c,v 1.30 2001/02/04 22:12:47 christos Exp $ */ +/* $NetBSD: cleanerd.c,v 1.31 2001/07/13 20:30:21 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.30 2001/02/04 22:12:47 christos Exp $"); +__RCSID("$NetBSD: cleanerd.c,v 1.31 2001/07/13 20:30:21 perseant Exp $"); #endif #endif /* not lint */ @@ -109,24 +109,24 @@ typedef struct { #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)); -int lfs_bmapv __P((fsid_t *, BLOCK_INFO *, int)); -int lfs_markv __P((fsid_t *, BLOCK_INFO *, int)); +int lfs_segwait(fsid_t *, struct timeval *); +int lfs_segclean(fsid_t *, u_long); +int lfs_bmapv(fsid_t *, BLOCK_INFO *, int); +int lfs_markv(fsid_t *, BLOCK_INFO *, int); /* function prototypes */ -int bi_tossold __P((const void *, const void *, const void *)); -int choose_segments __P((FS_INFO *, struct seglist *, - unsigned long (*)(FS_INFO *, SEGUSE *))); -void clean_fs __P((FS_INFO *, unsigned long (*)(FS_INFO *, SEGUSE *), int, long)); -int clean_loop __P((FS_INFO *, int, long)); -int add_segment __P((FS_INFO *, struct seglist *, SEGS_AND_BLOCKS *)); -int clean_segments __P((FS_INFO *, SEGS_AND_BLOCKS *)); -unsigned long cost_benefit __P((FS_INFO *, SEGUSE *)); -int cost_compare __P((const void *, const void *)); -void sig_report __P((int)); -void just_exit __P((int)); -int main __P((int, char *[])); +int bi_tossold(const void *, const void *, const void *); +int choose_segments(FS_INFO *, struct seglist *, + unsigned long (*)(FS_INFO *, SEGUSE *)); +void clean_fs(FS_INFO *, unsigned long (*)(FS_INFO *, SEGUSE *), int, long); +int clean_loop(FS_INFO *, int, long); +int add_segment(FS_INFO *, struct seglist *, SEGS_AND_BLOCKS *); +int clean_segments(FS_INFO *, SEGS_AND_BLOCKS *); +unsigned long cost_benefit(FS_INFO *, SEGUSE *); +int cost_compare(const void *, const void *); +void sig_report(int); +void just_exit(int); +int main(int, char *[]); /* * Cleaning Cost Functions: @@ -141,9 +141,7 @@ int main __P((int, char *[])); */ unsigned long -cost_benefit(fsp, su) - FS_INFO *fsp; /* file system information */ - SEGUSE *su; +cost_benefit(FS_INFO *fsp, SEGUSE *su) { struct lfs *lfsp; struct timeval t; @@ -180,9 +178,7 @@ cost_benefit(fsp, su) } int -main(argc, argv) - int argc; - char *argv[]; +main(int argc, char **argv) { FS_INFO *fsp; struct statfs *lstatfsp; /* file system stats */ @@ -340,24 +336,21 @@ main(argc, argv) /* return the number of segments cleaned */ int -clean_loop(fsp, nsegs, options) - FS_INFO *fsp; /* file system information */ - int nsegs; - long options; +clean_loop(FS_INFO *fsp, int nsegs, long options) { struct lfs *lfsp; double loadavg[MAXLOADS]; time_t now; u_long max_free_segs; - u_long db_per_seg; + u_long fsb_per_seg; lfsp = &fsp->fi_lfs; /* * Compute the maximum possible number of free segments, given the * number of free blocks. */ - db_per_seg = fsbtodb(lfsp, lfsp->lfs_ssize); - max_free_segs = fsp->fi_cip->bfree / db_per_seg + lfsp->lfs_minfreeseg; + fsb_per_seg = segtod(lfsp, 1); + max_free_segs = fsp->fi_cip->bfree / fsb_per_seg + lfsp->lfs_minfreeseg; /* * We will clean if there are not enough free blocks or total clean @@ -366,16 +359,16 @@ clean_loop(fsp, nsegs, options) now = time((time_t *)NULL); if(debug > 1) { - syslog(LOG_DEBUG, "db_per_seg = %lu bfree = %u avail = %d," - " bfree = %u, ", db_per_seg, fsp->fi_cip->bfree, + syslog(LOG_DEBUG, "fsb_per_seg = %lu bfree = %u avail = %d," + " bfree = %u, ", fsb_per_seg, fsp->fi_cip->bfree, fsp->fi_cip->avail, fsp->fi_cip->bfree); syslog(LOG_DEBUG, "clean segs = %d, max_free_segs = %ld", fsp->fi_cip->clean, max_free_segs); } - if ((fsp->fi_cip->bfree - fsp->fi_cip->avail > db_per_seg && - fsp->fi_cip->avail < (long)db_per_seg && - fsp->fi_cip->bfree > (long)db_per_seg) || + if ((fsp->fi_cip->bfree - fsp->fi_cip->avail > fsb_per_seg && + fsp->fi_cip->avail < (long)fsb_per_seg && + fsp->fi_cip->bfree > (long)fsb_per_seg) || (fsp->fi_cip->clean < max_free_segs && (fsp->fi_cip->clean <= lfsp->lfs_minfreeseg || fsp->fi_cip->clean < max_free_segs * BUSY_LIM))) @@ -444,9 +437,9 @@ clean_loop(fsp, nsegs, options) } } if (debug > 1) { - if (fsp->fi_cip->bfree - fsp->fi_cip->avail <= db_per_seg) + if (fsp->fi_cip->bfree - fsp->fi_cip->avail <= fsb_per_seg) syslog(LOG_DEBUG, "condition 1 false"); - if (fsp->fi_cip->avail >= (long)db_per_seg) + if (fsp->fi_cip->avail >= (long)fsb_per_seg) syslog(LOG_DEBUG, "condition 2 false"); if (fsp->fi_cip->clean >= max_free_segs) syslog(LOG_DEBUG, "condition 3 false"); @@ -462,14 +455,11 @@ clean_loop(fsp, nsegs, options) void -clean_fs(fsp, cost_func, nsegs, options) - FS_INFO *fsp; /* file system information */ - unsigned long (*cost_func) __P((FS_INFO *, SEGUSE *)); - int nsegs; - long options; +clean_fs(FS_INFO *fsp, unsigned long (*cost_func)(FS_INFO *, SEGUSE *), + int nsegs, long options) { struct seglist *segs, *sp; - long int to_clean, cleaned_bytes, seg_size; + long int to_clean, cleaned_bytes; unsigned long i, j, total; struct rusage ru; fsid_t *fsidp; @@ -477,7 +467,6 @@ clean_fs(fsp, cost_func, nsegs, options) SEGS_AND_BLOCKS *sbp; fsidp = &fsp->fi_statfsp->f_fsid; - seg_size = (1 << fsp->fi_lfs.lfs_segshift); if ((segs = malloc(fsp->fi_lfs.lfs_nseg * sizeof(struct seglist))) == NULL) { @@ -589,9 +578,7 @@ clean_fs(fsp, cost_func, nsegs, options) * cost/benefit than any utilized segment. */ int -cost_compare(a, b) - const void *a; - const void *b; +cost_compare(const void *a, const void *b) { return ((struct seglist *)b)->sl_cost < ((struct seglist *)a)->sl_cost ? -1 : 1; } @@ -602,10 +589,7 @@ cost_compare(a, b) * filled in. */ int -choose_segments(fsp, seglist, cost_func) - FS_INFO *fsp; - struct seglist *seglist; - unsigned long (*cost_func) __P((FS_INFO *, SEGUSE *)); +choose_segments(FS_INFO *fsp, struct seglist *seglist, unsigned long (*cost_func)(FS_INFO *, SEGUSE *)) { struct lfs *lfsp; struct seglist *sp; @@ -663,10 +647,7 @@ choose_segments(fsp, seglist, cost_func) * in preparation for sending through lfs_markv. */ int -add_segment(fsp, slp, sbp) - FS_INFO *fsp; - struct seglist *slp; - SEGS_AND_BLOCKS *sbp; +add_segment(FS_INFO *fsp, struct seglist *slp, SEGS_AND_BLOCKS *sbp) { int id = slp->sl_id; BLOCK_INFO *tba, *_bip; @@ -684,7 +665,7 @@ add_segment(fsp, slp, sbp) lfsp = &fsp->fi_lfs; sp = SEGUSE_ENTRY(lfsp, fsp->fi_segusep, id); - seg_addr = sntoda(lfsp,id); + seg_addr = sntod(lfsp,id); error = 0; tba = NULL; @@ -718,7 +699,7 @@ add_segment(fsp, slp, sbp) "add_segment: lfs_segmapv failed for segment %d", id); goto out; } - cleaner_stats.blocks_read += fsp->fi_lfs.lfs_ssize; + cleaner_stats.blocks_read += segtod(lfsp, 1); if (debug > 1) syslog(LOG_DEBUG, "lfs_segmapv returned %d blocks", num_blocks); @@ -747,8 +728,8 @@ add_segment(fsp, slp, sbp) /* XXX KS - check for misplaced blocks */ for(i=0; i<num_blocks; i++) { if(tba[i].bi_daddr - && ((char *)(tba[i].bi_bp) - seg_buf) != (tba[i].bi_daddr - seg_addr) * DEV_BSIZE - && datosn(&(fsp->fi_lfs), tba[i].bi_daddr) == id) + && ((char *)(tba[i].bi_bp) - seg_buf) != fsbtob(lfsp, tba[i].bi_daddr - seg_addr) + && dtosn(&(fsp->fi_lfs), tba[i].bi_daddr) == id) { if(debug > 1) { syslog(LOG_DEBUG, "seg %d, ino %d lbn %d, 0x%x != 0x%lx (fixed)", @@ -756,7 +737,7 @@ add_segment(fsp, slp, sbp) tba[i].bi_inode, tba[i].bi_lbn, tba[i].bi_daddr, - (long)seg_addr + ((char *)(tba[i].bi_bp) - seg_buf)/DEV_BSIZE); + (long)seg_addr + btofsb(lfsp, (char *)(tba[i].bi_bp) - seg_buf)); } /* * XXX KS - have to be careful here about Inodes; @@ -765,7 +746,7 @@ add_segment(fsp, slp, sbp) * the *right* inode, not the first one in the block. */ if(tba[i].bi_lbn == LFS_UNUSED_LBN) { - dip = (struct dinode *)(seg_buf + (tba[i].bi_daddr - seg_addr) * DEV_BSIZE); + dip = (struct dinode *)(seg_buf + fsbtob(lfsp, tba[i].bi_daddr - seg_addr)); for(j=INOPB(lfsp)-1;j>=0;j--) { if(dip[j].di_u.inumber == tba[i].bi_inode) { tba[i].bi_bp = (char *)(dip+j); @@ -785,13 +766,12 @@ add_segment(fsp, slp, sbp) } err(1,"lost inode"); } else if (debug > 1) { - syslog(LOG_DEBUG,"Ino %d corrected to 0x%x+%d", + syslog(LOG_DEBUG,"Ino %d corrected to 0x%x", tba[i].bi_inode, - tba[i].bi_daddr, - (int)((caddr_t)(tba[i].bi_bp) - (caddr_t)(long)seg_addr) % DEV_BSIZE); + tba[i].bi_daddr); } } else { - tba[i].bi_bp = seg_buf + (tba[i].bi_daddr - seg_addr) * DEV_BSIZE; + tba[i].bi_bp = seg_buf + fsbtob(lfsp, tba[i].bi_daddr - seg_addr); } } } @@ -865,9 +845,7 @@ add_segment(fsp, slp, sbp) /* Call markv and clean up */ int -clean_segments(fsp, sbp) - FS_INFO *fsp; - SEGS_AND_BLOCKS *sbp; +clean_segments(FS_INFO *fsp, SEGS_AND_BLOCKS *sbp) { int maxblocks, clean_blocks; BLOCK_INFO *bp; @@ -878,7 +856,7 @@ clean_segments(fsp, sbp) cleaner_stats.segs_cleaned += sbp->nsegs; cleaner_stats.blocks_written += sbp->nb; - util = ((double)sbp->nb / fsp->fi_lfs.lfs_ssize); + util = ((double)sbp->nb / segtod(&fsp->fi_lfs, 1)); cleaner_stats.util_tot += util; cleaner_stats.util_sos += util * util; if (do_small) @@ -911,22 +889,18 @@ clean_segments(fsp, sbp) int -bi_tossold(client, a, b) - const void *client; - const void *a; - const void *b; +bi_tossold(const void *client, const void *a, const void *b) { const struct tossstruct *t; t = (struct tossstruct *)client; return (((BLOCK_INFO *)a)->bi_daddr == LFS_UNUSED_DADDR || - datosn(t->lfs, ((BLOCK_INFO *)a)->bi_daddr) != t->seg); + dtosn(t->lfs, ((BLOCK_INFO *)a)->bi_daddr) != t->seg); } void -sig_report(sig) - int sig; +sig_report(int sig) { double avg = 0.0; @@ -958,8 +932,7 @@ sig_report(sig) } void -just_exit(sig) - int sig; +just_exit(int sig) { exit(0); } diff --git a/libexec/lfs_cleanerd/lfs_cleanerd.8 b/libexec/lfs_cleanerd/lfs_cleanerd.8 index daf85becba4..25deb49b800 100644 --- a/libexec/lfs_cleanerd/lfs_cleanerd.8 +++ b/libexec/lfs_cleanerd/lfs_cleanerd.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: lfs_cleanerd.8,v 1.8 2000/11/08 19:45:08 hubertf Exp $ +.\" $NetBSD: lfs_cleanerd.8,v 1.9 2001/07/13 20:30:22 perseant Exp $ .\" .\" Copyright (c) 1993 .\" The Regents of the University of California. All rights reserved. @@ -113,11 +113,10 @@ not usually necessary to set to a low value. .El .Sh SEE ALSO -.Xr lfs_bmapv 2 , -.Xr lfs_markv 2 , -.Xr lfs_segwait 2 , -.Xr mount_lfs 8 , -.Xr newfs_lfs 8 +.Xr mount_lfs 8 +.Xr lfs_bmapv 2 +.Xr lfs_markv 2 +.Xr lfs_segwait 2 .Sh HISTORY The .Nm diff --git a/libexec/lfs_cleanerd/library.c b/libexec/lfs_cleanerd/library.c index 6bc97054596..178021d1773 100644 --- a/libexec/lfs_cleanerd/library.c +++ b/libexec/lfs_cleanerd/library.c @@ -1,4 +1,4 @@ -/* $NetBSD: library.c,v 1.21 2001/02/04 22:12:47 christos Exp $ */ +/* $NetBSD: library.c,v 1.22 2001/07/13 20:30:22 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.21 2001/02/04 22:12:47 christos Exp $"); +__RCSID("$NetBSD: library.c,v 1.22 2001/07/13 20:30:22 perseant Exp $"); #endif #endif /* not lint */ @@ -62,19 +62,19 @@ __RCSID("$NetBSD: library.c,v 1.21 2001/02/04 22:12:47 christos Exp $"); #include "clean.h" -void add_blocks __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t, - daddr_t, daddr_t)); -void add_inodes __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t, - daddr_t)); -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 *, daddr_t)); -int pseg_size __P((daddr_t, FS_INFO *, SEGSUM *)); +void add_blocks(FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t, + daddr_t, daddr_t); +void add_inodes(FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t, + daddr_t); +int bi_compare(const void *, const void *); +int bi_toss(const void *, const void *, const void *); +void get_ifile(FS_INFO *, int); +int get_superblock(FS_INFO *, struct lfs *); +int pseg_valid(FS_INFO *, SEGSUM *, daddr_t); +int pseg_size(daddr_t, FS_INFO *, SEGSUM *); extern int debug; -extern u_long cksum __P((void *, size_t)); /* XXX */ +extern u_long cksum(void *, size_t); /* XXX */ static int ifile_fd; static int dev_fd; @@ -86,10 +86,7 @@ static int dev_fd; * a non-zero value is returned. */ int -fs_getmntinfo(buf, name, type) - struct statfs **buf; - char *name; - const char *type; +fs_getmntinfo(struct statfs **buf, char *name, const char *type) { /* allocate space for the filesystem info */ *buf = (struct statfs *)malloc(sizeof(struct statfs)); @@ -123,9 +120,7 @@ fs_getmntinfo(buf, name, type) * Returns an pointer to an FS_INFO structure, NULL on error. */ FS_INFO * -get_fs_info (lstatfsp, use_mmap) - struct statfs *lstatfsp; /* IN: pointer to statfs struct */ - int use_mmap; /* IN: mmap or read */ +get_fs_info (struct statfs *lstatfsp, int use_mmap) { FS_INFO *fsp; @@ -139,8 +134,6 @@ get_fs_info (lstatfsp, use_mmap) syslog(LOG_ERR, "Exiting: get_fs_info: get_superblock failed: %m"); exit(1); } - fsp->fi_daddr_shift = - fsp->fi_lfs.lfs_bshift - fsp->fi_lfs.lfs_fsbtodb; get_ifile (fsp, use_mmap); return (fsp); } @@ -151,9 +144,7 @@ get_fs_info (lstatfsp, use_mmap) * refresh the file system information (statfs) info. */ void -reread_fs_info(fsp, use_mmap) - FS_INFO *fsp; /* IN: prointer fs_infos to reread */ - int use_mmap; +reread_fs_info(FS_INFO *fsp, int use_mmap) { if (ifile_fd <= 0) { if (fstatfs(ifile_fd, fsp->fi_statfsp)) { @@ -171,12 +162,11 @@ reread_fs_info(fsp, use_mmap) * Gets the superblock from disk (possibly in face of errors) */ int -get_superblock (fsp, sbp) - FS_INFO *fsp; /* local file system info structure */ - struct lfs *sbp; +get_superblock (FS_INFO *fsp, struct lfs *sbp) { char mntfromname[MNAMELEN+1]; char buf[LFS_SBPAD]; + static off_t sboff = LFS_LABELPAD; strcpy(mntfromname, "/dev/r"); strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5); @@ -189,10 +179,26 @@ get_superblock (fsp, sbp) } else lseek(dev_fd, 0, SEEK_SET); - get(dev_fd, LFS_LABELPAD, buf, LFS_SBPAD); - memcpy(&(sbp->lfs_dlfs), buf, sizeof(struct dlfs)); + do { + get(dev_fd, sboff, buf, LFS_SBPAD); + memcpy(&(sbp->lfs_dlfs), buf, sizeof(struct dlfs)); + if (sboff == LFS_LABELPAD && fsbtob(sbp, 1) > LFS_LABELPAD) + sboff = fsbtob(sbp, (off_t)sbp->lfs_sboffs[0]); + else + break; + } while (1); + /* close (fid); */ + /* Compatibility */ + if (sbp->lfs_version < 2) { + sbp->lfs_sumsize = LFS_V1_SUMMARY_SIZE; + sbp->lfs_ibsize = sbp->lfs_bsize; + sbp->lfs_start = sbp->lfs_sboffs[0]; + sbp->lfs_tstamp = sbp->lfs_otstamp; + sbp->lfs_fsbtodb = 0; + } + return (0); } @@ -201,10 +207,7 @@ get_superblock (fsp, sbp) * fatal error on failure. */ void -get_ifile (fsp, use_mmap) - FS_INFO *fsp; - int use_mmap; - +get_ifile (FS_INFO *fsp, int use_mmap) { struct stat file_stat; struct statfs statfsbuf; @@ -306,19 +309,21 @@ redo_read: * 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 */ +pseg_size(daddr_t pseg_addr, FS_INFO *fsp, SEGSUM *sp) { 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 = lfsp->lfs_sumsize + + howmany(sp->ss_ninos, INOPB(lfsp)) * lfsp->lfs_ibsize; + + if (lfsp->lfs_version == 1) + fp = (FINFO *)(((char *)sp) + sizeof(SEGSUM_V1)); + else + fp = (FINFO *)(sp + 1); + for (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]); @@ -335,12 +340,7 @@ pseg_size(pseg_addr, fsp, sp) * pair will be listed at most once. */ int -lfs_segmapv(fsp, seg, seg_buf, blocks, bcount) - FS_INFO *fsp; /* pointer to local file system information */ - int seg; /* the segment number */ - caddr_t seg_buf; /* the buffer containing the segment's data */ - BLOCK_INFO **blocks; /* OUT: array of block_info for live blocks */ - int *bcount; /* OUT: number of active blocks in segment */ +lfs_segmapv(FS_INFO *fsp, int seg, caddr_t seg_buf, BLOCK_INFO **blocks, int *bcount) { BLOCK_INFO *bip, *_bip; SEGSUM *sp; @@ -360,8 +360,9 @@ lfs_segmapv(fsp, seg, seg_buf, blocks, bcount) sup = SEGUSE_ENTRY(lfsp, fsp->fi_segusep, seg); s = seg_buf + (sup->su_flags & SEGUSE_SUPERBLOCK ? LFS_SBPAD : 0); - seg_addr = sntoda(lfsp, seg); - pseg_addr = seg_addr + (sup->su_flags & SEGUSE_SUPERBLOCK ? btodb(LFS_SBPAD) : 0); + seg_addr = sntod(lfsp, seg); + pseg_addr = seg_addr + (sup->su_flags & SEGUSE_SUPERBLOCK ? + btofsb(lfsp, LFS_SBPAD) : 0); if(debug > 1) syslog(LOG_DEBUG, "\tsegment buffer at: %p\tseg_addr 0x%x", s, seg_addr); @@ -380,14 +381,19 @@ lfs_segmapv(fsp, seg, seg_buf, blocks, bcount) #ifdef DIAGNOSTIC /* Verify size of summary block */ - sumsize = sizeof(SEGSUM) + + sumsize = (lfsp->lfs_version == 1 ? sizeof(SEGSUM_V1) : + sizeof(SEGSUM)) + (sp->ss_ninos + INOPB(lfsp) - 1) / INOPB(lfsp); - for (i = 0, fip = (FINFO *)(sp + 1); i < sp->ss_nfinfo; ++i) { + if (lfsp->lfs_version == 1) + fip = (FINFO *)(((char *)sp) + sizeof(SEGSUM_V1)); + else + fip = (FINFO *)(sp + 1); + for (i = 0; i < sp->ss_nfinfo; ++i) { sumsize += sizeof(FINFO) + (fip->fi_nblocks - 1) * sizeof(daddr_t); fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks]); } - if (sumsize > LFS_SUMMARY_SIZE) { + if (sumsize > lfsp->lfs_sumsize) { syslog(LOG_ERR, "Exiting: Segment %d summary block too big: %d\n", seg, sumsize); @@ -406,7 +412,7 @@ lfs_segmapv(fsp, seg, seg_buf, blocks, bcount) ssize = pseg_size(pseg_addr, fsp, sp); s += ssize; - pseg_addr += btodb(ssize); /* XXX was bytetoda(fsp,ssize) */ + pseg_addr += btofsb(lfsp, ssize); } if(nsegs < sup->su_nsums) { syslog(LOG_WARNING,"only %d segment summaries in seg %d (expected %d)", @@ -439,34 +445,34 @@ lfs_segmapv(fsp, seg, seg_buf, blocks, bcount) * blocks or inodes from files with new version numbers. */ void -add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr) - FS_INFO *fsp; /* pointer to super block */ - BLOCK_INFO *bip; /* Block info array */ - int *countp; /* IN/OUT: number of blocks in array */ - SEGSUM *sp; /* segment summmary pointer */ - caddr_t seg_buf; /* buffer containing segment */ - daddr_t segaddr; /* address of this segment */ - daddr_t psegaddr; /* address of this partial segment */ +add_blocks (FS_INFO *fsp, BLOCK_INFO *bip, int *countp, SEGSUM *sp, + caddr_t seg_buf, daddr_t segaddr, daddr_t psegaddr) { IFILE *ifp; FINFO *fip; caddr_t bp; daddr_t *dp, *iaddrp; - int db_per_block, i, j; - int db_frag; + int fsb_per_block, i, j; + int fsb_frag; u_long page_size; + struct lfs *lfsp; if(debug > 1) syslog(LOG_DEBUG, "FILE INFOS"); - db_per_block = fsbtodb(&fsp->fi_lfs, 1); + lfsp = &fsp->fi_lfs; + fsb_per_block = fragstofsb(lfsp, lfsp->lfs_frag); page_size = fsp->fi_lfs.lfs_bsize; - bp = seg_buf + datobyte(fsp, psegaddr - segaddr) + LFS_SUMMARY_SIZE; + bp = seg_buf + fsbtob(lfsp, psegaddr - segaddr) + lfsp->lfs_sumsize; bip += *countp; - psegaddr += bytetoda(fsp, LFS_SUMMARY_SIZE); - iaddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE); + psegaddr += btofsb(lfsp, lfsp->lfs_sumsize); + iaddrp = (daddr_t *)((caddr_t)sp + lfsp->lfs_sumsize); --iaddrp; - for (fip = (FINFO *)(sp + 1), i = 0; i < sp->ss_nfinfo; + if (lfsp->lfs_version == 1) + fip = (FINFO *)(((char *)sp) + sizeof(SEGSUM_V1)); + else + fip = (FINFO *)(sp + 1); + for (i = 0; i < sp->ss_nfinfo; ++i, fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks])) { ifp = IFILE_ENTRY(&fsp->fi_lfs, fsp->fi_ifilep, fip->fi_ino); @@ -477,14 +483,17 @@ add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr) for (j = 0; j < fip->fi_nblocks; j++, dp++) { /* Skip over intervening inode blocks */ while (psegaddr == *iaddrp) { - psegaddr += db_per_block; + psegaddr += fsb_per_block; bp += page_size; --iaddrp; } bip->bi_inode = fip->fi_ino; bip->bi_lbn = *dp; bip->bi_daddr = psegaddr; - bip->bi_segcreate = (time_t)(sp->ss_create); + if (lfsp->lfs_version == 1) + bip->bi_segcreate = (time_t)(sp->ss_ident); + else + bip->bi_segcreate = (time_t)(sp->ss_create); bip->bi_bp = bp; bip->bi_version = ifp->if_version; @@ -492,21 +501,21 @@ add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr) || fip->fi_lastlength == page_size) { bip->bi_size = page_size; - psegaddr += db_per_block; + psegaddr += fsb_per_block; bp += page_size; } else { - db_frag = fragstodb(&(fsp->fi_lfs), + fsb_frag = fragstofsb(&(fsp->fi_lfs), numfrags(&(fsp->fi_lfs), fip->fi_lastlength)); if(debug > 1) { syslog(LOG_DEBUG, "lastlength, frags: %d, %d", - fip->fi_lastlength, db_frag); + fip->fi_lastlength, fsb_frag); } bip->bi_size = fip->fi_lastlength; bp += fip->fi_lastlength; - psegaddr += db_frag; + psegaddr += fsb_frag; } ++bip; ++(*countp); @@ -520,13 +529,8 @@ add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr) * actually added. */ void -add_inodes (fsp, bip, countp, sp, seg_buf, seg_addr) - FS_INFO *fsp; /* pointer to super block */ - BLOCK_INFO *bip; /* block info array */ - int *countp; /* pointer to current number of inodes */ - SEGSUM *sp; /* segsum pointer */ - caddr_t seg_buf; /* the buffer containing the segment's data */ - daddr_t seg_addr; /* disk address of seg_buf */ +add_inodes (FS_INFO *fsp, BLOCK_INFO *bip, int *countp, SEGSUM *sp, + caddr_t seg_buf, daddr_t seg_addr) { struct dinode *di = NULL; /* XXX gcc */ struct lfs *lfsp; @@ -545,12 +549,12 @@ add_inodes (fsp, bip, countp, sp, seg_buf, seg_addr) if(debug > 1) syslog(LOG_DEBUG, "INODES:"); - daddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE); + daddrp = (daddr_t *)((caddr_t)sp + lfsp->lfs_sumsize); for (i = 0; i < sp->ss_ninos; ++i) { if (i % INOPB(lfsp) == 0) { --daddrp; - di = (struct dinode *)(seg_buf + - ((*daddrp - seg_addr) << fsp->fi_daddr_shift)); + di = (struct dinode *)(seg_buf + fsbtob(lfsp, + *daddrp - seg_addr)); } else ++di; @@ -559,7 +563,10 @@ add_inodes (fsp, bip, countp, sp, seg_buf, seg_addr) bp->bi_inode = inum; bp->bi_daddr = *daddrp; bp->bi_bp = di; - bp->bi_segcreate = sp->ss_create; + if (lfsp->lfs_version == 1) + bp->bi_segcreate = sp->ss_ident; + else + bp->bi_segcreate = sp->ss_create; bp->bi_size = i; /* XXX KS - kludge */ if (inum == LFS_IFILE_INUM) { @@ -586,10 +593,7 @@ add_inodes (fsp, bip, countp, sp, seg_buf, seg_addr) * the partial as well as whether or not the checksum is valid. */ int -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 */ +pseg_valid (FS_INFO *fsp, SEGSUM *ssp, daddr_t addr) { int nblocks; #if 0 @@ -610,7 +614,7 @@ pseg_valid (fsp, ssp, addr) #if 0 /* check data/inode block(s) checksum too */ datap = (u_long *)malloc(nblocks * sizeof(u_long)); - p = (caddr_t)ssp + LFS_SUMMARY_SIZE; + p = (caddr_t)ssp + lfsp->lfs_sumsize; for (i = 0; i < nblocks; ++i) { datap[i] = *((u_long *)p); p += fsp->fi_lfs.lfs_bsize; @@ -630,11 +634,7 @@ pseg_valid (fsp, ssp, addr) * read a segment into a memory buffer */ int -mmap_segment (fsp, segment, segbuf, use_mmap) - FS_INFO *fsp; /* file system information */ - int segment; /* segment number */ - caddr_t *segbuf; /* pointer to buffer area */ - int use_mmap; /* mmap instead of read */ +mmap_segment (FS_INFO *fsp, int segment, caddr_t *segbuf, int use_mmap) { struct lfs *lfsp; daddr_t seg_daddr; /* base disk address of segment */ @@ -645,8 +645,8 @@ mmap_segment (fsp, segment, segbuf, use_mmap) lfsp = &fsp->fi_lfs; /* get the disk address of the beginning of the segment */ - seg_daddr = sntoda(lfsp, segment); - seg_byte = datobyte(fsp, seg_daddr); + seg_daddr = sntod(lfsp, segment); + seg_byte = fsbtob(lfsp, (off_t)seg_daddr); ssize = seg_size(lfsp); strcpy(mntfromname, "/dev/r"); @@ -697,10 +697,7 @@ mmap_segment (fsp, segment, segbuf, use_mmap) } void -munmap_segment (fsp, seg_buf, use_mmap) - FS_INFO *fsp; /* file system information */ - caddr_t seg_buf; /* pointer to buffer area */ - int use_mmap; /* mmap instead of read/write */ +munmap_segment (FS_INFO *fsp, caddr_t seg_buf, int use_mmap) { if (use_mmap) munmap (seg_buf, seg_size(&fsp->fi_lfs)); @@ -712,10 +709,7 @@ munmap_segment (fsp, seg_buf, use_mmap) * USEFUL DEBUGGING TOOLS: */ void -print_SEGSUM (lfsp, p, addr) - struct lfs *lfsp; - SEGSUM *p; - daddr_t addr; +print_SEGSUM (struct lfs *lfsp, SEGSUM *p, daddr_t addr) { if (p) (void) dump_summary(lfsp, p, DUMP_ALL, NULL, addr); @@ -724,9 +718,7 @@ print_SEGSUM (lfsp, p, addr) } int -bi_compare(a, b) - const void *a; - const void *b; +bi_compare(const void *a, const void *b) { const BLOCK_INFO *ba, *bb; int diff; @@ -757,10 +749,7 @@ bi_compare(a, b) } int -bi_toss(dummy, a, b) - const void *dummy; - const void *a; - const void *b; +bi_toss(const void *dummy, const void *a, const void *b) { const BLOCK_INFO *ba, *bb; @@ -771,12 +760,7 @@ bi_toss(dummy, a, b) } void -toss(p, nump, size, dotoss, client) - void *p; - int *nump; - size_t size; - int (*dotoss) __P((const void *, const void *, const void *)); - void *client; +toss(void *p, int *nump, size_t size, int (*dotoss)(const void *, const void *, const void *), void *client) { int i; char *p0, *p1; diff --git a/libexec/lfs_cleanerd/misc.c b/libexec/lfs_cleanerd/misc.c index 49644888346..724b231289d 100644 --- a/libexec/lfs_cleanerd/misc.c +++ b/libexec/lfs_cleanerd/misc.c @@ -1,4 +1,4 @@ -/* $NetBSD: misc.c,v 1.6 1999/03/14 11:39:28 drochner Exp $ */ +/* $NetBSD: misc.c,v 1.7 2001/07/13 20:30:22 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.6 1999/03/14 11:39:28 drochner Exp $"); +__RCSID("$NetBSD: misc.c,v 1.7 2001/07/13 20:30:22 perseant Exp $"); #endif #endif /* not lint */ @@ -60,11 +60,7 @@ __RCSID("$NetBSD: misc.c,v 1.6 1999/03/14 11:39:28 drochner Exp $"); extern char *special; void -get(fd, off, p, len) - int fd; - off_t off; - void *p; - size_t len; +get(int fd, off_t off, void *p, size_t len) { int rbytes; diff --git a/libexec/lfs_cleanerd/print.c b/libexec/lfs_cleanerd/print.c index 3da35524f77..96352d545da 100644 --- a/libexec/lfs_cleanerd/print.c +++ b/libexec/lfs_cleanerd/print.c @@ -1,4 +1,4 @@ -/* $NetBSD: print.c,v 1.9 2001/01/04 17:29:04 lukem Exp $ */ +/* $NetBSD: print.c,v 1.10 2001/07/13 20:30:22 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.9 2001/01/04 17:29:04 lukem Exp $"); +__RCSID("$NetBSD: print.c,v 1.10 2001/07/13 20:30:22 perseant Exp $"); #endif #endif /* not lint */ @@ -58,7 +58,7 @@ __RCSID("$NetBSD: print.c,v 1.9 2001/01/04 17:29:04 lukem Exp $"); #include "clean.h" extern int debug; -extern u_long cksum __P((void *, size_t)); /* XXX */ +extern u_long cksum(void *, size_t); /* XXX */ /* * Print out a summary block; return number of blocks in segment; 0 @@ -67,12 +67,7 @@ extern u_long cksum __P((void *, size_t)); /* XXX */ */ int -dump_summary(lfsp, sp, flags, iaddrp, addr) - struct lfs *lfsp; - SEGSUM *sp; - u_long flags; - daddr_t **iaddrp; - daddr_t addr; +dump_summary(struct lfs *lfsp, SEGSUM *sp, u_long flags, daddr_t **iaddrp, daddr_t addr) { int i, j, blk, numblocks, accino=0; daddr_t *dp, ddp, *idp; @@ -87,7 +82,7 @@ dump_summary(lfsp, sp, flags, iaddrp, addr) return(-1); if (sp->ss_sumsum != (ck = cksum(&sp->ss_datasum, - LFS_SUMMARY_SIZE - sizeof(sp->ss_sumsum)))) { + lfsp->lfs_sumsize - sizeof(sp->ss_sumsum)))) { free(datap); return(-1); } @@ -99,7 +94,9 @@ dump_summary(lfsp, sp, flags, iaddrp, addr) "ninos ", sp->ss_ninos, "sumsum ", sp->ss_sumsum, "datasum ", sp->ss_datasum ); - syslog(LOG_DEBUG, "\tcreate %s", ctime((time_t *)&sp->ss_create)); + syslog(LOG_DEBUG, "\tcreate %s", ctime( + (lfsp->lfs_version == 1 ? (time_t *)&sp->ss_ident : + (time_t *)&sp->ss_create))); } numblocks = (sp->ss_ninos + INOPB(lfsp) - 1) / INOPB(lfsp); @@ -108,7 +105,7 @@ dump_summary(lfsp, sp, flags, iaddrp, addr) if (flags & DUMP_INODE_ADDRS) syslog(LOG_DEBUG, " Inode addresses:"); - idp = dp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE); + idp = dp = (daddr_t *)((caddr_t)sp + lfsp->lfs_sumsize); --idp; for (--dp, i = 0; i < howmany(sp->ss_ninos,INOPB(lfsp)); --dp) { if (flags & DUMP_INODE_ADDRS) @@ -119,26 +116,30 @@ dump_summary(lfsp, sp, flags, iaddrp, addr) *iaddrp = dp; } - ddp = addr + LFS_SUMMARY_SIZE/DEV_BSIZE; - for (fp = (FINFO *)(sp + 1), i = 0; i < sp->ss_nfinfo; ++i) { + ddp = addr + btofsb(lfsp, lfsp->lfs_sumsize); + if (lfsp->lfs_version == 1) + fp = (FINFO *)(((char *)sp) + sizeof(SEGSUM_V1)); + else + fp = (FINFO *)(sp + 1); + for (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); + datap[blk++] = *(u_long*)((caddr_t)sp + fsbtob(lfsp, ddp-addr)); --idp; - ddp += lfsp->lfs_bsize/DEV_BSIZE; + ddp += btofsb(lfsp, lfsp->lfs_ibsize); accino++; } for(j=0;j<fp->fi_nblocks;j++) { if(j==fp->fi_nblocks-1) { - size = fp->fi_lastlength/DEV_BSIZE; + size = btofsb(lfsp, fp->fi_lastlength); /* printf(" %lx:%d",ddp,size); */ } else { - size = lfsp->lfs_bsize/DEV_BSIZE; + size = btofsb(lfsp, lfsp->lfs_bsize); /* printf(" %lx/%d",ddp,size); */ } - datap[blk++] = *(u_long*)((caddr_t)sp + (ddp-addr)*DEV_BSIZE); + datap[blk++] = *(u_long*)((caddr_t)sp + fsbtob(lfsp, ddp-addr)); ddp += size; } numblocks += fp->fi_nblocks; @@ -160,7 +161,7 @@ dump_summary(lfsp, sp, flags, iaddrp, addr) 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); + datap[blk++] = *(u_long*)((caddr_t)sp + fsbtob(lfsp, ddp-addr)); --idp; accino++; } @@ -185,8 +186,7 @@ dump_summary(lfsp, sp, flags, iaddrp, addr) } void -dump_cleaner_info(ipage) - void *ipage; +dump_cleaner_info(void *ipage) { CLEANERINFO *cip; @@ -199,8 +199,7 @@ dump_cleaner_info(ipage) } void -dump_super(lfsp) - struct lfs *lfsp; +dump_super(struct lfs *lfsp) { int i; @@ -278,6 +277,6 @@ dump_super(lfsp) syslog(LOG_DEBUG, "%s%d\t%s%d\t%s0x%X\t%s%d\n", "nactive ", lfsp->lfs_nactive, "fmod ", lfsp->lfs_fmod, - "clean ", lfsp->lfs_clean, + "pflags ", lfsp->lfs_pflags, "ronly ", lfsp->lfs_ronly); } diff --git a/sbin/dump_lfs/Makefile b/sbin/dump_lfs/Makefile index f94b91165dd..66ceccdcfcf 100644 --- a/sbin/dump_lfs/Makefile +++ b/sbin/dump_lfs/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.1 1999/09/29 04:57:49 perseant Exp $ +# $NetBSD: Makefile,v 1.2 2001/07/13 20:30:18 perseant Exp $ # @(#)Makefile 8.1 (Berkeley) 6/5/93 # lfs_inode.c LFS filestore-specific routines @@ -9,6 +9,7 @@ PROG= dump_lfs LINKS= ${BINDIR}/dump_lfs ${BINDIR}/rdump_lfs CPPFLAGS+=-DRDUMP -I${.CURDIR} -I${.CURDIR}/../dump +CPPFLAGS+=-DDUMP_LFS # CPPFLAGS+= -DDEBUG -DTDEBUG -DFDEBUG -DWRITEDEBUG -DSTATS -DDIAGNOSTICS SRCS= itime.c main.c optr.c dumprmt.c rcache.c tape.c traverse.c unctime.c \ ffs_bswap.c lfs_inode.c diff --git a/sbin/dump_lfs/lfs_inode.c b/sbin/dump_lfs/lfs_inode.c index 86ad80a5763..a729789b111 100644 --- a/sbin/dump_lfs/lfs_inode.c +++ b/sbin/dump_lfs/lfs_inode.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_inode.c,v 1.2 1999/10/01 04:35:23 perseant Exp $ */ +/* $NetBSD: lfs_inode.c,v 1.3 2001/07/13 20:30:18 perseant Exp $ */ /*- * Copyright (c) 1980, 1991, 1993, 1994 @@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 1991, 1993, 1994\n\ #if 0 static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/1/95"; #else -__RCSID("$NetBSD: lfs_inode.c,v 1.2 1999/10/01 04:35:23 perseant Exp $"); +__RCSID("$NetBSD: lfs_inode.c,v 1.3 2001/07/13 20:30:18 perseant Exp $"); #endif #endif /* not lint */ @@ -82,19 +82,58 @@ struct lfs *sblock; int fs_read_sblock(char *sblock_buf) { + char tbuf[LFS_SBPAD]; int needswap = 0; + off_t sboff = LFS_LABELPAD; sblock = (struct lfs *)sblock_buf; - rawread(LFS_LABELPAD, (char *) sblock, LFS_SBPAD); - if (sblock->lfs_magic != LFS_MAGIC) { + while(1) { + rawread(sboff, (char *) sblock, LFS_SBPAD); + if (sblock->lfs_magic != LFS_MAGIC) { #ifdef notyet - if (sblock->lfs_magic == bswap32(LFS_MAGIC)) { - lfs_sb_swap(sblock, sblock, 0); - needswap = 1; - } else + if (sblock->lfs_magic == bswap32(LFS_MAGIC)) { + lfs_sb_swap(sblock, sblock, 0); + needswap = 1; + } else #endif - quit("bad sblock magic number\n"); + quit("bad sblock magic number\n"); + } + if (fsbtob(sblock, sblock->lfs_sboffs[0]) != sboff) { + sboff = fsbtob(sblock, sblock->lfs_sboffs[0]); + continue; + } + break; + } + + /* + * Read the secondary and take the older of the two + */ + rawread(fsbtob(sblock, sblock->lfs_sboffs[1]), tbuf, LFS_SBPAD); +#ifdef notyet + if (needswap) + lfs_sb_swap(tbuf, tbuf, 0); +#endif + if (((struct lfs *)tbuf)->lfs_magic != LFS_MAGIC) { + msg("Warning: secondary superblock at 0x%x bad magic\n", + fsbtodb(sblock, sblock->lfs_sboffs[1])); + } else { + if (sblock->lfs_version > 1) { + if (((struct lfs *)tbuf)->lfs_serial < sblock->lfs_serial) { + memcpy(sblock, tbuf, LFS_SBPAD); + sboff = fsbtob(sblock, sblock->lfs_sboffs[1]); + } + } else { + if (((struct lfs *)tbuf)->lfs_otstamp < sblock->lfs_otstamp) { + memcpy(sblock, tbuf, LFS_SBPAD); + sboff = fsbtob(sblock, sblock->lfs_sboffs[1]); + } + } + } + if (sboff != LFS_SBPAD) { + msg("Using superblock at alternate location 0x%lx\n", + (unsigned long)(btodb(sboff))); } + return needswap; } @@ -110,11 +149,15 @@ fs_parametrize(void) spcl.c_flags = iswap32(iswap32(spcl.c_flags) | DR_NEWINODEFMT); ufsi.ufs_dsize = fsbtodb(sblock,sblock->lfs_size); + if (sblock->lfs_version == 1) + ufsi.ufs_dsize = sblock->lfs_size >> sblock->lfs_blktodb; ufsi.ufs_bsize = sblock->lfs_bsize; ufsi.ufs_bshift = sblock->lfs_bshift; ufsi.ufs_fsize = sblock->lfs_fsize; ufsi.ufs_frag = sblock->lfs_frag; - ufsi.ufs_fsatoda = 0; + ufsi.ufs_fsatoda = sblock->lfs_fsbtodb; + if (sblock->lfs_version == 1) + ufsi.ufs_fsatoda = 0; ufsi.ufs_nindir = sblock->lfs_nindir; ufsi.ufs_inopb = sblock->lfs_inopb; ufsi.ufs_maxsymlinklen = sblock->lfs_maxsymlinklen; @@ -123,7 +166,7 @@ fs_parametrize(void) ufsi.ufs_fmask = ~(sblock->lfs_ffmask); ufsi.ufs_qfmask = sblock->lfs_ffmask; - dev_bsize = sblock->lfs_bsize >> sblock->lfs_fsbtodb; + dev_bsize = sblock->lfs_bsize >> sblock->lfs_blktodb; return &ufsi; } @@ -154,7 +197,7 @@ lfs_bmap(struct lfs *fs, struct dinode *idinode, ufs_daddr_t lbn) int off=0; char bp[MAXBSIZE]; - if(lbn > 0 && lbn > (idinode->di_size-1)/dev_bsize) { + if(lbn > 0 && lbn > lblkno(fs, idinode->di_size)) { return UNASSIGNED; } /* @@ -188,7 +231,7 @@ lfs_bmap(struct lfs *fs, struct dinode *idinode, ufs_daddr_t lbn) if(up == UNASSIGNED || up == LFS_UNUSED_DADDR) return UNASSIGNED; /* printf("lbn %d: parent is the triple\n", -lbn); */ - bread(up, bp, sblock->lfs_bsize); + bread(fsbtodb(sblock, up), bp, sblock->lfs_bsize); return ((daddr_t *)bp)[off]; } else /* residue == 0 */ { /* Single indirect. Two cases. */ @@ -220,7 +263,7 @@ lfs_bmap(struct lfs *fs, struct dinode *idinode, ufs_daddr_t lbn) up = lfs_bmap(fs,idinode,up); if(up == UNASSIGNED || up == LFS_UNUSED_DADDR) return UNASSIGNED; - bread(up, bp, sblock->lfs_bsize); + bread(fsbtodb(sblock, up), bp, sblock->lfs_bsize); return ((daddr_t *)bp)[off]; } @@ -235,7 +278,8 @@ lfs_ientry(ino_t ino) lbn = ino/sblock->lfs_ifpb + sblock->lfs_cleansz + sblock->lfs_segtabsz; blkno = lfs_bmap(sblock,getino(sblock->lfs_ifile),lbn); if(blkno != ifblkno) - bread(blkno, (char *)ifileblock, sblock->lfs_bsize); + bread(fsbtodb(sblock, blkno), (char *)ifileblock, + sblock->lfs_bsize); return ifileblock + (ino%sblock->lfs_ifpb); } @@ -266,7 +310,8 @@ getino(inum) /* Load the ifile inode if not already */ if(ifile_dinode.di_u.inumber == 0) { blkno = sblock->lfs_idaddr; - bread(blkno, (char *)inoblock, (int)sblock->lfs_bsize); + bread(fsbtodb(sblock, blkno), (char *)inoblock, + (int)sblock->lfs_bsize); dp = lfs_ifind(sblock, inum, inoblock); ifile_dinode = *dp; /* Structure copy */ } @@ -279,7 +324,8 @@ getino(inum) return &empty_dinode; if(blkno != inoblkno) { - bread(blkno, (char *)inoblock, (int)sblock->lfs_bsize); + bread(fsbtodb(sblock, blkno), (char *)inoblock, + (int)sblock->lfs_bsize); #ifdef notyet if (needswap) for (i = 0; i < MAXINOPB; i++) diff --git a/sbin/fsck_lfs/dir.c b/sbin/fsck_lfs/dir.c index dbb48179ea2..2536fd64469 100644 --- a/sbin/fsck_lfs/dir.c +++ b/sbin/fsck_lfs/dir.c @@ -1,4 +1,4 @@ -/* $NetBSD: dir.c,v 1.4 2000/06/14 18:43:57 perseant Exp $ */ +/* $NetBSD: dir.c,v 1.5 2001/07/13 20:30:18 perseant Exp $ */ /* * Copyright (c) 1980, 1986, 1993 @@ -122,7 +122,7 @@ dirscan(struct inodesc * idesc) (idesc->id_filesize & (DIRBLKSIZ - 1)) != 0) idesc->id_filesize = roundup(idesc->id_filesize, DIRBLKSIZ); blksiz = idesc->id_numfrags * sblock.lfs_fsize; - if (chkrange(idesc->id_blkno, idesc->id_numfrags)) { + if (chkrange(idesc->id_blkno, fragstofsb(&sblock, idesc->id_numfrags))) { idesc->id_filesize -= blksiz; return (SKIP); } @@ -574,9 +574,9 @@ expanddir(struct dinode * dp, char *name) dp->di_db[lastbn + 1] = dp->di_db[lastbn]; dp->di_db[lastbn] = newblk; dp->di_size += sblock.lfs_bsize; - dp->di_blocks += btodb(sblock.lfs_bsize); - bp = getdirblk(dp->di_db[lastbn + 1], - (long)dblksize(&sblock, dp, lastbn + 1)); + dp->di_blocks += btofsb(&sblock, sblock.lfs_bsize); + bp = getdirblk(dp->di_db[lastbn + 1], + (long)dblksize(&sblock, dp, lastbn + 1)); if (bp->b_errs) goto bad; memcpy(firstblk, bp->b_un.b_buf, DIRBLKSIZ); @@ -606,7 +606,7 @@ bad: dp->di_db[lastbn] = dp->di_db[lastbn + 1]; dp->di_db[lastbn + 1] = 0; dp->di_size -= sblock.lfs_bsize; - dp->di_blocks -= btodb(sblock.lfs_bsize); + dp->di_blocks -= btofsb(&sblock, sblock.lfs_bsize); freeblk(newblk, sblock.lfs_frag); return (0); } diff --git a/sbin/fsck_lfs/inode.c b/sbin/fsck_lfs/inode.c index e5e3d60db83..2a64c315d1b 100644 --- a/sbin/fsck_lfs/inode.c +++ b/sbin/fsck_lfs/inode.c @@ -1,4 +1,4 @@ -/* $NetBSD: inode.c,v 1.10 2001/02/04 21:52:02 christos Exp $ */ +/* $NetBSD: inode.c,v 1.11 2001/07/13 20:30:18 perseant Exp $ */ /* * Copyright (c) 1997, 1998 @@ -65,11 +65,21 @@ int lfs_maxino(void); struct dinode * lfs_difind(struct lfs * fs, ino_t ino, struct dinode * dip) { - register int cnt; + struct dinode *ldip, *fin; - for (cnt = 0; cnt < INOPB(fs); cnt++) - if (dip[cnt].di_inumber == ino) - return &(dip[cnt]); +#ifdef LFS_IFILE_FRAG_ADDRESSING + if (fs->lfs_version == 1) + fin = dip + INOPB(fs); + else + fin = dip + INOPF(fs); +#else + fin = dip + INOPB(fs); +#endif + + for (ldip = dip; ldip < fin; ++ldip) { + if (ldip->di_inumber == ino) + return ldip; + } /* printf("lfs_difind: dinode %u not found\n", ino); */ return NULL; } @@ -228,7 +238,7 @@ gidinode(void) struct ifile * lfs_ientry(ino_t ino, struct bufarea ** bpp) { - struct ifile *ifp; + IFILE *ifp; *bpp = getfileblk(&sblock, lfs_ginode(LFS_IFILE_INUM), ino / sblock.lfs_ifpb + sblock.lfs_cleansz + @@ -237,8 +247,14 @@ lfs_ientry(ino_t ino, struct bufarea ** bpp) printf("Warning: ino %d ientry in unassigned block\n", ino); } if (*bpp) { - ifp = (((struct ifile *)((*bpp)->b_un.b_buf)) + - (ino % sblock.lfs_ifpb)); + if (sblock.lfs_version > 1) { + ifp = (((IFILE *)((*bpp)->b_un.b_buf)) + + (ino % sblock.lfs_ifpb)); + } else { + ifp = (IFILE *)(((IFILE_V1 *) + ((*bpp)->b_un.b_buf)) + + (ino % sblock.lfs_ifpb)); + } return ifp; } else return NULL; @@ -248,10 +264,15 @@ SEGUSE * lfs_gseguse(int segnum, struct bufarea ** bpp) { int blkno; + struct bufarea *bp; - blkno = segnum / (sblock.lfs_bsize / sizeof(SEGUSE)) + sblock.lfs_cleansz; - (*bpp) = getfileblk(&sblock, lfs_ginode(LFS_IFILE_INUM), blkno); - return ((SEGUSE *)(*bpp)->b_un.b_buf) + segnum % (sblock.lfs_bsize / sizeof(SEGUSE)); + blkno = segnum / sblock.lfs_sepb + sblock.lfs_cleansz; + (*bpp) = bp = getfileblk(&sblock, lfs_ginode(LFS_IFILE_INUM), blkno); + if (sblock.lfs_version == 1) + return (SEGUSE *)((SEGUSE_V1 *)(bp->b_un.b_buf) + + segnum % sblock.lfs_sepb); + else + return (SEGUSE *)(bp->b_un.b_buf) + segnum % sblock.lfs_sepb; } daddr_t @@ -280,7 +301,7 @@ lfs_ino_daddr(ino_t inumber) } din_table[inumber] = daddr; - seg_table[datosn(&sblock, daddr)].su_nbytes += DINODE_SIZE; + seg_table[dtosn(&sblock, daddr)].su_nbytes += DINODE_SIZE; } return daddr; } @@ -301,7 +322,7 @@ lfs_ginode(ino_t inumber) daddr = idaddr; if (din_table[LFS_IFILE_INUM] == 0) { din_table[LFS_IFILE_INUM] = daddr; - seg_table[datosn(&sblock, daddr)].su_nbytes += DINODE_SIZE; + seg_table[dtosn(&sblock, daddr)].su_nbytes += DINODE_SIZE; } return gidinode(); } @@ -314,7 +335,10 @@ lfs_ginode(ino_t inumber) if (pbp) pbp->b_flags &= ~B_INUSE; - pbp = getddblk(daddr, sblock.lfs_bsize); + if (sblock.lfs_version == 1) + pbp = getddblk(daddr, sblock.lfs_bsize); + else + pbp = getddblk(daddr, sblock.lfs_fsize); din = lfs_difind(&sblock, inumber, pbp->b_un.b_dinode); if (din == NULL) { @@ -467,7 +491,7 @@ iblock(struct inodesc * idesc, long ilevel, u_int64_t isize) return (n); } else func = dirscan; - if (chkrange(idesc->id_blkno, fragstodb(&sblock, idesc->id_numfrags))) + if (chkrange(idesc->id_blkno, fragstofsb(&sblock, idesc->id_numfrags))) return (SKIP); bp = getddblk(idesc->id_blkno, sblock.lfs_bsize); ilevel--; @@ -536,10 +560,16 @@ iblock(struct inodesc * idesc, long ilevel, u_int64_t isize) int chkrange(daddr_t blk, int cnt) { - if (blk < btodb(LFS_LABELPAD+LFS_SBPAD)) { + if (blk < sntod(&sblock, 0)) { + return (1); + } + if (blk > maxfsblock) { + return (1); + } + if (blk + cnt < sntod(&sblock, 0)) { return (1); } - if (blk > fsbtodb(&sblock, maxfsblock)) { + if (blk + cnt > maxfsblock) { return (1); } return (0); @@ -797,7 +827,7 @@ allocino(ino_t request, int type) dp->di_atime = t; dp->di_mtime = dp->di_ctime = dp->di_atime; dp->di_size = sblock.lfs_fsize; - dp->di_blocks = btodb(sblock.lfs_fsize); + dp->di_blocks = btofsb(&sblock, sblock.lfs_fsize); n_files++; inodirty(); if (newinofmt) diff --git a/sbin/fsck_lfs/pass0.c b/sbin/fsck_lfs/pass0.c index d5fdab3d75a..7fc485489dd 100644 --- a/sbin/fsck_lfs/pass0.c +++ b/sbin/fsck_lfs/pass0.c @@ -1,4 +1,4 @@ -/* $NetBSD: pass0.c,v 1.8 2001/01/05 02:02:58 lukem Exp $ */ +/* $NetBSD: pass0.c,v 1.9 2001/07/13 20:30:19 perseant Exp $ */ /* * Copyright (c) 1998 Konrad E. Schroder. @@ -68,7 +68,7 @@ check_segment(int, int, daddr_t, struct lfs *, int, * finfo blocks, for one thing. */ -#define dbshift (sblock.lfs_bshift - sblock.lfs_fsbtodb) +#define dbshift (sblock.lfs_bshift - sblock.lfs_blktodb) void pass0() @@ -161,7 +161,8 @@ dump_segsum(SEGSUM * sump, daddr_t addr) printf("\tsumsum: %x (%d)\n", sump->ss_sumsum, sump->ss_sumsum); printf("\tdatasum: %x (%d)\n", sump->ss_datasum, sump->ss_datasum); printf("\tnext: %x (%d)\n", sump->ss_next, sump->ss_next); - printf("\tcreate: %x (%d)\n", sump->ss_create, sump->ss_create); + printf("\tcreate: %llx (%lld)\n", (long long)sump->ss_create, + (long long)sump->ss_create); printf("\tnfinfo: %x (%d)\n", sump->ss_nfinfo, sump->ss_nfinfo); printf("\tninos: %x (%d)\n", sump->ss_ninos, sump->ss_ninos); printf("\tflags: %c%c\n", @@ -169,6 +170,7 @@ dump_segsum(SEGSUM * sump, daddr_t addr) sump->ss_flags & SS_CONT ? 'c' : '-'); } +/* XXX Don't use... broken. -JO */ void check_segment(int fd, int segnum, daddr_t addr, struct lfs * fs, int flags, int (*func)(struct lfs *, SEGSUM *, daddr_t)) { @@ -180,7 +182,7 @@ check_segment(int fd, int segnum, daddr_t addr, struct lfs * fs, int flags, int off_t sum_offset, db_ssize; int bc, su_flags, su_nsums, su_ninos; - db_ssize = sblock.lfs_ssize << sblock.lfs_fsbtodb; + db_ssize = segtod(&sblock, 1); su = lfs_gseguse(segnum, &bp); su_flags = su->su_flags; @@ -223,7 +225,7 @@ check_segment(int fd, int segnum, daddr_t addr, struct lfs * fs, int flags, int while (1) { if (su_nsums <= psegnum) break; - bp = getddblk(sum_offset >> dbshift, LFS_SUMMARY_SIZE); + bp = getddblk(sum_offset >> dbshift, sblock.lfs_sumsize); sump = (SEGSUM *)(bp->b_un.b_buf); if (sump->ss_magic != SS_MAGIC) { if (flags & CKSEG_VERBOSE) @@ -232,7 +234,7 @@ check_segment(int fd, int segnum, daddr_t addr, struct lfs * fs, int flags, int bp->b_flags &= ~B_INUSE; break; } - if (sump->ss_sumsum != cksum(&sump->ss_datasum, LFS_SUMMARY_SIZE - sizeof(sump->ss_sumsum))) { + if (sump->ss_sumsum != cksum(&sump->ss_datasum, sblock.lfs_sumsize - sizeof(sump->ss_sumsum))) { if (flags & CKSEG_VERBOSE) { /* Corrupt partial segment */ pwarn("CORRUPT PARTIAL SEGMENT %d/%d OF SEGMENT %d AT BLK 0x%llx", @@ -262,8 +264,9 @@ check_segment(int fd, int segnum, daddr_t addr, struct lfs * fs, int flags, int */ bc = (*func)(&sblock, sump, (daddr_t)(sum_offset >> dbshift)); if (bc) { - sum_offset += LFS_SUMMARY_SIZE + bc; - ninos += (sump->ss_ninos + INOPB(&sblock) - 1) / INOPB(&sblock); + sum_offset += sblock.lfs_sumsize + bc; + ninos += (sump->ss_ninos + INOPB(&sblock) - 1) + / INOPB(&sblock); psegnum++; } else { bp->b_flags &= ~B_INUSE; @@ -295,8 +298,8 @@ check_summary(struct lfs * fs, SEGSUM * sp, daddr_t pseg_addr) u_long *datap; u_int32_t ccksum; - sn = datosn(fs, pseg_addr); - seg_addr = sntoda(fs, sn); + sn = dtosn(fs, pseg_addr); + seg_addr = sntod(fs, sn); /* * printf("Pseg at 0x%x, %d inos, %d @@ -318,11 +321,11 @@ check_summary(struct lfs * fs, SEGSUM * sp, daddr_t pseg_addr) datac = 0; dp = (daddr_t *)sp; - dp += LFS_SUMMARY_SIZE / sizeof(daddr_t); + dp += sblock.lfs_sumsize / sizeof(daddr_t); dp--; idp = dp; - daddr = pseg_addr + (LFS_SUMMARY_SIZE / dev_bsize); + daddr = pseg_addr + btofsb(&sblock, sblock.lfs_sumsize); fp = (FINFO *)(sp + 1); for (i = 0, j = 0; i < sp->ss_nfinfo || j < howmany(sp->ss_ninos, INOPB(fs)); i++) { /* printf("*idp=%x, daddr=%x\n", *idp, daddr); */ @@ -333,22 +336,22 @@ check_summary(struct lfs * fs, SEGSUM * sp, daddr_t pseg_addr) break; } while (j < howmany(sp->ss_ninos, INOPB(fs)) && *idp == daddr) { - bp = getddblk(daddr, (1 << fs->lfs_bshift)); + bp = getddblk(daddr, fs->lfs_bsize); datap[datac++] = ((u_long *)(bp->b_un.b_buf))[0]; bp->b_flags &= ~B_INUSE; ++j; - daddr += (1 << fs->lfs_bshift) / dev_bsize; + daddr += btofsb(&sblock, fs->lfs_bsize); --idp; } if (i < sp->ss_nfinfo) { for (k = 0; k < fp->fi_nblocks; k++) { len = (k == fp->fi_nblocks - 1 ? fp->fi_lastlength - : (1 << fs->lfs_bshift)); + : fs->lfs_bsize); bp = getddblk(daddr, len); datap[datac++] = ((u_long *)(bp->b_un.b_buf))[0]; bp->b_flags &= ~B_INUSE; - daddr += len / dev_bsize; + daddr += btofsb(&sblock, len); } fp = (FINFO *)(fp->fi_blocks + fp->fi_nblocks); } diff --git a/sbin/fsck_lfs/pass1.c b/sbin/fsck_lfs/pass1.c index aacdd741ede..9104882dd34 100644 --- a/sbin/fsck_lfs/pass1.c +++ b/sbin/fsck_lfs/pass1.c @@ -1,4 +1,4 @@ -/* $NetBSD: pass1.c,v 1.10 2001/01/06 23:08:26 joff Exp $ */ +/* $NetBSD: pass1.c,v 1.11 2001/07/13 20:30:19 perseant Exp $ */ /* * Copyright (c) 1980, 1986, 1993 @@ -84,7 +84,7 @@ void pass1() { ino_t inumber; - int i, total_segments; + int i; struct inodesc idesc; struct dinode *idinode, *tinode; struct ifile *ifp; @@ -105,7 +105,6 @@ pass1() cp = (CLEANERINFO *)(pbp->b_un.b_buf); #endif - total_segments = sblock.lfs_size / sblock.lfs_bsize; /* * Find all allocated blocks, initialize numdirs. @@ -362,7 +361,7 @@ pass1check(struct inodesc * idesc) register struct dups *dlp; struct dups *new; - if ((anyout = chkrange(blkno, fragstodb(&sblock, idesc->id_numfrags))) != 0) { + if ((anyout = chkrange(blkno, fragstofsb(&sblock, idesc->id_numfrags))) != 0) { blkerror(idesc->id_number, "BAD", blkno); if (badblk++ >= MAXBAD) { pwarn("EXCESSIVE BAD BLKS I=%u", @@ -374,9 +373,9 @@ pass1check(struct inodesc * idesc) return (STOP); } } else if (!testbmap(blkno)) { - seg_table[datosn(&sblock, blkno)].su_nbytes += idesc->id_numfrags * sblock.lfs_fsize; + seg_table[dtosn(&sblock, blkno)].su_nbytes += idesc->id_numfrags * sblock.lfs_fsize; } - for (ndblks = fragstodb(&sblock, idesc->id_numfrags); ndblks > 0; blkno++, ndblks--) { + for (ndblks = fragstofsb(&sblock, idesc->id_numfrags); ndblks > 0; blkno++, ndblks--) { if (anyout && chkrange(blkno, 1)) { res = SKIP; } else if (!testbmap(blkno)) { diff --git a/sbin/fsck_lfs/pass5.c b/sbin/fsck_lfs/pass5.c index 4750be57a53..7733544e77e 100644 --- a/sbin/fsck_lfs/pass5.c +++ b/sbin/fsck_lfs/pass5.c @@ -1,4 +1,4 @@ -/* $NetBSD: pass5.c,v 1.8 2000/11/21 06:24:26 perseant Exp $ */ +/* $NetBSD: pass5.c,v 1.9 2001/07/13 20:30:19 perseant Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -61,6 +61,7 @@ pass5() unsigned long avail; /* blocks available for writing */ unsigned long dmeta; /* blocks in segsums and inodes */ int nclean; /* clean segments */ + size_t labelskew; /* * Check segment holdings against actual holdings. Check for @@ -97,24 +98,33 @@ pass5() } } if (su->su_flags & SEGUSE_DIRTY) { - bb += btodb(su->su_nbytes) + su->su_nsums; - ubb += btodb(su->su_nbytes) + su->su_nsums + fsbtodb(&sblock, su->su_ninos); - dmeta += btodb(LFS_SUMMARY_SIZE * su->su_nsums); - dmeta += fsbtodb(&sblock, su->su_ninos); + bb += btofsb(&sblock, su->su_nbytes + + su->su_nsums * sblock.lfs_sumsize); + ubb += btofsb(&sblock, su->su_nbytes + + su->su_nsums * sblock.lfs_sumsize + + su->su_ninos * sblock.lfs_ibsize); + dmeta += btofsb(&sblock, + sblock.lfs_sumsize * su->su_nsums); + dmeta += btofsb(&sblock, + sblock.lfs_ibsize * su->su_ninos); } else { nclean++; - avail += fsbtodb(&sblock, sblock.lfs_ssize); + avail += segtod(&sblock, 1); if (su->su_flags & SEGUSE_SUPERBLOCK) - avail -= btodb(LFS_SBPAD); + avail -= btofsb(&sblock, LFS_SBPAD); + if (i == 0 && sblock.lfs_version > 1 && + sblock.lfs_start < btofsb(&sblock, LFS_LABELPAD)) + avail -= btofsb(&sblock, LFS_LABELPAD) - + sblock.lfs_start; } bp->b_flags &= ~B_INUSE; } /* Also may be available bytes in current seg */ - i = datosn(&sblock, sblock.lfs_offset); - avail += sntoda(&sblock, i + 1) - sblock.lfs_offset; + i = dtosn(&sblock, sblock.lfs_offset); + avail += sntod(&sblock, i + 1) - sblock.lfs_offset; /* But do not count minfreesegs */ - avail -= fsbtodb(&sblock, sblock.lfs_ssize) * - (sblock.lfs_minfreeseg - (sblock.lfs_minfreeseg / 2)); + avail -= segtod(&sblock, (sblock.lfs_minfreeseg - + (sblock.lfs_minfreeseg / 2))); if (dmeta != sblock.lfs_dmeta) { pwarn("dmeta given as %d, should be %ld\n", sblock.lfs_dmeta, @@ -140,13 +150,16 @@ pass5() sbdirty(); } } - if (sblock.lfs_bfree > sblock.lfs_dsize - bb || - sblock.lfs_bfree < sblock.lfs_dsize - ubb) { + labelskew = (sblock.lfs_version == 1 ? 0 : + btofsb(&sblock, LFS_LABELPAD)); + if (sblock.lfs_bfree > sblock.lfs_dsize - bb - labelskew || + sblock.lfs_bfree < sblock.lfs_dsize - ubb - labelskew) { pwarn("bfree given as %d, should be between %ld and %ld\n", - sblock.lfs_bfree, sblock.lfs_dsize - ubb, - sblock.lfs_dsize - bb); + sblock.lfs_bfree, sblock.lfs_dsize - ubb - labelskew, + sblock.lfs_dsize - bb - labelskew); if (preen || reply("fix")) { - sblock.lfs_bfree = sblock.lfs_dsize - (ubb + bb) / 2; + sblock.lfs_bfree = sblock.lfs_dsize - labelskew - + (ubb + bb) / 2; sbdirty(); } } diff --git a/sbin/fsck_lfs/setup.c b/sbin/fsck_lfs/setup.c index 986d07816e9..ca046fac6f6 100644 --- a/sbin/fsck_lfs/setup.c +++ b/sbin/fsck_lfs/setup.c @@ -1,4 +1,4 @@ -/* $NetBSD: setup.c,v 1.8 2001/01/05 02:02:58 lukem Exp $ */ +/* $NetBSD: setup.c,v 1.9 2001/07/13 20:30:19 perseant Exp $ */ /* * Copyright (c) 1980, 1986, 1993 @@ -91,15 +91,16 @@ try_verify(struct lfs * osb, struct lfs * nsb) { daddr_t daddr; SEGSUM *sp; - char summary[LFS_SUMMARY_SIZE]; + char *summary; int bc, flag; daddr = osb->lfs_offset; + summary = malloc(osb->lfs_sumsize); while (daddr != nsb->lfs_offset) { flag = 0; oncemore: /* Read in summary block */ - bread(fsreadfd, summary, daddr, LFS_SUMMARY_SIZE); + bread(fsreadfd, summary, fsbtodb(osb, daddr), osb->lfs_sumsize); sp = (SEGSUM *)summary; /* @@ -108,10 +109,10 @@ oncemore: * setup before we can...fix this */ if (sp->ss_magic != SS_MAGIC || - sp->ss_sumsum != cksum(&sp->ss_datasum, LFS_SUMMARY_SIZE - + sp->ss_sumsum != cksum(&sp->ss_datasum, osb->lfs_sumsize - sizeof(sp->ss_sumsum))) { if (flag == 0) { - daddr += LFS_SBPAD / dev_bsize; + daddr += btofsb(osb, LFS_SBPAD); goto oncemore; } return 0x0; @@ -119,14 +120,33 @@ oncemore: bc = check_summary(osb, sp, daddr); if (bc == 0) break; - daddr += (LFS_SUMMARY_SIZE + bc) / dev_bsize; - if (datosn(osb, daddr) != datosn(osb, daddr + (LFS_SUMMARY_SIZE + (1 << osb->lfs_bshift)) / dev_bsize)) { + daddr += btofsb(osb, osb->lfs_sumsize + bc); + if (dtosn(osb, daddr) != dtosn(osb, daddr + + btofsb(osb, osb->lfs_sumsize + osb->lfs_bsize))) daddr = ((SEGSUM *)summary)->ss_next; - } } return daddr; } +u_quad_t maxtable[] = { + /* 1 */ -1, + /* 2 */ -1, + /* 4 */ -1, + /* 8 */ -1, + /* 16 */ -1, + /* 32 */ -1, + /* 64 */ -1, + /* 128 */ -1, + /* 256 */ -1, + /* 512 */ NDADDR + 128 + 128 * 128 + 128 * 128 * 128, + /* 1024 */ NDADDR + 256 + 256 * 256 + 256 * 256 * 256, + /* 2048 */ NDADDR + 512 + 512 * 512 + 512 * 512 * 512, + /* 4096 */ NDADDR + 1024 + 1024 * 1024 + 1024 * 1024 * 1024, + /* 8192 */ 1 << 31, + /* 16 K */ 1 << 31, + /* 32 K */ 1 << 31, + }; + int setup(const char *dev) { @@ -218,6 +238,22 @@ setup(const char *dev) if (bflag == 0x0 && idaddr == 0x0) { /* + * If we read a proper superblock, but its address was not + * lfs_sboffs[0], we're holding a fake primary superblock, + * and need to read the real one. + */ + if (sblock.lfs_sboffs[0] != dbtofsb(&sblock, + LFS_LABELPAD / dev_bsize)) + { + if (debug) + pwarn("Getting 'real' prinary superblock from 0x%x\n", + fsbtodb(&sblock, sblock.lfs_sboffs[0])); + bflag = fsbtodb(&sblock, sblock.lfs_sboffs[0]); + readsb(1); + bflag = 0; + } + + /* * Even if that superblock read in properly, it may not * be guaranteed to point to a complete checkpoint. * Read in the second superblock too, and take whichever @@ -226,7 +262,7 @@ setup(const char *dev) sb0 = malloc(sizeof(*sb0)); sb1 = malloc(sizeof(*sb1)); memcpy(sb0, &sblock, sizeof(*sb0)); - bflag = sblock.lfs_sboffs[1]; + bflag = fsbtodb(&sblock, sblock.lfs_sboffs[1]); if (readsb(1) == 0) { pwarn("COULDN'T READ ALT SUPERBLOCK AT BLK %d", bflag); if (reply("ASSUME PRIMARY SUPERBLOCK IS GOOD") == 0) { @@ -236,32 +272,55 @@ setup(const char *dev) } } else { memcpy(sb1, &sblock, sizeof(*sb1)); - if (debug) - pwarn("sb0 %d, sb1 %d\n", sb0->lfs_tstamp, sblock.lfs_tstamp); + if (debug) { + if (sb0->lfs_version > 1) { + pwarn("sb0 sn=%lld, sb1 sn=%lld\n", + (long long)sb0->lfs_serial, + (long long)sblock.lfs_serial); + } else { + pwarn("sb0 %lld, sb1 %lld\n", + (long long)sb0->lfs_otstamp, + (long long)sblock.lfs_otstamp); + } + } /* * Verify the checkpoint of the newer superblock, * if the timestamp of the two superblocks is * different. XXX use lfs_offset instead, discover * how to quickly discover "newness" based on that. */ - if (sb0->lfs_tstamp != sb1->lfs_tstamp) { - if (sb0->lfs_tstamp > sb1->lfs_tstamp) { - osb = sb1; - nsb = sb0; + if ((sb0->lfs_version == 1 && + sb0->lfs_otstamp != sb1->lfs_otstamp) || + (sb0->lfs_version > 1 && + sb0->lfs_serial != sb1->lfs_serial)) { + if (sb0->lfs_version == 1) { + if (sb0->lfs_otstamp > sb1->lfs_otstamp) { + osb = sb1; + nsb = sb0; + } else { + osb = sb0; + nsb = sb1; + } } else { - osb = sb0; - nsb = sb1; + if (sb0->lfs_serial > sb1->lfs_serial) { + osb = sb1; + nsb = sb0; + } else { + osb = sb0; + nsb = sb1; + } } daddr = try_verify(osb, nsb); if (debug) printf("done.\n"); if (daddr == nsb->lfs_offset) { - pwarn("Checkpoint verified, recovered %d seconds of data\n", nsb->lfs_tstamp - osb->lfs_tstamp); + pwarn("Checkpoint verified, recovered %lld seconds of data\n", + (long long)nsb->lfs_tstamp - (long long)osb->lfs_tstamp); memcpy(&sblock, nsb, sizeof(*nsb)); sbdirty(); } else { - pwarn("Checkpoint invalid, lost %d seconds of data\n", nsb->lfs_tstamp - osb->lfs_tstamp); + pwarn("Checkpoint invalid, lost %lld seconds of data\n", (long long)nsb->lfs_tstamp - (long long)osb->lfs_tstamp); memcpy(&sblock, osb, sizeof(*osb)); } } @@ -276,73 +335,47 @@ setup(const char *dev) printf("lfs_bsize = %lu\n", (unsigned long)sblock.lfs_bsize); printf("lfs_fsize = %lu\n", (unsigned long)sblock.lfs_fsize); printf("lfs_frag = %lu\n", (unsigned long)sblock.lfs_frag); - printf("INOPB(fs) = %lu\n", (unsigned long) INOPB(&sblock)); + printf("INOPB(fs) = %lu\n", (unsigned long)INOPB(&sblock)); + if (sblock.lfs_version > 1) + printf("INOPF(fs) = %lu\n", + (unsigned long)INOPF(&sblock)); /* printf("fsbtodb(fs,1) = %lu\n",fsbtodb(&sblock,1)); */ } -#if 0 /* FFS-specific fs-clean check */ - if (debug) - printf("clean = %d\n", sblock.lfs_clean); - if (sblock.lfs_clean & FS_ISCLEAN) { - if (doskipclean) { - pwarn("%sile system is clean; not checking\n", - preen ? "f" : "** F"); - return (-1); - } - if (!preen) - pwarn("** File system is already clean\n"); + /* Compatibility */ + if (sblock.lfs_version == 1) { + sblock.lfs_sumsize = LFS_V1_SUMMARY_SIZE; + sblock.lfs_ibsize = sblock.lfs_bsize; + sblock.lfs_start = sblock.lfs_sboffs[0]; + sblock.lfs_fsbtodb = 0; } - maxino = sblock.lfs_ncg * sblock.lfs_ipg; -#else initbarea(&iblk); - iblk.b_un.b_buf = malloc(sblock.lfs_bsize); - if (bread(fsreadfd, (char *)iblk.b_un.b_buf, idaddr, - (long)sblock.lfs_bsize) != 0) { + iblk.b_un.b_buf = malloc(sblock.lfs_ibsize); + if (bread(fsreadfd, (char *)iblk.b_un.b_buf, fsbtodb(&sblock, idaddr), + (long)sblock.lfs_ibsize) != 0) { printf("Couldn't read disk block %d\n", idaddr); exit(1); } idinode = lfs_difind(&sblock, sblock.lfs_ifile, &ifblock); + if (idinode == NULL) { + printf("Ifile inode not found at daddr 0x%x\n", idaddr); + exit(1); + /* XXX find it in the segment summaries */ + } + maxino = ((idinode->di_size - (sblock.lfs_cleansz + sblock.lfs_segtabsz) * sblock.lfs_bsize) / sblock.lfs_bsize) * sblock.lfs_ifpb; if (debug) - printf("maxino=%d\n", maxino); + printf("maxino = %d\n", maxino); din_table = (daddr_t *)malloc(maxino * sizeof(*din_table)); memset(din_table, 0, maxino * sizeof(*din_table)); seg_table = (SEGUSE *)malloc(sblock.lfs_nseg * sizeof(SEGUSE)); memset(seg_table, 0, sblock.lfs_nseg * sizeof(SEGUSE)); -#endif - maxfsblock = sblock.lfs_size * (sblock.lfs_bsize / dev_bsize); -#if 0 - sizepb = sblock.lfs_bsize; - maxfilesize = sblock.lfs_bsize * NDADDR - 1; - for (i = 0; i < NIADDR; i++) { - sizepb *= NINDIR(&sblock); - maxfilesize += sizepb; - } - maxfilesize++; /* XXX */ -#else /* LFS way */ - { - u_quad_t maxtable[] = { - /* 1 */ -1, - /* 2 */ -1, - /* 4 */ -1, - /* 8 */ -1, - /* 16 */ -1, - /* 32 */ -1, - /* 64 */ -1, - /* 128 */ -1, - /* 256 */ -1, - /* 512 */ NDADDR + 128 + 128 * 128 + 128 * 128 * 128, - /* 1024 */ NDADDR + 256 + 256 * 256 + 256 * 256 * 256, - /* 2048 */ NDADDR + 512 + 512 * 512 + 512 * 512 * 512, - /* 4096 */ NDADDR + 1024 + 1024 * 1024 + 1024 * 1024 * 1024, - /* 8192 */ 1 << 31, - /* 16 K */ 1 << 31, - /* 32 K */ 1 << 31, - }; - maxfilesize = maxtable[sblock.lfs_bshift] << sblock.lfs_bshift; - } -#endif + if (sblock.lfs_version == 1) + maxfsblock = sblock.lfs_size * (sblock.lfs_bsize / dev_bsize); + else + maxfsblock = sblock.lfs_size; + maxfilesize = maxtable[sblock.lfs_bshift] << sblock.lfs_bshift; if ((sblock.lfs_minfree < 0 || sblock.lfs_minfree > 99)) { pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK", sblock.lfs_minfree); @@ -351,7 +384,6 @@ setup(const char *dev) sbdirty(); } } - /* XXX used to be ~(sblock.lfs_bsize - 1) */ if (sblock.lfs_bmask != sblock.lfs_bsize - 1) { pwarn("INCORRECT BMASK=%x IN SUPERBLOCK (should be %x)", (unsigned int)sblock.lfs_bmask, diff --git a/sbin/fsck_lfs/utilities.c b/sbin/fsck_lfs/utilities.c index 470bf3dde71..df558375f71 100644 --- a/sbin/fsck_lfs/utilities.c +++ b/sbin/fsck_lfs/utilities.c @@ -1,4 +1,4 @@ -/* $NetBSD: utilities.c,v 1.7 2001/02/04 21:52:04 christos Exp $ */ +/* $NetBSD: utilities.c,v 1.8 2001/07/13 20:30:19 perseant Exp $ */ /* * Copyright (c) 1980, 1986, 1993 @@ -184,7 +184,7 @@ foundit: struct bufarea * getdatablk(daddr_t blkno, long size) { - return getddblk(fsbtodb(&sblock, blkno), size); + return getddblk(blkno, size); } void @@ -193,16 +193,18 @@ getdblk(struct bufarea * bp, daddr_t blk, long size) if (bp->b_bno != blk) { flush(fswritefd, bp); diskreads++; - bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, blk, size); + bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, + fsbtodb(&sblock, blk), size); bp->b_bno = blk; bp->b_size = size; } } + void getblk(struct bufarea * bp, daddr_t blk, long size) { - getdblk(bp, fsbtodb(&sblock, blk), size); + getdblk(bp, blk, size); } void @@ -251,20 +253,21 @@ ckfini(int markclean) return; } flush(fswritefd, &sblk); - if (havesb && sblk.b_bno != LFS_LABELPAD / dev_bsize && - sblk.b_bno != sblock.lfs_sboffs[0] && + if (havesb && sblk.b_bno != sblock.lfs_sboffs[0] && + sblk.b_bno != sblock.lfs_sboffs[1] && !preen && reply("UPDATE STANDARD SUPERBLOCKS")) { - sblk.b_bno = LFS_LABELPAD / dev_bsize; + sblk.b_bno = fsbtodb(&sblock, sblock.lfs_sboffs[0]); sbdirty(); flush(fswritefd, &sblk); } if (havesb) { - if (sblk.b_bno == LFS_LABELPAD / dev_bsize) { + if (sblk.b_bno == fsbtodb(&sblock, sblock.lfs_sboffs[0])) { /* Do the first alternate */ - sblk.b_bno = sblock.lfs_sboffs[1]; + sblk.b_bno = fsbtodb(&sblock, sblock.lfs_sboffs[1]); sbdirty(); flush(fswritefd, &sblk); - } else if (sblk.b_bno == sblock.lfs_sboffs[1]) { + } else if (sblk.b_bno == + fsbtodb(&sblock, sblock.lfs_sboffs[1])) { /* Do the primary */ sblk.b_bno = LFS_LABELPAD / dev_bsize; sbdirty(); @@ -283,7 +286,7 @@ ckfini(int markclean) if (bufhead.b_size != cnt) errexit("Panic: lost %d buffers\n", bufhead.b_size - cnt); pbp = pdirbp = (struct bufarea *)0; - if (markclean && sblock.lfs_clean == 0) { + if (markclean && !(sblock.lfs_pflags & LFS_PF_CLEAN)) { /* * Mark the file system as clean, and sync the superblock. */ @@ -292,14 +295,16 @@ ckfini(int markclean) else if (!reply("MARK FILE SYSTEM CLEAN")) markclean = 0; if (markclean) { - sblock.lfs_clean = 1; + sblock.lfs_pflags |= LFS_PF_CLEAN; sbdirty(); flush(fswritefd, &sblk); if (sblk.b_bno == LFS_LABELPAD / dev_bsize) { /* Do the first alternate */ - sblk.b_bno = sblock.lfs_sboffs[0]; + sblk.b_bno = fsbtodb(&sblock, + sblock.lfs_sboffs[0]); flush(fswritefd, &sblk); - } else if (sblk.b_bno == sblock.lfs_sboffs[0]) { + } else if (sblk.b_bno == fsbtodb(&sblock, + sblock.lfs_sboffs[0])) { /* Do the primary */ sblk.b_bno = LFS_LABELPAD / dev_bsize; flush(fswritefd, &sblk); diff --git a/sbin/newfs_lfs/config.h b/sbin/newfs_lfs/config.h index bf7c4de62ce..614d6f24b4e 100644 --- a/sbin/newfs_lfs/config.h +++ b/sbin/newfs_lfs/config.h @@ -1,4 +1,4 @@ -/* $NetBSD: config.h,v 1.5 2000/09/09 04:49:56 perseant Exp $ */ +/* $NetBSD: config.h,v 1.6 2001/07/13 20:30:19 perseant Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -36,11 +36,9 @@ */ /* - * The first boot and super blocks are given in absolute disk addresses. - * The byte-offset forms are preferred, as they don't imply a sector size. + * Version of the LFS to make. Default to the newest one. */ -#define BBSIZE 8192 -#define SBSIZE 8192 +#define DFL_VERSION LFS_VERSION /* * The following two constants set the default block and fragment sizes. @@ -49,7 +47,7 @@ * sectorsize <= DESFRAGSIZE <= DESBLKSIZE * DESBLKSIZE / DESFRAGSIZE <= 8 */ -#define DFL_FRAGSIZE 1024 +#define DFL_FRAGSIZE 512 #define DFL_BLKSIZE 8192 /* @@ -67,11 +65,10 @@ /* * The following constants set the default block and segment size for a log - * structured file system. Both must be powers of two and the segment size - * must be a multiple of the block size. We also set minimum block and segment - * sizes. + * structured file system. The block size must be a power of two and less + * than the segment size. */ -#define LFS_MINSEGSIZE (64*1024) +#define LFS_MINSEGSIZE (64 * 1024) #define DFL_LFSSEG (1024 * 1024) #define DFL_LFSSEG_SHIFT 20 #define DFL_LFSSEG_MASK 0xFFFFF diff --git a/sbin/newfs_lfs/extern.h b/sbin/newfs_lfs/extern.h index db754074a98..cbd87694ec7 100644 --- a/sbin/newfs_lfs/extern.h +++ b/sbin/newfs_lfs/extern.h @@ -1,4 +1,4 @@ -/* $NetBSD: extern.h,v 1.4 2000/12/05 19:51:14 perseant Exp $ */ +/* $NetBSD: extern.h,v 1.5 2001/07/13 20:30:20 perseant Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -37,15 +37,14 @@ struct dlfs; -u_long lfs_sb_cksum __P((struct dlfs *)); -u_long cksum __P((void *, size_t)); -u_short dkcksum __P((struct disklabel *)); -void fatal __P((const char *fmt, ...)) +u_long lfs_sb_cksum(struct dlfs *); +u_long cksum(void *, size_t); +u_short dkcksum(struct disklabel *); +void fatal(const char *fmt, ...) __attribute__((__format__(__printf__,1,2))); -u_int log2 __P((u_int)); -int make_lfs - __P((int, struct disklabel *, struct partition *, int, - int, int, int, int)); +u_int log2(u_int); +int make_lfs(int, struct disklabel *, struct partition *, int, + int, int, int, int, int, int, int, int, u_int32_t); extern char *progname; extern char *special; diff --git a/sbin/newfs_lfs/lfs.c b/sbin/newfs_lfs/lfs.c index 624a2654370..28ffb1833a2 100644 --- a/sbin/newfs_lfs/lfs.c +++ b/sbin/newfs_lfs/lfs.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs.c,v 1.21 2000/11/23 23:09:57 perseant Exp $ */ +/* $NetBSD: lfs.c,v 1.22 2001/07/13 20:30:20 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.21 2000/11/23 23:09:57 perseant Exp $"); +__RCSID("$NetBSD: lfs.c,v 1.22 2001/07/13 20:30:20 perseant Exp $"); #endif #endif /* not lint */ @@ -66,13 +66,14 @@ __RCSID("$NetBSD: lfs.c,v 1.21 2000/11/23 23:09:57 perseant Exp $"); #include "extern.h" extern int Nflag; /* Don't write anything */ -daddr_t *ifib = NULL; /* Ifile single indirect block (lbn -NDADDR) */ +daddr_t **ifibp = NULL; /* Ifile single indirect blocks */ +int ifibc; /* Number of indirect blocks */ /* * This table is indexed by the log base 2 of the block size. * It returns the maximum file size allowed in a file system * with the specified block size. For block sizes smaller than - * 8K, the size is limited by tha maximum number of blocks that + * 8K, the size is limited by the maximum number of blocks that * can be reached by triply indirect blocks: * NDADDR + INOPB(bsize) + INOPB(bsize)^2 + INOPB(bsize)^3 * For block size of 8K or larger, the file size is limited by the @@ -105,7 +106,7 @@ static struct lfs lfs_default = { /* dlfs_magic */ LFS_MAGIC, /* dlfs_version */ LFS_VERSION, /* dlfs_size */ 0, - /* dlfs_ssize */ DFL_LFSSEG/DFL_LFSBLOCK, + /* dlfs_ssize */ DFL_LFSSEG, /* dlfs_dsize */ 0, /* dlfs_bsize */ DFL_LFSBLOCK, /* dlfs_fsize */ DFL_LFSFRAG, @@ -122,10 +123,10 @@ static struct lfs lfs_default = { /* dlfs_curseg */ 0, /* dlfs_offset */ 0, /* dlfs_lastpseg */ 0, - /* dlfs_tstamp */ 0, + /* dlfs_inopf */ 0, /* dlfs_minfree */ MINFREE, /* dlfs_maxfilesize */ 0, - /* dlfs_dbpseg */ DFL_LFSSEG/DEV_BSIZE, + /* dlfs_fsbpseg */ 0, /* dlfs_inopb */ DFL_LFSBLOCK/sizeof(struct dinode), /* dlfs_ifpb */ DFL_LFSBLOCK/sizeof(IFILE), /* dlfs_sepb */ DFL_LFSBLOCK/sizeof(SEGUSE), @@ -142,15 +143,24 @@ static struct lfs lfs_default = { /* dlfs_bmask */ DFL_LFSBLOCK_MASK, /* dlfs_ffmask */ DFL_LFS_FFMASK, /* dlfs_fbmask */ DFL_LFS_FBMASK, - /* dlfs_fsbtodb */ 0, + /* dlfs_blktodb */ 0, /* dlfs_sushift */ 0, /* dlfs_maxsymlinklen */ MAXSYMLINKLEN, /* dlfs_sboffs */ { 0 }, /* dlfs_nclean */ 0, /* dlfs_fsmnt */ { 0 }, - /* dlfs_clean */ 0, + /* dlfs_pflags */ 0, /* dlfs_dmeta */ 0, /* dlfs_minfreeseg */ 0, + /* dlfs_sumsize */ 0, + /* dlfs_serial */ 0, + /* dlfs_ibsize */ DFL_LFSFRAG, + /* dlfs_start */ 0, + /* dlfs_inodefmt */ LFS_44INODEFMT, + /* dlfs_tstamp */ 0, + /* dlfs_interleave */ 0, + /* dlfs_ident */ 0, + /* dlfs_fsbtodb */ 0, /* dlfs_pad */ { 0 }, /* dlfs_cksum */ 0 @@ -183,21 +193,15 @@ struct direct lfs_lf_dir[] = { { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, }; -static daddr_t make_dinode - __P((ino_t, struct dinode *, int, daddr_t, struct lfs *)); -static void make_dir __P(( void *, struct direct *, int)); -static void put __P((int, off_t, void *, size_t)); +static daddr_t make_dinode(ino_t, struct dinode *, int, daddr_t, struct lfs *); +static void make_dir( void *, struct direct *, int); +static void put(int, off_t, void *, size_t); int -make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) - int fd; - struct disklabel *lp; - struct partition *partp; - int minfree; - int block_size; - int frag_size; - int seg_size; - int minfreeseg; +make_lfs(int fd, struct disklabel *lp, struct partition *partp, int minfree, + int block_size, int frag_size, int seg_size, int minfreeseg, + int version, daddr_t start, int ibsize, int interleave, + u_int32_t roll_id) { struct dinode *dip; /* Pointer to a disk inode */ struct dinode *dpagep; /* Pointer to page of disk inodes */ @@ -205,6 +209,7 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) FINFO file_info; /* File info structure in summary blocks */ IFILE *ifile; /* Pointer to array of ifile structures */ IFILE *ip; /* Pointer to array of ifile structures */ + IFILE_V1 *ifile_v1, *ip_v1; struct lfs *lfsp; /* Superblock */ SEGUSE *segp; /* Segment usage table */ SEGUSE *segtable; /* Segment usage table */ @@ -222,17 +227,23 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) int block_array_size; /* How many entries in block array */ int bsize; /* Block size */ int fsize; /* Fragment size */ - int db_per_fb; /* Disk blocks per file block */ + int db_per_blk; /* Disk blocks per file block */ int i, j; - off_t off; /* Offset at which to write */ + off_t off, startoff; /* Offset at which to write */ int sb_interval; /* number of segs between super blocks */ off_t seg_seek; /* Seek offset for a segment */ int ssize; /* Segment size */ int sum_size; /* Size of the summary block */ int warned_segtoobig=0; + double fssize; + int label_fsb, sb_fsb; + int curw, ww; + char tbuf[BUFSIZ]; lfsp = &lfs_default; + lfsp->lfs_version = version; + /* If partition is not an LFS partition, warn that that is the case */ if(partp->p_fstype != FS_BSDLFS) { fatal("partition label indicated fs type \"%s\", expected \"%s\"", @@ -245,12 +256,21 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) if (!(fsize = frag_size)) if (!(fsize = partp->p_fsize)) fsize = DFL_LFSFRAG; - if (!(ssize = seg_size)) + if (!(ssize = seg_size)) { + ssize = DFL_LFSSEG; if (partp->p_sgs == 0 || !(ssize = (partp->p_fsize * partp->p_frag) << partp->p_sgs)) { ssize = DFL_LFSSEG; } + } + if (version > 1) { + if (ibsize == 0) + ibsize = fsize; + if (ibsize <= 0 || ibsize % fsize) + fatal("illegal inode block size: %d\n", ibsize); + } else if (ibsize && ibsize != bsize) + fatal("cannot specify inode block size when version == 1\n"); /* Sanity check: fsize<=bsize<ssize */ if (fsize > bsize) { @@ -267,6 +287,13 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) progname, ssize, DFL_LFSSEG); ssize = DFL_LFSSEG; } + if (start < 0 || start >= partp->p_size) + fatal("filesystem offset %ld out of range", (long)start); + if (version == 1) { + if (start) + warnx("filesystem offset ignored for version 1 filesystem"); + start = LFS_LABELPAD / lp->d_secsize; + } tryagain: /* Modify parts of superblock overridden by command line arguments */ @@ -277,7 +304,6 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) lfsp->lfs_bsize = bsize; lfsp->lfs_fsize = fsize; lfsp->lfs_bmask = bsize - 1; - lfsp->lfs_inopb = bsize / sizeof(struct dinode); lfsp->lfs_ffmask = fsize - 1; lfsp->lfs_ffshift = log2(fsize); if (1 << lfsp->lfs_ffshift != fsize) @@ -285,33 +311,69 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) lfsp->lfs_frag = numfrags(lfsp, bsize); lfsp->lfs_fbmask = lfsp->lfs_frag - 1; lfsp->lfs_fbshift = log2(lfsp->lfs_frag); -/* MIS -- should I round to power of 2 */ lfsp->lfs_ifpb = bsize / sizeof(IFILE); - lfsp->lfs_sepb = bsize / sizeof(SEGUSE); lfsp->lfs_nindir = bsize / sizeof(daddr_t); } - if (ssize != DFL_LFSSEG) { + if (lfsp->lfs_version == 1) { + lfsp->lfs_sumsize = LFS_V1_SUMMARY_SIZE; lfsp->lfs_segshift = log2(ssize); if (1 << lfsp->lfs_segshift != ssize) fatal("%d: segment size not power of 2", ssize); - lfsp->lfs_ssize = ssize; lfsp->lfs_segmask = ssize - 1; - lfsp->lfs_dbpseg = ssize / DEV_BSIZE; + lfsp->lfs_ifpb = lfsp->lfs_bsize / sizeof(IFILE_V1); + lfsp->lfs_ibsize = lfsp->lfs_bsize; + lfsp->lfs_sepb = bsize / sizeof(SEGUSE_V1); + lfsp->lfs_ssize = ssize >> lfsp->lfs_bshift; + } else { + if (ssize % fsize) { + fprintf(stderr, + "Segment size %d is not a multiple of frag size; ", + ssize); + ssize = roundup(ssize, fsize); + fprintf(stderr, "trying size %d.\n", ssize); + goto tryagain; + } + lfsp->lfs_sumsize = fsize; + lfsp->lfs_segshift = 0; + lfsp->lfs_segmask = 0; + lfsp->lfs_sepb = bsize / sizeof(SEGUSE); + lfsp->lfs_ssize = ssize; + lfsp->lfs_ibsize = ibsize; } - lfsp->lfs_ssize = ssize >> lfsp->lfs_bshift; + lfsp->lfs_inopb = lfsp->lfs_ibsize / sizeof(struct dinode); lfsp->lfs_minfree = minfree; + if (version > 1) { + lfsp->lfs_inopf = lp->d_secsize/DINODE_SIZE; + lfsp->lfs_interleave = interleave; + if (roll_id == 0) { + /* Pick one; even time(NULL) would almost do */ + srandom(time(NULL)); + roll_id = random(); + } + lfsp->lfs_ident = roll_id; + } + /* * Fill in parts of superblock that can be computed from file system * size, disk geometry and current time. */ - db_per_fb = bsize/lp->d_secsize; - lfsp->lfs_fsbtodb = log2(db_per_fb); - lfsp->lfs_sushift = log2(lfsp->lfs_sepb); + db_per_blk = bsize/lp->d_secsize; + lfsp->lfs_blktodb = log2(db_per_blk); + lfsp->lfs_fsbtodb = log2(fsize / lp->d_secsize); + if (version == 1) { + lfsp->lfs_sushift = log2(lfsp->lfs_sepb); + lfsp->lfs_fsbtodb = 0; + lfsp->lfs_size = partp->p_size >> lfsp->lfs_blktodb; + } + label_fsb = btofsb(lfsp, roundup(LFS_LABELPAD, fsize)); + sb_fsb = btofsb(lfsp, roundup(LFS_SBPAD, fsize)); + lfsp->lfs_fsbpseg = dbtofsb(lfsp, ssize / lp->d_secsize); lfsp->lfs_size = partp->p_size >> lfsp->lfs_fsbtodb; - lfsp->lfs_dsize = lfsp->lfs_size - (LFS_LABELPAD >> lfsp->lfs_bshift); - lfsp->lfs_nseg = lfsp->lfs_dsize / lfsp->lfs_ssize; + lfsp->lfs_dsize = dbtofsb(lfsp, partp->p_size) - + MAX(label_fsb, dbtofsb(lfsp, start)); + lfsp->lfs_nseg = lfsp->lfs_dsize / segtod(lfsp, 1); lfsp->lfs_nclean = lfsp->lfs_nseg - 1; lfsp->lfs_maxfilesize = maxtable[lfsp->lfs_bshift] << lfsp->lfs_bshift; @@ -327,23 +389,24 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) { if(seg_size == 0 && ssize > (bsize<<1)) { if(!warned_segtoobig) { - fprintf(stderr,"Segment size %d is too large; trying smaller sizes.\n", ssize); + fprintf(stderr,"Segment size %d is too large; " + "trying smaller sizes.\n", ssize); if (ssize == (bsize << 16)) { - fprintf(stderr, "(Did you perhaps accidentally leave \"16\" in the disklabel's sgs field?)\n"); + fprintf(stderr, "(Did you perhaps " + "accidentally leave \"16\" " + "in the disklabel's sgs " + "field?)\n"); } } ++warned_segtoobig; ssize >>= 1; goto tryagain; } - fatal("Could not allocate enough segments with segment size %d and block size %d;\nplease decrease the segment size.\n", - ssize, lfsp->lfs_bsize); + fatal("Could not allocate enough segments with segment " + "size %d and block size %d;\nplease decrease the " + "segment size.\n", ssize, lfsp->lfs_bsize); } - printf("%.1fMB in %d segments of size %d\n", - (lfsp->lfs_nseg * (double)ssize) / 1048576.0, - lfsp->lfs_nseg, ssize); - /* * The number of free blocks is set from the number of segments * times the segment size - lfs_minfreesegs (that we never write @@ -353,19 +416,24 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) * be written due to fragmentation. */ lfsp->lfs_dsize = (lfsp->lfs_nseg - lfsp->lfs_minfreeseg) * - fsbtodb(lfsp, lfsp->lfs_ssize); - + segtod(lfsp, 1); lfsp->lfs_bfree = lfsp->lfs_dsize; - lfsp->lfs_bfree -= fsbtodb(lfsp, lfsp->lfs_nseg / 2); + lfsp->lfs_bfree -= dbtofsb(lfsp, ((lfsp->lfs_nseg / 2) << + lfsp->lfs_blktodb)); + lfsp->lfs_segtabsz = SEGTABSIZE_SU(lfsp); lfsp->lfs_cleansz = CLEANSIZE_SU(lfsp); if ((lfsp->lfs_tstamp = time(NULL)) == -1) fatal("time: %s", strerror(errno)); + if (version == 1) + lfsp->lfs_otstamp = lfsp->lfs_tstamp; + if ((sb_interval = lfsp->lfs_nseg / LFS_MAXNUMSB) < LFS_MIN_SBINTERVAL) sb_interval = LFS_MIN_SBINTERVAL; /* To start, one inode block and one segsum are dirty metadata */ - lfsp->lfs_dmeta = 1 + fsbtodb(lfsp, 1); + lfsp->lfs_dmeta = btofsb(lfsp, lfsp->lfs_sumsize + lfsp->lfs_ibsize); + /* * Now, lay out the file system. We need to figure out where * the superblocks go, initialize the checkpoint information @@ -376,27 +444,33 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) */ /* Figure out where the superblocks are going to live */ - lfsp->lfs_sboffs[0] = btodb(LFS_LABELPAD); - lfsp->lfs_dsize -= btodb(LFS_SBPAD); + lfsp->lfs_sboffs[0] = label_fsb; + if (version == 1) + lfsp->lfs_start = lfsp->lfs_sboffs[0]; + else + lfsp->lfs_start = dbtofsb(lfsp, start); + lfsp->lfs_dsize -= sb_fsb; for (i = 1; i < LFS_MAXNUMSB; i++) { - sb_addr = ((i * sb_interval) << - (lfsp->lfs_segshift - lfsp->lfs_bshift + lfsp->lfs_fsbtodb)) + sb_addr = ((i * sb_interval) * segtod(lfsp, 1)) + lfsp->lfs_sboffs[0]; - if (sb_addr > partp->p_size) + /* Segment 0 eats the label, except for version 1 */ + if (lfsp->lfs_version > 1 && lfsp->lfs_start < label_fsb) + sb_addr -= label_fsb - start; + if (sb_addr > dbtofsb(lfsp, partp->p_size)) break; lfsp->lfs_sboffs[i] = sb_addr; - lfsp->lfs_dsize -= btodb(LFS_SBPAD); + lfsp->lfs_dsize -= sb_fsb; } /* We need >= 2 superblocks */ if(lfsp->lfs_sboffs[1] == 0x0) { - fatal("Could not assign a disk adress for the second superblock.\nPlease decrease the segment size.\n"); + fatal("Could not assign a disk adress for the second " + "superblock.\nPlease decrease the segment size.\n"); } last_sb_addr = lfsp->lfs_sboffs[i - 1]; - lfsp->lfs_lastseg = lfsp->lfs_sboffs[0]; - lfsp->lfs_nextseg = - lfsp->lfs_sboffs[1] ? lfsp->lfs_sboffs[1] : lfsp->lfs_sboffs[0]; + lfsp->lfs_lastseg = sntod(lfsp, 0); + lfsp->lfs_nextseg = sntod(lfsp, 1); lfsp->lfs_curseg = lfsp->lfs_lastseg; /* @@ -410,36 +484,48 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) fatal("%s", strerror(errno)); cleaninfo->clean = lfsp->lfs_nseg - 1; cleaninfo->dirty = 1; + if (version > 1) { + cleaninfo->free_head = LFS_FIRST_INUM; + cleaninfo->free_tail = lfsp->lfs_ifpb - 1; + } if (!(segtable = malloc(lfsp->lfs_segtabsz << lfsp->lfs_bshift))) fatal("%s", strerror(errno)); + memset(segtable, 0, lfsp->lfs_segtabsz << lfsp->lfs_bshift); segp = segtable; blocks_used = lfsp->lfs_segtabsz + lfsp->lfs_cleansz + 4; segp->su_nbytes = ((lfsp->lfs_segtabsz + lfsp->lfs_cleansz + 1) << lfsp->lfs_bshift) + - 2 * roundup(DIRBLKSIZ,lfsp->lfs_fsize) + + 2 * roundup(DIRBLKSIZ, lfsp->lfs_fsize) + 3 * DINODE_SIZE; - segp->su_lastmod = lfsp->lfs_tstamp; + if (version == 1) + segp->su_olastmod = lfsp->lfs_tstamp; + else + segp->su_lastmod = lfsp->lfs_tstamp; segp->su_nsums = 1; /* 1 summary blocks */ segp->su_ninos = 1; /* 1 inode block */ segp->su_flags = SEGUSE_SUPERBLOCK | SEGUSE_DIRTY; - lfsp->lfs_bfree -= btodb(LFS_SUMMARY_SIZE); - lfsp->lfs_bfree -= - fsbtodb(lfsp, lfsp->lfs_cleansz + lfsp->lfs_segtabsz + 4); + lfsp->lfs_bfree -= btofsb(lfsp, lfsp->lfs_sumsize); + lfsp->lfs_bfree -= fragstofsb(lfsp, blkstofrags(lfsp, + (lfsp->lfs_cleansz + lfsp->lfs_segtabsz + 4))); /* * Now figure out the address of the ifile inode. The inode block * appears immediately after the segment summary. */ - lfsp->lfs_idaddr = (LFS_LABELPAD + LFS_SBPAD + LFS_SUMMARY_SIZE) / - lp->d_secsize; - - j = 1; - for (segp = segtable + 1, i = 1; i < lfsp->lfs_nseg; i++, segp++) { + lfsp->lfs_idaddr = label_fsb + sb_fsb + + btofsb(lfsp, lfsp->lfs_sumsize); + + for (i = 1, j = 1; i < lfsp->lfs_nseg; i++) { + segp = (SEGUSE *)(((char *)segtable) + + ((i / lfsp->lfs_sepb) << lfsp->lfs_bshift) + + (i % lfsp->lfs_sepb) * (version == 1 ? + sizeof(SEGUSE_V1) : + sizeof(SEGUSE))); if ((i % sb_interval) == 0 && j < LFS_MAXNUMSB) { segp->su_flags = SEGUSE_SUPERBLOCK; - lfsp->lfs_bfree -= (LFS_SBPAD / lp->d_secsize); + lfsp->lfs_bfree -= sb_fsb; ++j; } else segp->su_flags = 0; @@ -466,50 +552,72 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) lfsp->lfs_nfiles = LFS_FIRST_INUM - 1; /* Now create a block of disk inodes */ - if (!(dpagep = malloc(lfsp->lfs_bsize))) + if (!(dpagep = malloc(lfsp->lfs_ibsize))) fatal("%s", strerror(errno)); dip = (struct dinode *)dpagep; - memset(dip, 0, lfsp->lfs_bsize); + memset(dip, 0, lfsp->lfs_ibsize); /* Create a block of IFILE structures. */ if (!(ipagep = (char *)malloc(lfsp->lfs_bsize))) fatal("%s", strerror(errno)); - ifile = (IFILE *)ipagep; + if (version == 1) + ifile_v1 = (IFILE_V1 *)ipagep; + else + ifile = (IFILE *)ipagep; /* * Initialize IFILE. It is the next block following the * block of inodes (whose address has been calculated in * lfsp->lfs_idaddr; */ - sb_addr = lfsp->lfs_idaddr + lfsp->lfs_bsize / lp->d_secsize; + ifibc = 0; + sb_addr = lfsp->lfs_idaddr + btofsb(lfsp, lfsp->lfs_ibsize); sb_addr = make_dinode(LFS_IFILE_INUM, dip, - (lfsp->lfs_cleansz + lfsp->lfs_segtabsz+1)<<lfsp->lfs_fbshift, + blkstofrags(lfsp, lfsp->lfs_cleansz + lfsp->lfs_segtabsz+1), sb_addr, lfsp); dip->di_mode = IFREG|IREAD|IWRITE; dip->di_flags = SF_IMMUTABLE; /* XXX KS */ - ip = &ifile[LFS_IFILE_INUM]; - ip->if_version = 1; - ip->if_daddr = lfsp->lfs_idaddr; + if (version == 1) { + ip_v1 = &ifile_v1[LFS_IFILE_INUM]; + ip_v1->if_version = 1; + ip_v1->if_daddr = lfsp->lfs_idaddr; + } else { + ip = &ifile[LFS_IFILE_INUM]; + ip->if_version = 1; + ip->if_daddr = lfsp->lfs_idaddr; + } /* Initialize the ROOT Directory */ sb_addr = make_dinode(ROOTINO, ++dip, howmany(DIRBLKSIZ,lfsp->lfs_fsize), sb_addr, lfsp); dip->di_mode = IFDIR | UMASK; dip->di_size = DIRBLKSIZ; - dip->di_blocks = howmany(roundup(DIRBLKSIZ,lfsp->lfs_fsize),DEV_BSIZE); + dip->di_blocks = btofsb(lfsp, roundup(DIRBLKSIZ,lfsp->lfs_fsize)); dip->di_nlink = 3; - ip = &ifile[ROOTINO]; - ip->if_version = 1; - ip->if_daddr = lfsp->lfs_idaddr; + if (version == 1) { + ip_v1 = &ifile_v1[ROOTINO]; + ip_v1->if_version = 1; + ip_v1->if_daddr = lfsp->lfs_idaddr; + } else { + ip = &ifile[ROOTINO]; + ip->if_version = 1; + ip->if_daddr = lfsp->lfs_idaddr; + } /* Initialize the lost+found Directory */ sb_addr = make_dinode(LOSTFOUNDINO, ++dip, howmany(DIRBLKSIZ,lfsp->lfs_fsize), sb_addr, lfsp); dip->di_mode = IFDIR | UMASK; dip->di_size = DIRBLKSIZ; - dip->di_blocks = howmany(roundup(DIRBLKSIZ,lfsp->lfs_fsize),DEV_BSIZE); + dip->di_blocks = btofsb(lfsp, roundup(DIRBLKSIZ,lfsp->lfs_fsize)); dip->di_nlink = 2; - ip = &ifile[LOSTFOUNDINO]; - ip->if_version = 1; - ip->if_daddr = lfsp->lfs_idaddr; + if (version == 1) { + ip_v1 = &ifile_v1[LOSTFOUNDINO]; + ip_v1->if_version = 1; + ip_v1->if_daddr = lfsp->lfs_idaddr; + } else { + ip = &ifile[LOSTFOUNDINO]; + ip->if_version = 1; + ip->if_daddr = lfsp->lfs_idaddr; + } /* Make all the other dinodes invalid */ for (i = INOPB(lfsp)-3, dip++; i; i--, dip++) @@ -517,21 +625,57 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) /* Link remaining IFILE entries in free list */ - for (ip = &ifile[LFS_FIRST_INUM], i = LFS_FIRST_INUM; - i < lfsp->lfs_ifpb; ++ip) { - ip->if_version = 1; - ip->if_daddr = LFS_UNUSED_DADDR; - ip->if_nextfree = ++i; + if (version == 1) { + for (ip_v1 = &ifile_v1[LFS_FIRST_INUM], i = LFS_FIRST_INUM; + i < lfsp->lfs_ifpb; ++ip_v1) { + ip_v1->if_version = 1; + ip_v1->if_daddr = LFS_UNUSED_DADDR; + ip_v1->if_nextfree = ++i; + } + ifile_v1[lfsp->lfs_ifpb - 1].if_nextfree = LFS_UNUSED_INUM; + } else { + for (ip = &ifile[LFS_FIRST_INUM], i = LFS_FIRST_INUM; + i < lfsp->lfs_ifpb; ++ip) { + ip->if_version = 1; + ip->if_daddr = LFS_UNUSED_DADDR; + ip->if_nextfree = ++i; + } + ifile[lfsp->lfs_ifpb - 1].if_nextfree = LFS_UNUSED_INUM; + } + + /* XXX Check to make sure it will all fit in one segment. */ + /* XXX When we have a partial-segment writer this can go away. */ + if (dtosn(lfsp, sb_addr - 1) != 0) { + if (!warned_segtoobig) { + fprintf(stderr, "Segment size %d is too small; ", + ssize); + if (version == 1) + while(ssize < fsbtob(lfsp, sb_addr)) + ssize <<= 1; + else + ssize = fsbtob(lfsp, sb_addr); + fprintf(stderr, "trying size %d.\n", ssize); + goto tryagain; + } + fatal("Can't fit %d bytes into one segment sized %d", + fsbtob(lfsp, sb_addr), ssize); } - ifile[lfsp->lfs_ifpb - 1].if_nextfree = LFS_UNUSED_INUM; /* Now, write the segment */ + printf("Creating a version %d LFS", lfsp->lfs_version); + if (lfsp->lfs_version > 1) + printf(" with roll-forward ident 0x%x", lfsp->lfs_ident); + printf("\n"); + fssize = (double)lfsp->lfs_nseg; + fssize *= (double)ssize; + fssize /= 1048576.0; + printf("%.1fMB in %d segments of size %d\n", fssize, + lfsp->lfs_nseg, ssize); + /* Adjust blocks_used to take indirect block into account */ - if(ifib) { - ++blocks_used; - segtable[0].su_nbytes += lfsp->lfs_bsize; - } + blocks_used += ifibc; + segtable[0].su_nbytes += ifibc * lfsp->lfs_bsize; /* Compute a checksum across all the data you're writing */ dp = datasump = malloc (blocks_used * sizeof(u_long)); @@ -542,14 +686,17 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) for (i = 0; i < lfsp->lfs_segtabsz; i++) *dp++ = ((u_long *)segtable)[(i << lfsp->lfs_bshift) / sizeof(u_long)]; /* Segusage table */ - *dp++ = ((u_long *)ifile)[0]; /* Ifile */ + *dp++ = ((u_long *)ipagep)[0]; /* Ifile */ /* Still need the root and l+f bytes; get them later */ /* Write out the inode block */ - off = LFS_LABELPAD + LFS_SBPAD + LFS_SUMMARY_SIZE; - put(fd, off, dpagep, lfsp->lfs_bsize); - off += lfsp->lfs_bsize; + startoff = fsbtob(lfsp, label_fsb + sb_fsb); + if (startoff < fsbtob(lfsp, lfsp->lfs_start)) + startoff = fsbtob(lfsp, lfsp->lfs_start); + off = startoff + lfsp->lfs_sumsize; + put(fd, off, dpagep, lfsp->lfs_ibsize); + off += lfsp->lfs_ibsize; /* Write out the ifile */ @@ -561,13 +708,13 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) off += (lfsp->lfs_segtabsz << lfsp->lfs_bshift); (void)free(segtable); - put(fd, off, ifile, lfsp->lfs_bsize); + put(fd, off, ipagep, lfsp->lfs_bsize); off += lfsp->lfs_bsize; - /* XXX KS - write the single indirect block */ - if(ifib) { - *dp++ = ((u_long *)ifib)[0]; - put(fd, off, ifib, lfsp->lfs_bsize); + /* Write the indirect blocks */ + for (i = 0; i < ifibc; i++) { + *dp++ = ((u_long *)(ifibp[i]))[0]; + put(fd, off, ifibp[i], lfsp->lfs_bsize); off += lfsp->lfs_bsize; } @@ -583,7 +730,7 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) *dp++ = ((u_long *)ipagep)[0]; dip = ((struct dinode *)dpagep) + 1; put(fd, off, ipagep, dblksize(lfsp,dip,0)); - off += dblksize(lfsp,dip,0); + off += dblksize(lfsp, dip, 0); memset(ipagep, 0, lfsp->lfs_bsize); make_dir(ipagep, lfs_lf_dir, @@ -591,22 +738,27 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) *dp++ = ((u_long *)ipagep)[0]; dip = ((struct dinode *)dpagep) + 2; put(fd, off, ipagep, dblksize(lfsp,dip,0)); - off += dblksize(lfsp,dip,0); + off += dblksize(lfsp, dip, 0); /* Write Superblock */ - lfsp->lfs_offset = off / lp->d_secsize; - lfsp->lfs_avail = lfsp->lfs_dsize - - (fsbtodb(lfsp, lfsp->lfs_ssize) - btodb(LFS_SBPAD) - - (sntoda(lfsp, 1) - lfsp->lfs_offset)); - + lfsp->lfs_offset = btofsb(lfsp, off); + lfsp->lfs_avail = lfsp->lfs_dsize - btofsb(lfsp, (off - startoff)); + if (lfsp->lfs_start < label_fsb) + lfsp->lfs_avail -= label_fsb - lfsp->lfs_start; lfsp->lfs_bfree = lfsp->lfs_avail; /* XXX */ /* Slop for an imperfect cleaner */ - lfsp->lfs_avail += (lfsp->lfs_minfreeseg / 2) * - fsbtodb(lfsp, lfsp->lfs_ssize); - + lfsp->lfs_avail += segtod(lfsp, lfsp->lfs_minfreeseg / 2); lfsp->lfs_cksum = lfs_sb_cksum(&(lfsp->lfs_dlfs)); put(fd, (off_t)LFS_LABELPAD, &(lfsp->lfs_dlfs), sizeof(struct dlfs)); + /* If that was different from lfs_sboffs[0], write the latter too */ + if (LFS_LABELPAD < fsbtob(lfsp, (off_t)lfsp->lfs_sboffs[0])) { + printf("Writing 1st superblock at both %lld and %lld bytes\n", + (long long)LFS_LABELPAD, + fsbtob(lfsp, (long long)lfsp->lfs_sboffs[0])); + put(fd, (off_t)lfsp->lfs_sboffs[0], &(lfsp->lfs_dlfs), + sizeof(struct dlfs)); + } /* * Finally, calculate all the fields for the summary structure @@ -615,7 +767,13 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) memset(&summary,0,sizeof(summary)); summary.ss_next = lfsp->lfs_nextseg; - summary.ss_create = lfsp->lfs_tstamp; + if (version == 1) + /* ident is where create was in v1 */ + summary.ss_ident = lfsp->lfs_tstamp; + else { + summary.ss_create = lfsp->lfs_tstamp; + summary.ss_ident = lfsp->lfs_ident; + } summary.ss_nfinfo = 3; summary.ss_ninos = 3; summary.ss_magic = SS_MAGIC; @@ -631,12 +789,14 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) * is already counted. Finally, we leave room for 1 inode block * address. */ - sum_size = 3*sizeof(FINFO) + sizeof(SEGSUM) + 2*sizeof(daddr_t) + + sum_size = (version == 1 ? sizeof(SEGSUM_V1) : sizeof(SEGSUM)); + sum_size += 3 * sizeof(FINFO) + 2 * sizeof(daddr_t) + (lfsp->lfs_cleansz + lfsp->lfs_segtabsz) * sizeof(ufs_daddr_t); -#define SUMERR \ -"Multiple summary blocks in segment 1 not yet implemented\nsummary is %d bytes." - if (sum_size > LFS_SUMMARY_SIZE) - fatal(SUMERR, sum_size); + + if (sum_size > lfsp->lfs_sumsize) + fatal("Multiple summary blocks in segment 0 " + "not yet implemented\n" + "summary is %d bytes.", sum_size); block_array_size = lfsp->lfs_cleansz + lfsp->lfs_segtabsz + 1; if (block_array_size > NDADDR) @@ -654,7 +814,10 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) /* copy into segment */ sump = ipagep; memcpy(sump, &summary, sizeof(SEGSUM)); - sump += sizeof(SEGSUM); + if (version == 1) + sump += sizeof(SEGSUM_V1); + else + sump += sizeof(SEGSUM); /* Now, add the ifile */ file_info.fi_nblocks = block_array_size; @@ -683,14 +846,15 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) file_info.fi_lastlength = dblksize(lfsp, dip, 0); memmove(sump, &file_info, sizeof(FINFO)); - ((daddr_t *)ipagep)[LFS_SUMMARY_SIZE / sizeof(daddr_t) - 1] = + ((daddr_t *)ipagep)[lfsp->lfs_sumsize / sizeof(daddr_t) - 1] = lfsp->lfs_idaddr; ((SEGSUM *)ipagep)->ss_sumsum = cksum(ipagep+sizeof(summary.ss_sumsum), - LFS_SUMMARY_SIZE - sizeof(summary.ss_sumsum)); - put(fd, (off_t)LFS_LABELPAD + LFS_SBPAD, ipagep, LFS_SUMMARY_SIZE); + lfsp->lfs_sumsize - sizeof(summary.ss_sumsum)); + put(fd, (off_t)startoff, ipagep, lfsp->lfs_sumsize); sp = (SEGSUM *)ipagep; sp->ss_create = 0; + sp->ss_ident = 0; sp->ss_nfinfo = 0; sp->ss_ninos = 0; sp->ss_datasum = 0; @@ -700,23 +864,33 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) /* Now write the summary block for the next partial so it's invalid */ sp->ss_sumsum = - cksum(&sp->ss_datasum, LFS_SUMMARY_SIZE - sizeof(sp->ss_sumsum)); - put(fd, off, sp, LFS_SUMMARY_SIZE); + cksum(&sp->ss_datasum, lfsp->lfs_sumsize - sizeof(sp->ss_sumsum)); + put(fd, off, sp, lfsp->lfs_sumsize); /* Now, write the rest of the superblocks */ lfsp->lfs_cksum = lfs_sb_cksum(&(lfsp->lfs_dlfs)); printf("super-block backups (for fsck -b #) at:\n"); + curw = 0; + ww = 0; for (i = 0; i < LFS_MAXNUMSB; i++) { seg_addr = lfsp->lfs_sboffs[i]; - printf("%d%s ", seg_addr, (i == LFS_MAXNUMSB - 1 ? "" : ",")); + sprintf(tbuf, "%d%s ", fsbtodb(lfsp, seg_addr), + (i == LFS_MAXNUMSB - 1 ? "" : ",")); + ww = strlen(tbuf); + curw += ww; + if (curw + ww > 78) { + printf("%s\n", tbuf); + curw = 0; + } else + printf("%s", tbuf); /* Leave the time stamp on the alt sb, zero the rest */ if(i == 2) { lfsp->lfs_tstamp = 0; lfsp->lfs_cksum = lfs_sb_cksum(&(lfsp->lfs_dlfs)); } - seg_seek = (off_t)seg_addr * lp->d_secsize; + seg_seek = fsbtob(lfsp, (off_t)seg_addr); put(fd, seg_seek, &(lfsp->lfs_dlfs), sizeof(struct dlfs)); } printf("\n"); @@ -726,11 +900,7 @@ make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size, minfreeseg) } static void -put(fd, off, p, len) - int fd; - off_t off; - void *p; - size_t len; +put(int fd, off_t off, void *p, size_t len) { int wbytes; @@ -738,9 +908,11 @@ put(fd, off, p, len) return; if (lseek(fd, off, SEEK_SET) < 0) - fatal("%s: seek: %s", special, strerror(errno)); + fatal("%s: seek %lld: %s", special, (long long)off, + strerror(errno)); if ((wbytes = write(fd, p, len)) < 0) - fatal("%s: write: %s", special, strerror(errno)); + fatal("%s: write: %d at %lld: %s", special, len, + (long long)off, strerror(errno)); if (wbytes != len) fatal("%s: short write (%d, not %ld)", special, wbytes, (u_long) len); @@ -752,22 +924,17 @@ put(fd, off, p, len) */ static daddr_t -make_dinode(ino, dip, nfrags, saddr, lfsp) - ino_t ino; /* inode we're creating */ - struct dinode *dip; /* disk inode */ - int nfrags; /* number of frags in file */ - daddr_t saddr; /* starting block address */ - struct lfs *lfsp; /* superblock */ +make_dinode(ino_t ino, struct dinode *dip, int nfrags, daddr_t saddr, struct lfs *lfsp) { - int db_per_fb, i; - int nblocks; + int fsb_per_blk, i; + int nblocks, bb, ibi, base, factor, lvl; nblocks = howmany(nfrags, lfsp->lfs_frag); if(nblocks >= NDADDR) nfrags = roundup(nfrags, lfsp->lfs_frag); dip->di_nlink = 1; - dip->di_blocks = fragstodb(lfsp, nfrags); + dip->di_blocks = fragstofsb(lfsp, nfrags); dip->di_size = (nfrags << lfsp->lfs_ffshift); dip->di_atime = dip->di_mtime = dip->di_ctime = lfsp->lfs_tstamp; @@ -775,35 +942,64 @@ make_dinode(ino, dip, nfrags, saddr, lfsp) dip->di_inumber = ino; dip->di_gen = 1; - db_per_fb = 1 << lfsp->lfs_fsbtodb; -#if 0 - if (NDADDR < nblocks) - fatal("File ino=%d requires more than the number of direct blocks; please increase block or segment size.",ino); -#else - if (NDADDR+NINDIR(lfsp) < nblocks) { - fatal("File ino=%d requires more blocks than can be accommodated with a single indirect block; please increase segment or block size.",ino); - } else if (NDADDR < nblocks) { - fprintf(stderr,"Using %d single indirect block(s) for inode %d\n", - (nblocks-NDADDR)/NINDIR(lfsp) + 1, ino); - dip->di_blocks += db_per_fb; + fsb_per_blk = fragstofsb(lfsp, blkstofrags(lfsp, 1)); + + if (NDADDR < nblocks) { + /* Count up how many indirect blocks we need, recursively */ + /* XXX We are only called with nblocks > 1 for Ifile */ + bb = nblocks - NDADDR; + while (bb > 0) { + bb = howmany(bb, NINDIR(lfsp)); + ifibc += bb; + --bb; + } + /* printf("using %d indirect blocks for inode %d\n", ifibc, ino); */ + ifibp = (daddr_t **)malloc(ifibc * sizeof(daddr_t *)); + for (i = 0; i < ifibc ; i++) { + ifibp[i] = (daddr_t *)malloc(lfsp->lfs_bsize); + memset(ifibp[i], 0, lfsp->lfs_bsize); + } + dip->di_blocks += fragstofsb(lfsp, blkstofrags(lfsp, ifibc)); } -#endif + /* Assign the block addresses for the ifile */ - for (i = 0; i < MIN(nblocks,NDADDR); i++, saddr += db_per_fb) { + for (i = 0; i < MIN(nblocks,NDADDR); i++, saddr += fsb_per_blk) { dip->di_db[i] = saddr; + /* printf("direct block %d at 0x%x\n", i, saddr); */ } if (nfrags & lfsp->lfs_fbmask) { /* Last block is a fragment */ - saddr -= db_per_fb - fragstodb(lfsp, nfrags & lfsp->lfs_fbmask); + saddr -= fsb_per_blk - fragstofsb(lfsp, nfrags & lfsp->lfs_fbmask); } - /* XXX We are only called with nblocks > 1 for Ifile */ - if(ino == LFS_IFILE_INUM && nblocks > NDADDR) { - ifib = (daddr_t *)malloc(lfsp->lfs_bsize); - memset(ifib,0,lfsp->lfs_bsize); - for (i = 0; i < nblocks-NDADDR; i++, saddr += db_per_fb) - ifib[i] = saddr; + if(nblocks > NDADDR) { + for (i = 0; i < nblocks - NDADDR; i++, saddr += fsb_per_blk) { + ifibp[i / NINDIR(lfsp)][i % NINDIR(lfsp)] = saddr; + /* printf("direct block %d at 0x%x\n", i + NDADDR, saddr); */ + } + /* printf("indir block ib[0] (%d) at 0x%x\n", -NDADDR, saddr);*/ dip->di_ib[0] = saddr; - saddr += db_per_fb; + saddr += fsb_per_blk; + bb = howmany(nblocks - NDADDR, NINDIR(lfsp)) - 1; + factor = NINDIR(lfsp); + base = -NDADDR - factor; + lvl = 1; + while (bb > 0) { + for (ibi = 0; ibi < bb; i++, ibi++, saddr += fsb_per_blk) { + ifibp[i / NINDIR(lfsp)][i % NINDIR(lfsp)] = + saddr; + /* printf("indir block %d at 0x%x\n", + base - ibi * factor - lvl + 1, saddr); */ + } + /* printf("indir block ib[%d] (%d) at 0x%x\n", lvl, + base - lvl, saddr); */ + dip->di_ib[lvl] = saddr; + saddr += fsb_per_blk; + bb = howmany(bb, NINDIR(lfsp)); + --bb; + factor *= NINDIR(lfsp); + base -= factor; + ++lvl; + } } return (saddr); @@ -815,10 +1011,7 @@ make_dinode(ino, dip, nfrags, saddr, lfsp) * entries in protodir fir in the first DIRBLKSIZ. */ static void -make_dir(bufp, protodir, entries) - void *bufp; - struct direct *protodir; - int entries; +make_dir(void *bufp, struct direct *protodir, int entries) { char *cp; int i, spcleft; diff --git a/sbin/newfs_lfs/misc.c b/sbin/newfs_lfs/misc.c index 898791405fe..b3f27f037d0 100644 --- a/sbin/newfs_lfs/misc.c +++ b/sbin/newfs_lfs/misc.c @@ -1,4 +1,4 @@ -/* $NetBSD: misc.c,v 1.1 1999/03/18 17:18:05 perseant Exp $ */ +/* $NetBSD: misc.c,v 1.2 2001/07/13 20:30:20 perseant Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/5/93"; #else -__RCSID("$NetBSD: misc.c,v 1.1 1999/03/18 17:18:05 perseant Exp $"); +__RCSID("$NetBSD: misc.c,v 1.2 2001/07/13 20:30:20 perseant Exp $"); #endif #endif /* not lint */ @@ -50,8 +50,7 @@ __RCSID("$NetBSD: misc.c,v 1.1 1999/03/18 17:18:05 perseant Exp $"); #include "extern.h" u_int -log2(num) - u_int num; +log2(u_int num) { u_int i, limit; diff --git a/sbin/newfs_lfs/newfs.c b/sbin/newfs_lfs/newfs.c index 6205537c795..eadbf7f2cb8 100644 --- a/sbin/newfs_lfs/newfs.c +++ b/sbin/newfs_lfs/newfs.c @@ -1,4 +1,4 @@ -/* $NetBSD: newfs.c,v 1.6 2000/12/05 19:51:15 perseant Exp $ */ +/* $NetBSD: newfs.c,v 1.7 2001/07/13 20:30:20 perseant Exp $ */ /*- * Copyright (c) 1989, 1992, 1993 @@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1989, 1992, 1993\n\ #if 0 static char sccsid[] = "@(#)newfs.c 8.5 (Berkeley) 5/24/95"; #else -__RCSID("$NetBSD: newfs.c,v 1.6 2000/12/05 19:51:15 perseant Exp $"); +__RCSID("$NetBSD: newfs.c,v 1.7 2001/07/13 20:30:20 perseant Exp $"); #endif #endif /* not lint */ @@ -78,15 +78,17 @@ __RCSID("$NetBSD: newfs.c,v 1.6 2000/12/05 19:51:15 perseant Exp $"); #define COMPAT /* allow non-labeled disks */ -int Nflag; /* run without writing file system */ +int version = DFL_VERSION; /* what version of lfs to make */ +int Nflag = 0; /* run without writing file system */ int fssize; /* file system size */ int sectorsize; /* bytes/sector */ int fsize = 0; /* fragment size */ int bsize = 0; /* block size */ +int ibsize = 0; /* inode block size */ +int interleave = 0; /* segment interleave */ int minfree = MINFREE; /* free space threshold */ int minfreeseg = 0; /* free segments reserved for the cleaner */ -int bbsize = BBSIZE; /* boot block size */ -int sbsize = SBSIZE; /* superblock size */ +u_int32_t roll_id = 0; /* roll-forward id */ u_long memleft; /* virtual memory available */ caddr_t membase; /* start address of memory based filesystem */ #ifdef COMPAT @@ -97,15 +99,15 @@ int unlabeled; char device[MAXPATHLEN]; char *progname, *special; -int main __P((int, char **)); -static struct disklabel *getdisklabel __P((char *, int)); -static struct disklabel *debug_readlabel __P((int)); +static struct disklabel *getdisklabel(char *, int); +static struct disklabel *debug_readlabel(int); #ifdef notdef -static void rewritelabel __P((char *, int, struct disklabel *)); +static void rewritelabel(char *, int, struct disklabel *); #endif -static void usage __P((void)); +static void usage(void); -#define CHUNKSIZE 65536 +/* CHUNKSIZE should be larger than MAXPHYS */ +#define CHUNKSIZE (1024 * 1024) static size_t auto_segsize(int fd, off_t len, int version) @@ -145,31 +147,27 @@ auto_segsize(int fd, off_t len, int version) if (seeks == 0) seeks = 1; - printf("bandwidth %ld B/s, seek time %ld ms (%ld seeks/s)\n", + printf("bw = %ld B/s, seek time %ld ms (%ld seeks/s)\n", (long)bw, 1000/seeks, seeks); final = dbtob(btodb(4 * bw / seeks)); - - /* Version 1 filesystems have po2 segment sizes */ if (version == 1) { for (i = 0; final; final >>= 1, i++) ; final = 1 << i; } - printf("using initial segment size %ld\n", (long)final); return final; } int -main(argc, argv) - int argc; - char *argv[]; +main(int argc, char **argv) { int ch; struct partition *pp; struct disklabel *lp; struct stat st; int debug, force, fsi, fso, segsize, maxpartitions; + daddr_t start; char *cp, *opstring; if ((progname = strrchr(*argv, '/')) != NULL) @@ -181,9 +179,9 @@ main(argc, argv) if (maxpartitions > 26) fatal("insane maxpartitions value %d", maxpartitions); - opstring = "AB:DFLNb:f:M:m:s:"; + opstring = "AB:b:DFf:I:i:LM:m:NO:r:s:v:"; - debug = force = segsize = 0; + debug = force = segsize = start = 0; while ((ch = getopt(argc, argv, opstring)) != -1) switch(ch) { case 'A': /* Adaptively configure segment size */ @@ -199,6 +197,9 @@ main(argc, argv) case 'F': force = 1; break; + case 'I': + interleave = atoi(optarg); + break; case 'L': /* Compatibility only */ break; case 'M': @@ -207,6 +208,9 @@ main(argc, argv) case 'N': Nflag++; break; + case 'O': + start = atoi(optarg); + break; #ifdef COMPAT case 'T': disktype = optarg; @@ -220,14 +224,27 @@ main(argc, argv) if ((fsize = atoi(optarg)) <= 0) fatal("%s: bad frag size", optarg); break; + case 'i': + if ((ibsize = atoi(optarg)) <= 0) + fatal("%s: bad inode block size", optarg); + break; case 'm': if ((minfree = atoi(optarg)) < 0 || minfree > 99) fatal("%s: bad free space %%\n", optarg); break; + case 'r': + if ((roll_id = strtoul(optarg, NULL, 0)) == 0) + fatal("%s: bad roll-forward id\n", optarg); + break; case 's': if ((fssize = atoi(optarg)) <= 0) fatal("%s: bad file system size", optarg); break; + case 'v': + version = atoi(optarg); + if (version <= 0 || version > LFS_VERSION) + fatal("%s: bad version", optarg); + break; case '?': default: usage(); @@ -303,11 +320,12 @@ main(argc, argv) /* Try autoconfiguring segment size, if asked to */ if (segsize == -1) - segsize = auto_segsize(fsi, dbtob(pp->p_size), 1); + segsize = auto_segsize(fsi, dbtob(pp->p_size), version); /* If we're making a LFS, we break out here */ exit(make_lfs(fso, lp, pp, minfree, bsize, fsize, segsize, - minfreeseg)); + minfreeseg, version, start, ibsize, interleave, + roll_id)); } #ifdef COMPAT @@ -317,9 +335,7 @@ char lmsg[] = "%s: can't read disk label"; #endif static struct disklabel * -getdisklabel(s, fd) - char *s; - int fd; +getdisklabel(char *s, int fd) { static struct disklabel lab; @@ -344,8 +360,7 @@ getdisklabel(s, fd) static struct disklabel * -debug_readlabel(fd) - int fd; +debug_readlabel(int fd) { static struct disklabel lab; int n; @@ -360,10 +375,7 @@ debug_readlabel(fd) #ifdef notdef static void -rewritelabel(s, fd, lp) - char *s; - int fd; - struct disklabel *lp; +rewritelabel(char *s, int fd, struct disklabel *lp) { #ifdef COMPAT if (unlabeled) @@ -421,12 +433,14 @@ usage() fprintf(stderr, "where fsoptions are:\n"); fprintf(stderr, "\t-A (autoconfigure segment size)\n"); fprintf(stderr, "\t-B segment size in bytes\n"); - fprintf(stderr, "\t-D debug\n"); + fprintf(stderr, "\t-D (debug)\n"); fprintf(stderr, "\t-N (do not create file system, just print out parameters)\n"); + fprintf(stderr, "\t-O first segment offset in sectors\n"); fprintf(stderr, "\t-b block size in bytes\n"); fprintf(stderr, "\t-f frag size in bytes\n"); fprintf(stderr, "\t-m minimum free space %%\n"); fprintf(stderr, "\t-s file system size in sectors\n"); + fprintf(stderr, "\t-v version\n"); exit(1); } diff --git a/sbin/newfs_lfs/newfs_lfs.8 b/sbin/newfs_lfs/newfs_lfs.8 index 5567fce2b32..f146b6c7fa9 100644 --- a/sbin/newfs_lfs/newfs_lfs.8 +++ b/sbin/newfs_lfs/newfs_lfs.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: newfs_lfs.8,v 1.12 2001/06/05 11:22:51 wiz Exp $ +.\" $NetBSD: newfs_lfs.8,v 1.13 2001/07/13 20:30:20 perseant Exp $ .\" .\" Copyright (c) 1993 .\" The Regents of the University of California. All rights reserved. @@ -33,7 +33,7 @@ .\" .\" @(#)newlfs.8 8.1 (Berkeley) 6/19/93 .\" -.Dd July 15, 1999 +.Dd July 12, 2001 .Dt NEWFS_LFS 8 .Os .Sh NAME @@ -83,21 +83,38 @@ shift, unless these are overridden by command-line flags. The fragment size of the file system in bytes. If not specified, the fragment size is taken from the partition label, or if the partition label indicates 0, a compile-time default of 1K is used. +.It Fl I Ar interleave +Specify the interleave between segments. The default is zero. +.It Fl i +The size of an inode block, in bytes. The default is to use the same +size as a fragment, or in a v1 filesystem, the same size as a data block. .It Fl L Create a log-structured file system (LFS). This is the default, and this option is provided for compatibility only. -.It Fl m Ar free space \&% -The percentage of space reserved from normal users; the minimum -free space threshold. The default value used is 10%. .It Fl M Ar nsegs Reserve this many segments for use exclusively by the cleaner, instead of letting .Nm do the computation. Do not use this option. +.It Fl m Ar free space \&% +The percentage of space reserved from normal users; the minimum +free space threshold. The default value used is 10%. .It Fl N Do not actually create the filesystem. +.It Fl O Ar offset +Start the first segment this many sectors from the beginning of the +partition. The default is zero. +.It Fl r Ar ident +For a v2 filesystem, specify the roll-forward identifier for the +filesystem. This identifier, a 32-bit numeric quantity, +should be different from that of any LFS that may previously +have existed on the same disk. By default the +identifier is chosen at random. .It Fl s Ar size The size of the file system in sectors. +.It Fl v Ar version +Make a filesystem with the specified disk layout version. Valid options +are 1 (the default) or 2. .El .Sh SEE ALSO .Xr disktab 5 , diff --git a/sys/ufs/lfs/TODO b/sys/ufs/lfs/TODO index 4f7593ee4b4..c60e2b69c4a 100644 --- a/sys/ufs/lfs/TODO +++ b/sys/ufs/lfs/TODO @@ -1,23 +1,20 @@ -# $NetBSD: TODO,v 1.4 2000/11/17 19:14:41 perseant Exp $ +# $NetBSD: TODO,v 1.5 2001/07/13 20:30:22 perseant Exp $ -- If we put an LFS onto a striped disk, we want to be able to specify - the segment size to be equal to the stripe size, regardless of whether - this is a power of two; also, the first segment should just eat the - label pad, like the segments eat the superblocks. Then, we could - neatly lay out the segments along stripe boundaries. [v2] +- Investigate alternate inode locking strategy: Inode locks are useful + for locking against simultaneous changes to inode size (balloc, + truncate, write) but because the assignment of disk blocks is also + covered by the segment lock, we don't really need to pay attention to + the inode lock when writing a segment, right? If this is true, the + locking problem in lfs_{bmapv,markv} goes away and lfs_reserve can go, + too. -- Working fsck_lfs. (Have something that will verify, need something - that will fix too. Really, need a general-purpose external +- Fully working fsck_lfs. (Really, need a general-purpose external partial-segment writer.) -- Roll-forward agent, *at least* to verify the newer superblock's - checkpoint (easy) but also to create a valid checkpoint for - post-checkpoint writes (requires an external partial-segment writer). - - Inode blocks are currently the same size as the fs block size; but all the ones I've seen are mostly empty, and this will be especially true if atime information is kept in the ifile instead of the inode. Could - we shrink the inode block size to 512? Or parametrize it at fs + we shrink the inode block size to DEV_BSIZE? Or parametrize it at fs creation time? - Get rid of DEV_BSIZE, pay attention to the media block size at mount time. @@ -28,12 +25,6 @@ be put back on the *head* of the vnode free list. Make sure we actually do this, since we now take IN_CLEANING off during segment write. -- Investigate the "unlocked access" in lfs_bmapv, see if we could wait - there most of the time? Are we getting inconsistent data? - -- Change the free_lock to be fs-specific, and change the dirvcount to be - subsystem-wide. - - The cleaner could be enhanced to be controlled from other processes, and possibly perform additional tasks: @@ -82,14 +73,6 @@ avoid the problem, and one that reads/writes from the raw disk could fix it. -- Overlap the version and nextfree fields in the IFILE - -- Change so that only search one sector of inode block file for the - inode by using sector addresses in the ifile instead of - logical disk addresses. - -- Fix the use of the ifile version field to use the generation number instead. - - Need to keep vnode v_numoutput up to date for pending writes? - If delete a file that's being executed, the version number isn't @@ -97,11 +80,6 @@ have an inode that no directory references, so the file should be reattached into lost+found. -- Investigate: should the access time be part of the IFILE: - pro: theoretically, saves disk writes - con: cacheing inodes should obviate this advantage - the IFILE is already humongous - - Currently there's no notion of write error checking. + Failed data/inode writes should be rescheduled (kernel level bad blocking). + Failed superblock writes should cause selection of new superblock diff --git a/sys/ufs/lfs/lfs.h b/sys/ufs/lfs/lfs.h index f9d103437c5..8da9d720eb1 100644 --- a/sys/ufs/lfs/lfs.h +++ b/sys/ufs/lfs/lfs.h @@ -1,4 +1,4 @@ -/* $NetBSD: lfs.h,v 1.36 2000/12/20 00:24:23 cgd Exp $ */ +/* $NetBSD: lfs.h,v 1.37 2001/07/13 20:30:22 perseant Exp $ */ /*- * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. @@ -75,12 +75,10 @@ */ #define LFS_EAGAIN_FAIL /* markv fail with EAGAIN if ino is locked */ #define LFS_TRACK_IOS /* attempt to avoid cleaning segments not yet fully written to disk */ -#define LFS_CANNOT_ROLLFW /* No roll-forward agent exists */ +#define LFS_DEBUG_RFW /* print roll-forward debugging info */ /* #define DEBUG_LFS */ /* Intensive debugging of LFS subsystem */ -/* #define LFS_ATIME_IFILE */ /* Store atime in Ifile, don't push */ - /* * Parameters and generic definitions */ @@ -88,6 +86,9 @@ #define MIN_FREE_SEGS 2 #define LFS_MAX_ACTIVE 10 #define LFS_MAXDIROP (desiredvnodes>>2) +#ifndef LFS_ATIME_IFILE +# define LFS_ATIME_IFILE 0 +#endif /* * #define WRITE_THRESHHOLD ((nbuf >> 1) - 10) @@ -121,6 +122,7 @@ /* For convenience */ #define IN_ALLMOD (IN_MODIFIED|IN_ACCESS|IN_CHANGE|IN_UPDATE|IN_ACCESSED|IN_CLEANING) + #define LFS_SET_UINO(ip, flags) do { \ if (((flags) & IN_ACCESSED) && !((ip)->i_flag & IN_ACCESSED)) \ ++(ip)->i_lfs->lfs_uinodes; \ @@ -144,13 +146,21 @@ } \ } while(0) - -#ifndef LFS_ATIME_IFILE -#define LFS_ITIMES(ip, acc, mod, cre) { \ - if ((ip)->i_flag & IN_ACCESS) { \ +#define LFS_ITIMES(ip, acc, mod, cre) do { \ + if ((ip)->i_flag & IN_ACCESS) { \ (ip)->i_ffs_atime = (acc)->tv_sec; \ (ip)->i_ffs_atimensec = (acc)->tv_nsec; \ - LFS_SET_UINO(ip, IN_ACCESSED); \ + if ((ip)->i_lfs->lfs_version > 1) { \ + struct buf *ibp; \ + IFILE *ifp; \ + \ + LFS_IENTRY(ifp, ip->i_lfs, ip->i_number, ibp); \ + ifp->if_atime_sec = (acc)->tv_sec; \ + ifp->if_atime_nsec = (acc)->tv_nsec; \ + VOP_BWRITE(ibp); \ + } else { \ + LFS_SET_UINO(ip, IN_ACCESSED); \ + } \ } \ if ((ip)->i_flag & (IN_CHANGE | IN_UPDATE)) { \ if ((ip)->i_flag & IN_UPDATE) { \ @@ -165,35 +175,10 @@ LFS_SET_UINO(ip, IN_MODIFIED); \ } \ (ip)->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE); \ -} -#else -# define LFS_ITIMES(ip, acc, mod, cre) { \ - struct buf *ibp; \ - IFILE *ifp; \ - \ - if ((ip)->i_flag & IN_ACCESS) { \ - LFS_IENTRY(ifp, ip->i_lfs, ip->i_number, ibp); \ - ifp->if_atime = (mod); \ - VOP_BWRITE(bp); \ - (ip)->i_flag &= ~IN_ACCESS; \ - } \ - if ((ip)->i_flag & (IN_CHANGE | IN_UPDATE)) { \ - LFS_SET_UINO(ip, IN_MODIFIED); \ - if ((ip)->i_flag & IN_UPDATE) { \ - (ip)->i_ffs_mtime = (mod)->tv_sec; \ - (ip)->i_ffs_mtimensec = (mod)->tv_nsec; \ - (ip)->i_modrev++; \ - } \ - if ((ip)->i_flag & IN_CHANGE) { \ - (ip)->i_ffs_ctime = (cre)->tv_sec; \ - (ip)->i_ffs_ctimensec = (cre)->tv_nsec; \ - } \ - (ip)->i_flag &= ~(IN_CHANGE | IN_UPDATE); \ - } \ -} -#endif +} while(0) -#define WRITEINPROG(vp) (vp->v_dirtyblkhd.lh_first && !(VTOI(vp)->i_flag & (IN_MODIFIED|IN_ACCESSED|IN_CLEANING))) +#define WRITEINPROG(vp) (vp->v_dirtyblkhd.lh_first && !(VTOI(vp)->i_flag & \ + (IN_MODIFIED | IN_ACCESSED | IN_CLEANING))) /* Here begins the berkeley code */ @@ -203,21 +188,31 @@ /* On-disk and in-memory checkpoint segment usage structure. */ typedef struct segusage SEGUSE; struct segusage { - u_int32_t su_nbytes; /* number of live bytes */ - u_int32_t su_lastmod; /* SEGUSE last modified timestamp */ - u_int16_t su_nsums; /* number of summaries in segment */ - u_int16_t su_ninos; /* number of inode blocks in seg */ - -#define SEGUSE_ACTIVE 0x01 /* segment is currently being written */ -#define SEGUSE_DIRTY 0x02 /* segment has data in it */ -#define SEGUSE_SUPERBLOCK 0x04 /* segment contains a superblock */ -#define SEGUSE_ERROR 0x08 /* cleaner: do not clean segment */ - u_int32_t su_flags; + u_int32_t su_nbytes; /* 0: number of live bytes */ + u_int32_t su_olastmod; /* 4: SEGUSE last modified timestamp */ + u_int16_t su_nsums; /* 8: number of summaries in segment */ + u_int16_t su_ninos; /* 10: number of inode blocks in seg */ + +#define SEGUSE_ACTIVE 0x01 /* segment currently being written */ +#define SEGUSE_DIRTY 0x02 /* segment has data in it */ +#define SEGUSE_SUPERBLOCK 0x04 /* segment contains a superblock */ +#define SEGUSE_ERROR 0x08 /* cleaner: do not clean segment */ + u_int32_t su_flags; /* 12: segment flags */ + u_int64_t su_lastmod; /* 16: last modified timestamp */ }; -#define SEGUPB(fs) (1 << (fs)->lfs_sushift) +typedef struct segusage_v1 SEGUSE_V1; +struct segusage_v1 { + u_int32_t su_nbytes; /* 0: number of live bytes */ + u_int32_t su_lastmod; /* 4: SEGUSE last modified timestamp */ + u_int16_t su_nsums; /* 8: number of summaries in segment */ + u_int16_t su_ninos; /* 10: number of inode blocks in seg */ + u_int32_t su_flags; /* 12: segment flags */ +}; + +#define SEGUPB(fs) (fs->lfs_sepb) #define SEGTABSIZE_SU(fs) \ - (((fs)->lfs_nseg + SEGUPB(fs) - 1) >> (fs)->lfs_sushift) + (((fs)->lfs_nseg + SEGUPB(fs) - 1) / (fs)->lfs_sepb) /* On-disk file information. One per file with data blocks in the segment. */ typedef struct finfo FINFO; @@ -226,18 +221,21 @@ struct finfo { u_int32_t fi_version; /* version number */ u_int32_t fi_ino; /* inode number */ u_int32_t fi_lastlength; /* length of last block in array */ - ufs_daddr_t fi_blocks[1]; /* array of logical block numbers */ + ufs_daddr_t fi_blocks[1]; /* array of logical block numbers */ }; + /* On-disk super block. */ struct dlfs { -#define LFS_MAGIC 0x070162 +#define LFS_MAGIC 0x070162 u_int32_t dlfs_magic; /* 0: magic number */ -#define LFS_VERSION 1 +#define LFS_VERSION 2 u_int32_t dlfs_version; /* 4: version number */ - u_int32_t dlfs_size; /* 8: number of blocks in fs */ - u_int32_t dlfs_ssize; /* 12: number of blocks per segment */ + u_int32_t dlfs_size; /* 8: number of blocks in fs (v1) */ + /* number of frags in fs (v2) */ + u_int32_t dlfs_ssize; /* 12: number of blocks per segment (v1) */ + /* number of bytes per segment (v2) */ u_int32_t dlfs_dsize; /* 16: number of disk blocks in fs */ u_int32_t dlfs_bsize; /* 20: file system block size */ u_int32_t dlfs_fsize; /* 24: size of frag blocks in fs */ @@ -256,14 +254,15 @@ struct dlfs { ufs_daddr_t dlfs_curseg; /* 68: current segment being written */ ufs_daddr_t dlfs_offset; /* 72: offset in curseg for next partial */ ufs_daddr_t dlfs_lastpseg; /* 76: address of last partial written */ - u_int32_t dlfs_tstamp; /* 80: time stamp */ + u_int32_t dlfs_inopf; /* 80: v1: time stamp; v2: inodes per frag */ +#define dlfs_otstamp dlfs_inopf /* These are configuration parameters. */ u_int32_t dlfs_minfree; /* 84: minimum percentage of free blocks */ /* These fields can be computed from the others. */ u_int64_t dlfs_maxfilesize; /* 88: maximum representable file size */ - u_int32_t dlfs_dbpseg; /* 96: disk blocks per segment */ + u_int32_t dlfs_fsbpseg; /* 96: fsb per segment */ u_int32_t dlfs_inopb; /* 100: inodes per block */ u_int32_t dlfs_ifpb; /* 104: IFILE entries per block */ u_int32_t dlfs_sepb; /* 108: SEGUSE entries per block */ @@ -280,24 +279,34 @@ struct dlfs { u_int64_t dlfs_bmask; /* 152: calc block offset from file offset */ u_int64_t dlfs_ffmask; /* 160: calc frag offset from file offset */ u_int64_t dlfs_fbmask; /* 168: calc frag offset from block offset */ - u_int32_t dlfs_fsbtodb; /* 176: fsbtodb and dbtofsb shift constant */ + u_int32_t dlfs_blktodb; /* 176: blktodb and dbtoblk shift constant */ u_int32_t dlfs_sushift; /* 180: fast mult/div for segusage table */ int32_t dlfs_maxsymlinklen; /* 184: max length of an internal symlink */ - -#define LFS_MIN_SBINTERVAL 5 /* minimum superblock segment spacing */ +#define LFS_MIN_SBINTERVAL 5 /* minimum superblock segment spacing */ #define LFS_MAXNUMSB 10 /* 188: superblock disk offsets */ ufs_daddr_t dlfs_sboffs[LFS_MAXNUMSB]; u_int32_t dlfs_nclean; /* 228: Number of clean segments */ u_char dlfs_fsmnt[MNAMELEN]; /* 232: name mounted on */ - /* XXX this is 2 bytes only to pad to a quad boundary */ - u_int16_t dlfs_clean; /* 322: file system is clean flag */ +#define LFS_PF_CLEAN 0x1 + u_int16_t dlfs_pflags; /* 322: file system persistent flags */ int32_t dlfs_dmeta; /* 324: total number of dirty summaries */ u_int32_t dlfs_minfreeseg; /* 328: segs reserved for cleaner */ - int8_t dlfs_pad[176]; /* 332: round to 512 bytes */ + u_int32_t dlfs_sumsize; /* 332: size of summary blocks */ + u_int64_t dlfs_serial; /* 336: serial number */ + u_int32_t dlfs_ibsize; /* 344: size of inode blocks */ + ufs_daddr_t dlfs_start; /* 348: start of segment 0 */ + u_int64_t dlfs_tstamp; /* 352: time stamp */ +#define LFS_44INODEFMT 0 +#define LFS_MAXINODEFMT 0 + u_int32_t dlfs_inodefmt; /* 360: inode format version */ + u_int32_t dlfs_interleave; /* 364: segment interleave */ + u_int32_t dlfs_ident; /* 368: per-fs identifier */ + u_int32_t dlfs_fsbtodb; /* 372: fsbtodb abd dbtodsb shift constant */ + int8_t dlfs_pad[132]; /* 376: round to 512 bytes */ /* Checksum -- last valid disk field. */ - u_int32_t dlfs_cksum; /* 508: checksum for superblock checking */ + u_int32_t dlfs_cksum; /* 508: checksum for superblock checking */ }; /* Maximum number of io's we can have pending at once */ @@ -326,10 +335,11 @@ struct lfs { #define lfs_curseg lfs_dlfs.dlfs_curseg #define lfs_offset lfs_dlfs.dlfs_offset #define lfs_lastpseg lfs_dlfs.dlfs_lastpseg -#define lfs_tstamp lfs_dlfs.dlfs_tstamp +#define lfs_otstamp lfs_dlfs.dlfs_inopf +#define lfs_inopf lfs_dlfs.dlfs_inopf #define lfs_minfree lfs_dlfs.dlfs_minfree #define lfs_maxfilesize lfs_dlfs.dlfs_maxfilesize -#define lfs_dbpseg lfs_dlfs.dlfs_dbpseg +#define lfs_fsbpseg lfs_dlfs.dlfs_fsbpseg #define lfs_inopb lfs_dlfs.dlfs_inopb #define lfs_ifpb lfs_dlfs.dlfs_ifpb #define lfs_sepb lfs_dlfs.dlfs_sepb @@ -346,16 +356,25 @@ struct lfs { #define lfs_ffshift lfs_dlfs.dlfs_ffshift #define lfs_fbmask lfs_dlfs.dlfs_fbmask #define lfs_fbshift lfs_dlfs.dlfs_fbshift +#define lfs_blktodb lfs_dlfs.dlfs_blktodb #define lfs_fsbtodb lfs_dlfs.dlfs_fsbtodb #define lfs_sushift lfs_dlfs.dlfs_sushift #define lfs_maxsymlinklen lfs_dlfs.dlfs_maxsymlinklen #define lfs_sboffs lfs_dlfs.dlfs_sboffs #define lfs_cksum lfs_dlfs.dlfs_cksum -#define lfs_clean lfs_dlfs.dlfs_clean +#define lfs_pflags lfs_dlfs.dlfs_pflags #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 +#define lfs_sumsize lfs_dlfs.dlfs_sumsize +#define lfs_serial lfs_dlfs.dlfs_serial +#define lfs_ibsize lfs_dlfs.dlfs_ibsize +#define lfs_start lfs_dlfs.dlfs_start +#define lfs_tstamp lfs_dlfs.dlfs_tstamp +#define lfs_inodefmt lfs_dlfs.dlfs_inodefmt +#define lfs_interleave lfs_dlfs.dlfs_interleave +#define lfs_ident lfs_dlfs.dlfs_ident /* These fields are set at mount time and are meaningless on disk. */ struct segment *lfs_sp; /* current segment being written */ @@ -375,12 +394,12 @@ struct lfs { #ifdef LFS_TRACK_IOS daddr_t lfs_pending[LFS_THROTTLE]; /* daddrs of pending writes */ #endif /* LFS_TRACK_IOS */ -#ifdef LFS_CANNOT_ROLLFW daddr_t lfs_sbactive; /* disk address of in-progress sb write */ -#endif struct vnode *lfs_flushvp; /* vnode being flushed */ struct vnode *lfs_unlockvp; /* being inactivated in lfs_segunlock */ u_int32_t lfs_diropwait; /* # procs waiting on dirop flush */ + size_t lfs_devbsize; /* Device block size */ + size_t lfs_devbshift; /* Device block shift */ struct lock lfs_freelock; pid_t lfs_rfpid; /* Process ID of roll-forward agent */ int lfs_nadirop; /* number of active dirop nodes */ @@ -416,7 +435,17 @@ struct ifile { #define LFS_UNUSED_DADDR 0 /* out-of-band daddr */ ufs_daddr_t if_daddr; /* inode disk address */ ino_t if_nextfree; /* next-unallocated inode */ -#ifdef LFS_ATIME_IFILE + /* XXX - when inode format changes, this changes too */ + u_int32_t if_atime_sec; /* Last access time, seconds */ + u_int32_t if_atime_nsec; /* and nanoseconds */ +}; + +typedef struct ifile_v1 IFILE_V1; +struct ifile_v1 { + u_int32_t if_version; /* inode version number */ + ufs_daddr_t if_daddr; /* inode disk address */ + ino_t if_nextfree; /* next-unallocated inode */ +#if LFS_ATIME_IFILE struct timespec if_atime; /* Last access time */ #endif }; @@ -430,6 +459,8 @@ typedef struct _cleanerinfo { u_int32_t dirty; /* number of dirty segments */ u_int32_t bfree; /* disk blocks free */ int32_t avail; /* disk blocks available */ + u_int32_t free_head; /* head of the inode free list */ + u_int32_t free_tail; /* tail of the inode free list */ } CLEANERINFO; #define CLEANSIZE_SU(fs) \ @@ -439,32 +470,54 @@ typedef struct _cleanerinfo { * All summary blocks are the same size, so we can always read a summary * block easily from a segment. */ -#define LFS_SUMMARY_SIZE 512 +#define LFS_V1_SUMMARY_SIZE 512 +#define LFS_DFL_SUMMARY_SIZE 512 /* On-disk segment summary information */ -typedef struct segsum SEGSUM; -struct segsum { - u_int32_t ss_sumsum; /* check sum of summary block */ - u_int32_t ss_datasum; /* check sum of data */ - u_int32_t ss_magic; /* segment summary magic number */ +typedef struct segsum_v1 SEGSUM_V1; +struct segsum_v1 { + u_int32_t ss_sumsum; /* 0: check sum of summary block */ + u_int32_t ss_datasum; /* 4: check sum of data */ + u_int32_t ss_magic; /* 8: segment summary magic number */ #define SS_MAGIC 0x061561 - ufs_daddr_t ss_next; /* next segment */ - u_int32_t ss_create; /* creation time stamp */ - u_int16_t ss_nfinfo; /* number of file info structures */ - u_int16_t ss_ninos; /* number of inodes in summary */ + ufs_daddr_t ss_next; /* 12: next segment */ + u_int32_t ss_create; /* 16: creation time stamp */ + u_int16_t ss_nfinfo; /* 20: number of file info structures */ + u_int16_t ss_ninos; /* 22: number of inodes in summary */ #define SS_DIROP 0x01 /* segment begins a dirop */ #define SS_CONT 0x02 /* more partials to finish this write*/ - u_int16_t ss_flags; /* used for directory operations */ - u_int16_t ss_pad; /* extra space */ + u_int16_t ss_flags; /* 24: used for directory operations */ + u_int16_t ss_pad; /* 26: extra space */ + /* FINFO's and inode daddr's... */ +}; + +typedef struct segsum SEGSUM; +struct segsum { + u_int32_t ss_sumsum; /* 0: check sum of summary block */ + u_int32_t ss_datasum; /* 4: check sum of data */ + u_int32_t ss_magic; /* 8: segment summary magic number */ + ufs_daddr_t ss_next; /* 12: next segment */ + u_int32_t ss_ident; /* 16: roll-forward fsid */ +#define ss_ocreate ss_ident /* ident is where create was in v1 */ + u_int16_t ss_nfinfo; /* 20: number of file info structures */ + u_int16_t ss_ninos; /* 22: number of inodes in summary */ + u_int16_t ss_flags; /* 24: used for directory operations */ + u_int8_t ss_pad[6]; /* 26: extra space */ + u_int64_t ss_serial; /* 32: serial number */ + u_int64_t ss_create; /* 40: time stamp */ /* FINFO's and inode daddr's... */ }; +#define SEGSUM_SIZE(fs) ((fs)->lfs_version == 1 ? sizeof(SEGSUM_V1) : sizeof(SEGSUM)) + /* NINDIR is the number of indirects in a file system block. */ #define NINDIR(fs) ((fs)->lfs_nindir) /* INOPB is the number of inodes in a secondary storage block. */ #define INOPB(fs) ((fs)->lfs_inopb) +/* INOPF is the number of inodes in a fragment. */ +#define INOPF(fs) ((fs)->lfs_inopf) #define blksize(fs, ip, lbn) \ (((lbn) >= NDADDR || (ip)->i_ffs_size >= ((lbn) + 1) << (fs)->lfs_bshift) \ @@ -475,10 +528,20 @@ struct segsum { ((int)((loc) & (fs)->lfs_ffmask)) #define fsbtodb(fs, b) ((b) << (fs)->lfs_fsbtodb) #define dbtofsb(fs, b) ((b) >> (fs)->lfs_fsbtodb) -#define fragstodb(fs, b) ((b) << ((fs)->lfs_fsbtodb - (fs)->lfs_fbshift)) -#define dbtofrags(fs, b) ((b) >> ((fs)->lfs_fsbtodb - (fs)->lfs_fbshift)) +#define fragstodb(fs, b) ((b) << ((fs)->lfs_blktodb - (fs)->lfs_fbshift)) +#define dbtofrags(fs, b) ((b) >> ((fs)->lfs_blktodb - (fs)->lfs_fbshift)) #define lblkno(fs, loc) ((loc) >> (fs)->lfs_bshift) #define lblktosize(fs, blk) ((blk) << (fs)->lfs_bshift) +/* Same as above, but named like dbtob(), btodb() */ +#define fsbtob(fs, b) ((b) << ((fs)->lfs_bshift - \ + (fs)->lfs_blktodb + (fs)->lfs_fsbtodb)) +#define btofsb(fs, b) ((b) >> ((fs)->lfs_bshift - \ + (fs)->lfs_blktodb + (fs)->lfs_fsbtodb)) +#define fsbtofrags(fs, b) ((b) >> ((fs)->lfs_blktodb - (fs)->lfs_fbshift - \ + (fs)->lfs_fsbtodb)) +#define fragstofsb(fs, b) ((b) << ((fs)->lfs_blktodb - (fs)->lfs_fbshift - \ + (fs)->lfs_fsbtodb)) +#define btofrags(fs, b) ((b) >> (fs)->lfs_ffshift) #define numfrags(fs, loc) /* calculates (loc / fs->lfs_fsize) */ \ ((loc) >> (fs)->lfs_ffshift) #define blkroundup(fs, size) /* calculates roundup(size, fs->lfs_bsize) */ \ @@ -497,11 +560,14 @@ struct segsum { (((lbn) >= NDADDR || (dip)->di_size >= ((lbn) + 1) << (fs)->lfs_bshift)\ ? (fs)->lfs_bsize \ : (fragroundup(fs, blkoff(fs, (dip)->di_size)))) -#define datosn(fs, daddr) /* disk address to segment number */ \ - (((daddr) - (fs)->lfs_sboffs[0]) / fsbtodb((fs), (fs)->lfs_ssize)) -#define sntoda(fs, sn) /* segment number to disk address */ \ - ((ufs_daddr_t)((sn) * ((fs)->lfs_ssize << (fs)->lfs_fsbtodb) + \ - (fs)->lfs_sboffs[0])) + +#define segtod(fs, seg) (((fs)->lfs_version == 1 ? \ + (fs)->lfs_ssize << (fs)->lfs_blktodb : \ + btofsb((fs), (fs)->lfs_ssize)) * (seg)) +#define dtosn(fs, daddr) /* block address to segment number */ \ + (((daddr) - (fs)->lfs_start) / segtod((fs), 1)) +#define sntod(fs, sn) /* segment number to disk address */ \ + ((ufs_daddr_t)(segtod((fs), (sn)) + (fs)->lfs_start)) /* Read in the block with the cleaner info from the ifile. */ #define LFS_CLEANERINFO(CP, F, BP) { \ @@ -523,15 +589,52 @@ struct segsum { brelse(bp); \ } while(0) +#define LFS_GET_HEADFREE(FS, CIP, BP, FREEP) do { \ + if ((FS)->lfs_version > 1) { \ + LFS_CLEANERINFO((CIP), (FS), (BP)); \ + (FS)->lfs_free = (CIP)->free_head; \ + brelse(BP); \ + } \ + *(FREEP) = (FS)->lfs_free; \ +} while (0) + +#define LFS_PUT_HEADFREE(FS, CIP, BP, VAL) do { \ + (FS)->lfs_free = (VAL); \ + if ((FS)->lfs_version > 1) { \ + LFS_CLEANERINFO((CIP), (FS), (BP)); \ + (CIP)->free_head = (VAL); \ + VOP_BWRITE(BP); \ + } \ +} while (0) + +#define LFS_GET_TAILFREE(FS, CIP, BP, FREEP) do { \ + LFS_CLEANERINFO((CIP), (FS), (BP)); \ + *(FREEP) = (CIP)->free_tail; \ + brelse(BP); \ +} while (0) + +#define LFS_PUT_TAILFREE(FS, CIP, BP, VAL) do { \ + LFS_CLEANERINFO((CIP), (FS), (BP)); \ + (CIP)->free_tail = (VAL); \ + VOP_BWRITE(BP); \ +} while (0) + +/* + * XXX - v1 compatibility code is not allowed to touch if_atime, since it + * may not be mapped! + */ /* Read in the block with a specific inode from the ifile. */ #define LFS_IENTRY(IP, F, IN, BP) { \ int _e; \ VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS; \ if ((_e = bread((F)->lfs_ivnode, \ - (IN) / (F)->lfs_ifpb + (F)->lfs_cleansz + (F)->lfs_segtabsz,\ - (F)->lfs_bsize, NOCRED, &(BP))) != 0) \ + (IN) / (F)->lfs_ifpb + (F)->lfs_cleansz + (F)->lfs_segtabsz, \ + (F)->lfs_bsize, NOCRED, &(BP))) != 0) \ panic("lfs: ifile read %d", _e); \ - (IP) = (IFILE *)(BP)->b_data + (IN) % (F)->lfs_ifpb; \ + if((F)->lfs_version == 1) \ + (IP) = (IFILE *)((IFILE_V1 *)(BP)->b_data + (IN) % (F)->lfs_ifpb); \ + else \ + (IP) = (IFILE *)(BP)->b_data + (IN) % (F)->lfs_ifpb; \ } /* Read in the block with a specific segment usage entry from the ifile. */ @@ -539,10 +642,14 @@ struct segsum { int _e; \ VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS; \ if ((_e = bread((F)->lfs_ivnode, \ - ((IN) >> (F)->lfs_sushift) + (F)->lfs_cleansz, \ + ((IN) / (F)->lfs_sepb) + (F)->lfs_cleansz, \ (F)->lfs_bsize, NOCRED, &(BP))) != 0) \ panic("lfs: ifile read: %d", _e); \ - (SP) = (SEGUSE *)(BP)->b_data + ((IN) & ((F)->lfs_sepb - 1)); \ + if ((F)->lfs_version == 1) \ + (SP) = (SEGUSE *)((SEGUSE_V1 *)(BP)->b_data + \ + ((IN) & ((F)->lfs_sepb - 1))); \ + else \ + (SP) = (SEGUSE *)(BP)->b_data + ((IN) % (F)->lfs_sepb); \ } /* Determine if a buffer belongs to the ifile */ @@ -556,12 +663,23 @@ typedef struct block_info { ino_t bi_inode; /* inode # */ ufs_daddr_t bi_lbn; /* logical block w/in file */ ufs_daddr_t bi_daddr; /* disk address of block */ - time_t bi_segcreate; /* origin segment create time */ + u_int64_t bi_segcreate; /* origin segment create time */ int bi_version; /* file version number */ void *bi_bp; /* data buffer */ int bi_size; /* size of the block (if fragment) */ } BLOCK_INFO; +/* Compatibility for 1.5 binaries */ +typedef struct block_info_15 { + ino_t bi_inode; /* inode # */ + ufs_daddr_t bi_lbn; /* logical block w/in file */ + ufs_daddr_t bi_daddr; /* disk address of block */ + u_int32_t bi_segcreate; /* origin segment create time */ + int bi_version; /* file version number */ + void *bi_bp; /* data buffer */ + int bi_size; /* size of the block (if fragment) */ +} BLOCK_INFO_15; + /* In-memory description of a segment about to be written. */ struct segment { struct lfs *fs; /* file system pointer */ diff --git a/sys/ufs/lfs/lfs_alloc.c b/sys/ufs/lfs/lfs_alloc.c index 1562679e67c..7b030efe39e 100644 --- a/sys/ufs/lfs/lfs_alloc.c +++ b/sys/ufs/lfs/lfs_alloc.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_alloc.c,v 1.47 2001/05/30 11:57:18 mrg Exp $ */ +/* $NetBSD: lfs_alloc.c,v 1.48 2001/07/13 20:30:23 perseant Exp $ */ /*- * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. @@ -111,11 +111,12 @@ lfs_rf_valloc(struct lfs *fs, ino_t ino, int version, struct proc *p, struct vnode **vpp) { IFILE *ifp; - struct buf *bp; + struct buf *bp, *cbp; struct vnode *vp; struct inode *ip; ino_t tino, oldnext; int error; + CLEANERINFO *cip; /* * First, just try a vget. If the version number is the one we want, @@ -148,9 +149,9 @@ lfs_rf_valloc(struct lfs *fs, ino_t ino, int version, struct proc *p, * The inode is not in use. Find it on the free list. */ /* If the Ifile is too short to contain this inum, extend it */ - while (VTOI(fs->lfs_ivnode)->i_ffs_size <= - dbtob(fsbtodb(fs, ino / fs->lfs_ifpb + fs->lfs_cleansz + - fs->lfs_segtabsz))) { + while (VTOI(fs->lfs_ivnode)->i_ffs_size <= (ino / + fs->lfs_ifpb + fs->lfs_cleansz + fs->lfs_segtabsz) + << fs->lfs_bshift) { extend_ifile(fs, NOCRED); } @@ -159,10 +160,11 @@ lfs_rf_valloc(struct lfs *fs, ino_t ino, int version, struct proc *p, ifp->if_version = version; brelse(bp); - if (ino == fs->lfs_free) { - fs->lfs_free = oldnext; + LFS_GET_HEADFREE(fs, cip, cbp, &ino); + if (ino) { + LFS_PUT_HEADFREE(fs, cip, cbp, oldnext); } else { - tino = fs->lfs_free; + tino = ino; while(1) { LFS_IENTRY(ifp, fs, tino, bp); if (ifp->if_nextfree == ino || @@ -211,10 +213,12 @@ extend_ifile(struct lfs *fs, struct ucred *cred) struct vnode *vp; struct inode *ip; IFILE *ifp; - struct buf *bp; + IFILE_V1 *ifp_v1; + struct buf *bp, *cbp; int error; ufs_daddr_t i, blkno, max; ino_t oldlast; + CLEANERINFO *cip; vp = fs->lfs_ivnode; (void)lfs_vref(vp); @@ -233,21 +237,33 @@ extend_ifile(struct lfs *fs, struct ucred *cred) i = (blkno - fs->lfs_segtabsz - fs->lfs_cleansz) * fs->lfs_ifpb; - oldlast = fs->lfs_free; - fs->lfs_free = i; + LFS_GET_HEADFREE(fs, cip, cbp, &oldlast); + LFS_PUT_HEADFREE(fs, cip, cbp, i); #ifdef DIAGNOSTIC if(fs->lfs_free == LFS_UNUSED_INUM) panic("inode 0 allocated [2]"); #endif /* DIAGNOSTIC */ max = i + fs->lfs_ifpb; /* printf("extend ifile for ino %d--%d\n", i, max); */ - for (ifp = (struct ifile *)bp->b_data; i < max; ++ifp) { - ifp->if_version = 1; - ifp->if_daddr = LFS_UNUSED_DADDR; - ifp->if_nextfree = ++i; + + if(fs->lfs_version == 1) { + for (ifp_v1 = (IFILE_V1 *)bp->b_data; i < max; ++ifp_v1) { + ifp_v1->if_version = 1; + ifp_v1->if_daddr = LFS_UNUSED_DADDR; + ifp_v1->if_nextfree = ++i; + } + ifp_v1--; + ifp_v1->if_nextfree = oldlast; + } else { + for (ifp = (IFILE *)bp->b_data; i < max; ++ifp) { + ifp->if_version = 1; + ifp->if_daddr = LFS_UNUSED_DADDR; + ifp->if_nextfree = ++i; + } + ifp--; + ifp->if_nextfree = oldlast; } - ifp--; - ifp->if_nextfree = oldlast; + (void) VOP_BWRITE(bp); /* Ifile */ lfs_vunref(vp); @@ -258,8 +274,7 @@ extend_ifile(struct lfs *fs, struct ucred *cred) /* ARGSUSED */ /* VOP_BWRITE 2i times */ int -lfs_valloc(v) - void *v; +lfs_valloc(void *v) { struct vop_valloc_args /* { struct vnode *a_pvp; @@ -268,30 +283,33 @@ lfs_valloc(v) struct vnode **a_vpp; } */ *ap = v; struct lfs *fs; - struct buf *bp; + struct buf *bp, *cbp; struct ifile *ifp; ino_t new_ino; int error; int new_gen; + CLEANERINFO *cip; fs = VTOI(ap->a_pvp)->i_lfs; if (fs->lfs_ronly) return EROFS; *ap->a_vpp = NULL; - /* - * Use lfs_seglock here, instead of fs->lfs_freelock, to ensure that - * the free list is not changed in between the time that the ifile - * blocks are written to disk and the time that the superblock is - * written to disk. - * - * XXX this sucks. We should instead encode the head of the free - * list into the CLEANERINFO block of the Ifile. [XXX v2] - */ - lfs_seglock(fs, SEGM_PROT); + if (fs->lfs_version == 1) { + /* + * Use lfs_seglock here, instead of fs->lfs_freelock, to + * ensure that the free list is not changed in between + * the time that the ifile blocks are written to disk + * and the time that the superblock is written to disk. + */ + lfs_seglock(fs, SEGM_PROT); + } else { + lockmgr(&fs->lfs_freelock, LK_EXCLUSIVE, 0); + } /* Get the head of the freelist. */ - new_ino = fs->lfs_free; + LFS_GET_HEADFREE(fs, cip, cbp, &new_ino); + #ifdef DIAGNOSTIC if(new_ino == LFS_UNUSED_INUM) { #ifdef DEBUG @@ -311,15 +329,19 @@ lfs_valloc(v) LFS_IENTRY(ifp, fs, new_ino, bp); if (ifp->if_daddr != LFS_UNUSED_DADDR) panic("lfs_valloc: inuse inode %d on the free list", new_ino); - fs->lfs_free = ifp->if_nextfree; + LFS_PUT_HEADFREE(fs, cip, cbp, ifp->if_nextfree); + new_gen = ifp->if_version; /* version was updated by vfree */ brelse(bp); /* Extend IFILE so that the next lfs_valloc will succeed. */ if (fs->lfs_free == LFS_UNUSED_INUM) { if ((error = extend_ifile(fs, ap->a_cred)) != 0) { - fs->lfs_free = new_ino; - lfs_segunlock(fs); + LFS_PUT_HEADFREE(fs, cip, cbp, new_ino); + if (fs->lfs_version == 1) + lfs_segunlock(fs); + else + lockmgr(&fs->lfs_freelock, LK_RELEASE, 0); return error; } } @@ -327,8 +349,11 @@ lfs_valloc(v) if(fs->lfs_free == LFS_UNUSED_INUM) panic("inode 0 allocated [3]"); #endif /* DIAGNOSTIC */ - - lfs_segunlock(fs); + + if (fs->lfs_version == 1) + lfs_segunlock(fs); + else + lockmgr(&fs->lfs_freelock, LK_RELEASE, 0); return lfs_ialloc(fs, ap->a_pvp, new_ino, new_gen, ap->a_vpp); } @@ -340,8 +365,9 @@ lfs_ialloc(struct lfs *fs, struct vnode *pvp, ino_t new_ino, int new_gen, struct inode *ip; struct vnode *vp; IFILE *ifp; - struct buf *bp; + struct buf *bp, *cbp; int error; + CLEANERINFO *cip; error = getnewvnode(VT_LFS, pvp->v_mount, lfs_vnodeop_p, &vp); /* printf("lfs_ialloc: ino %d vp %p error %d\n", new_ino, vp, error);*/ @@ -353,6 +379,7 @@ lfs_ialloc(struct lfs *fs, struct vnode *pvp, ino_t new_ino, int new_gen, lfs_vcreate(pvp->v_mount, new_ino, vp); ip = VTOI(vp); + LFS_SET_UINO(ip, IN_CHANGE | IN_MODIFIED); /* Zero out the direct and indirect block addresses. */ bzero(&ip->i_din, sizeof(ip->i_din)); ip->i_din.ffs_din.di_inumber = new_ino; @@ -397,8 +424,8 @@ lfs_ialloc(struct lfs *fs, struct vnode *pvp, ino_t new_ino, int new_gen, */ LFS_IENTRY(ifp, fs, new_ino, bp); ifp->if_daddr = LFS_UNUSED_DADDR; - ifp->if_nextfree = fs->lfs_free; - fs->lfs_free = new_ino; + LFS_GET_HEADFREE(fs, cip, cbp, &(ifp->if_nextfree)); + LFS_PUT_HEADFREE(fs, cip, cbp, new_ino); (void) VOP_BWRITE(bp); /* Ifile */ *vpp = NULLVP; @@ -407,10 +434,7 @@ lfs_ialloc(struct lfs *fs, struct vnode *pvp, ino_t new_ino, int new_gen, /* Create a new vnode/inode pair and initialize what fields we can. */ void -lfs_vcreate(mp, ino, vp) - struct mount *mp; - ino_t ino; - struct vnode *vp; +lfs_vcreate(struct mount *mp, ino_t ino, struct vnode *vp) { struct inode *ip; struct ufsmount *ump; @@ -440,15 +464,15 @@ lfs_vcreate(mp, ino, vp) ip->i_ffs_blocks = 0; ip->i_lfs_effnblks = 0; ip->i_flag = 0; - LFS_SET_UINO(ip, IN_CHANGE | IN_MODIFIED); + /* Why was IN_MODIFIED ever set here? */ + /* LFS_SET_UINO(ip, IN_CHANGE | IN_MODIFIED); */ } /* Free an inode. */ /* ARGUSED */ /* VOP_BWRITE 2i times */ int -lfs_vfree(v) - void *v; +lfs_vfree(void *v) { struct vop_vfree_args /* { struct vnode *a_pvp; @@ -456,13 +480,14 @@ lfs_vfree(v) int a_mode; } */ *ap = v; SEGUSE *sup; - struct buf *bp; + CLEANERINFO *cip; + struct buf *cbp, *bp; struct ifile *ifp; struct inode *ip; struct vnode *vp; struct lfs *fs; ufs_daddr_t old_iaddr; - ino_t ino; + ino_t ino, otail; extern int lfs_dirvcount; /* Get the inode number and file system. */ @@ -471,17 +496,14 @@ lfs_vfree(v) fs = ip->i_lfs; ino = ip->i_number; -#if 0 - /* - * Right now this is unnecessary since we take the seglock. - * But if the seglock is no longer necessary (e.g. we put the - * head of the free list into the Ifile) we will need to drain - * this vnode of any pending writes. - */ - if (WRITEINPROG(vp)) + /* Drain of pending writes */ + if (fs->lfs_version > 1 && WRITEINPROG(vp)) tsleep(vp, (PRIBIO+1), "lfs_vfree", 0); -#endif - lfs_seglock(fs, SEGM_PROT); + + if (fs->lfs_version == 1) + lfs_seglock(fs, SEGM_PROT); + else + lockmgr(&fs->lfs_freelock, LK_EXCLUSIVE, 0); if(vp->v_flag & VDIROP) { --lfs_dirvcount; @@ -499,27 +521,43 @@ lfs_vfree(v) /* * Set the ifile's inode entry to unused, increment its version number - * and link it into the free chain. + * and link it onto the free chain. */ LFS_IENTRY(ifp, fs, ino, bp); old_iaddr = ifp->if_daddr; ifp->if_daddr = LFS_UNUSED_DADDR; ++ifp->if_version; - ifp->if_nextfree = fs->lfs_free; - fs->lfs_free = ino; - (void) VOP_BWRITE(bp); /* Ifile */ + if (fs->lfs_version == 1) { + LFS_GET_HEADFREE(fs, cip, cbp, &(ifp->if_nextfree)); + LFS_PUT_HEADFREE(fs, cip, cbp, ino); + (void) VOP_BWRITE(bp); /* Ifile */ + } else { + ifp->if_nextfree = LFS_UNUSED_INUM; + /* + * XXX Writing the freed node here means that it might not + * XXX make it into the free list in the event of a crash + * XXX (the ifile could be written before the rest of this + * XXX completes). + */ + (void) VOP_BWRITE(bp); /* Ifile */ + LFS_GET_TAILFREE(fs, cip, cbp, &otail); + LFS_IENTRY(ifp, fs, otail, bp); + ifp->if_nextfree = ino; + VOP_BWRITE(bp); + LFS_PUT_TAILFREE(fs, cip, cbp, ino); + } #ifdef DIAGNOSTIC - if(fs->lfs_free == LFS_UNUSED_INUM) { + if(ino == LFS_UNUSED_INUM) { panic("inode 0 freed"); } #endif /* DIAGNOSTIC */ if (old_iaddr != LFS_UNUSED_DADDR) { - LFS_SEGENTRY(sup, fs, datosn(fs, old_iaddr), bp); + LFS_SEGENTRY(sup, fs, dtosn(fs, old_iaddr), bp); #ifdef DIAGNOSTIC if (sup->su_nbytes < DINODE_SIZE) { printf("lfs_vfree: negative byte count" " (segment %d short by %d)\n", - datosn(fs, old_iaddr), + dtosn(fs, old_iaddr), (int)DINODE_SIZE - sup->su_nbytes); panic("lfs_vfree: negative byte count"); sup->su_nbytes = DINODE_SIZE; @@ -533,6 +571,9 @@ lfs_vfree(v) fs->lfs_fmod = 1; --fs->lfs_nfiles; - lfs_segunlock(fs); + if (fs->lfs_version == 1) + lfs_segunlock(fs); + else + lockmgr(&fs->lfs_freelock, LK_RELEASE, 0); return (0); } diff --git a/sys/ufs/lfs/lfs_balloc.c b/sys/ufs/lfs/lfs_balloc.c index 85bede076d7..5698f983644 100644 --- a/sys/ufs/lfs/lfs_balloc.c +++ b/sys/ufs/lfs/lfs_balloc.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_balloc.c,v 1.28 2001/05/30 11:57:18 mrg Exp $ */ +/* $NetBSD: lfs_balloc.c,v 1.29 2001/07/13 20:30:23 perseant Exp $ */ /*- * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. @@ -93,7 +93,7 @@ #include <ufs/lfs/lfs.h> #include <ufs/lfs/lfs_extern.h> -int lfs_fragextend __P((struct vnode *, int, int, ufs_daddr_t, struct buf **)); +int lfs_fragextend(struct vnode *, int, int, ufs_daddr_t, struct buf **, struct ucred *); /* * Allocate a block, and to inode and filesystem block accounting for it @@ -110,8 +110,7 @@ int lfs_fragextend __P((struct vnode *, int, int, ufs_daddr_t, struct buf **)); */ /* VOP_BWRITE NIADDR+2 times */ int -lfs_balloc(v) - void *v; +lfs_balloc(void *v) { struct vop_balloc_args /* { struct vnode *a_vp; @@ -165,7 +164,8 @@ lfs_balloc(v) osize = blksize(fs, ip, lastblock); if (osize < fs->lfs_bsize && osize > 0) { if ((error = lfs_fragextend(vp, osize, fs->lfs_bsize, - lastblock, &bp))) + lastblock, &bp, + ap->a_cred))) return(error); ip->i_ffs_size = (lastblock + 1) * fs->lfs_bsize; uvm_vnp_setsize(vp, ip->i_ffs_size); @@ -188,7 +188,7 @@ lfs_balloc(v) if (lblktosize(fs, lbn) >= ip->i_ffs_size) { /* Brand new block or fragment */ frags = numfrags(fs, nsize); - bb = fragstodb(fs, frags); + bb = fragstofsb(fs, frags); *ap->a_bpp = bp = getblk(vp, lbn, nsize, 0, 0); ip->i_lfs_effnblks += bb; ip->i_lfs->lfs_bfree -= bb; @@ -201,7 +201,8 @@ lfs_balloc(v) } else { /* Extend existing block */ if ((error = - lfs_fragextend(vp, osize, nsize, lbn, &bp))) + lfs_fragextend(vp, osize, nsize, lbn, &bp, + ap->a_cred))) return error; } *ap->a_bpp = bp; @@ -249,7 +250,7 @@ lfs_balloc(v) clrbuf(ibp); ibp->b_blkno = UNWRITTEN; } else if (!(ibp->b_flags & (B_DELWRI | B_DONE))) { - ibp->b_blkno = idaddr; + ibp->b_blkno = fsbtodb(fs, idaddr); ibp->b_flags |= B_READ; VOP_STRATEGY(ibp); biowait(ibp); @@ -273,7 +274,7 @@ lfs_balloc(v) /* * Get the existing block from the cache. */ - frags = dbtofrags(fs, bb); + frags = fsbtofrags(fs, bb); *ap->a_bpp = bp = getblk(vp, lbn, blksize(fs, ip, lbn), 0, 0); /* @@ -331,12 +332,7 @@ lfs_balloc(v) /* VOP_BWRITE 1 time */ int -lfs_fragextend(vp, osize, nsize, lbn, bpp) - struct vnode *vp; - int osize; - int nsize; - ufs_daddr_t lbn; - struct buf **bpp; +lfs_fragextend(struct vnode *vp, int osize, int nsize, ufs_daddr_t lbn, struct buf **bpp, struct ucred *cred) { struct inode *ip; struct lfs *fs; @@ -349,7 +345,7 @@ lfs_fragextend(vp, osize, nsize, lbn, bpp) ip = VTOI(vp); fs = ip->i_lfs; - bb = (long)fragstodb(fs, numfrags(fs, nsize - osize)); + bb = (long)fragstofsb(fs, numfrags(fs, nsize - osize)); error = 0; /* @@ -359,7 +355,7 @@ lfs_fragextend(vp, osize, nsize, lbn, bpp) top: lfs_seglock(fs, SEGM_PROT); - if (!ISSPACE(fs, bb, curproc->p_ucred)) { + if (!ISSPACE(fs, bb, cred)) { error = ENOSPC; goto out; } @@ -368,7 +364,7 @@ lfs_fragextend(vp, osize, nsize, lbn, bpp) goto out; } #ifdef QUOTA - if ((error = chkdq(ip, bb, curproc->p_ucred, 0))) { + if ((error = chkdq(ip, bb, cred, 0))) { brelse(*bpp); goto out; } @@ -383,7 +379,7 @@ lfs_fragextend(vp, osize, nsize, lbn, bpp) if (!lfs_fits(fs, bb)) { brelse(*bpp); #ifdef QUOTA - chkdq(ip, -bb, curproc->p_ucred, 0); + chkdq(ip, -bb, cred, 0); #endif lfs_segunlock(fs); lfs_availwait(fs, bb); @@ -399,7 +395,7 @@ lfs_fragextend(vp, osize, nsize, lbn, bpp) * is written, so the on-disk live bytes count is always correct. */ if ((*bpp)->b_blkno > 0) { - LFS_SEGENTRY(sup, fs, datosn(fs, (*bpp)->b_blkno), ibp); + LFS_SEGENTRY(sup, fs, dtosn(fs, dbtofsb(fs, (*bpp)->b_blkno)), ibp); sup->su_nbytes += (nsize - osize); VOP_BWRITE(ibp); ip->i_ffs_blocks += bb; diff --git a/sys/ufs/lfs/lfs_bio.c b/sys/ufs/lfs/lfs_bio.c index 413401b35c1..75d95554df0 100644 --- a/sys/ufs/lfs/lfs_bio.c +++ b/sys/ufs/lfs/lfs_bio.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_bio.c,v 1.35 2000/12/03 06:43:36 perseant Exp $ */ +/* $NetBSD: lfs_bio.c,v 1.36 2001/07/13 20:30:23 perseant Exp $ */ /*- * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. @@ -115,10 +115,7 @@ extern int lfs_dostats; * Called with vp locked. (Note nowever that if nb < 0, vp is ignored.) */ int -lfs_reserve(fs, vp, nb) - struct lfs *fs; - struct vnode *vp; - int nb; +lfs_reserve(struct lfs *fs, struct vnode *vp, int nb) { CLEANERINFO *cip; struct buf *bp; @@ -169,8 +166,7 @@ lfs_reserve(fs, vp, nb) #define CANT_WAIT(BP,F) (IS_IFILE((BP)) || (BP)->b_lblkno<0 || ((F) & BW_CLEAN)) int -lfs_bwrite(v) - void *v; +lfs_bwrite(void *v) { struct vop_bwrite_args /* { struct buf *a_bp; @@ -195,19 +191,19 @@ lfs_bwrite(v) * the segment usage table, plus an ifile page. */ int -lfs_fits(struct lfs *fs, int db) +lfs_fits(struct lfs *fs, int fsb) { int needed; - needed = db + btodb(LFS_SUMMARY_SIZE) + + needed = fsb + btofsb(fs, fs->lfs_sumsize) + fsbtodb(fs, howmany(fs->lfs_uinodes + 1, INOPB(fs)) + - fs->lfs_segtabsz + 1); + fs->lfs_segtabsz + btofsb(fs, fs->lfs_sumsize)); if (needed >= fs->lfs_avail) { #ifdef DEBUG - printf("lfs_fits: no fit: db = %d, uinodes = %d, " + printf("lfs_fits: no fit: fsb = %d, uinodes = %d, " "needed = %d, avail = %d\n", - db, fs->lfs_uinodes, needed, fs->lfs_avail); + fsb, fs->lfs_uinodes, needed, fs->lfs_avail); #endif return 0; } @@ -215,9 +211,7 @@ lfs_fits(struct lfs *fs, int db) } int -lfs_availwait(fs, db) - struct lfs *fs; - int db; +lfs_availwait(struct lfs *fs, int db) { int error; CLEANERINFO *cip; @@ -250,13 +244,11 @@ lfs_availwait(fs, db) } int -lfs_bwrite_ext(bp, flags) - struct buf *bp; - int flags; +lfs_bwrite_ext(struct buf *bp, int flags) { struct lfs *fs; struct inode *ip; - int db, error, s; + int fsb, error, s; /* * Don't write *any* blocks if we're mounted read-only. @@ -288,9 +280,9 @@ lfs_bwrite_ext(bp, flags) */ if (!(bp->b_flags & B_LOCKED)) { fs = VFSTOUFS(bp->b_vp->v_mount)->um_lfs; - db = fragstodb(fs, numfrags(fs, bp->b_bcount)); + fsb = fragstofsb(fs, numfrags(fs, bp->b_bcount)); if (!CANT_WAIT(bp, flags)) { - if ((error = lfs_availwait(fs, db)) != 0) { + if ((error = lfs_availwait(fs, fsb)) != 0) { brelse(bp); return error; } @@ -300,9 +292,11 @@ lfs_bwrite_ext(bp, flags) if (bp->b_flags & B_CALL) { LFS_SET_UINO(ip, IN_CLEANING); } else { - LFS_SET_UINO(ip, IN_CHANGE | IN_MODIFIED | IN_UPDATE); + LFS_SET_UINO(ip, IN_MODIFIED); + if (bp->b_lblkno >= 0) + LFS_SET_UINO(ip, IN_UPDATE); } - fs->lfs_avail -= db; + fs->lfs_avail -= fsb; bp->b_flags |= B_DELWRI; LFS_LOCK_BUF(bp); @@ -322,9 +316,7 @@ lfs_bwrite_ext(bp, flags) } void -lfs_flush_fs(fs, flags) - struct lfs *fs; - int flags; +lfs_flush_fs(struct lfs *fs, int flags) { if(fs->lfs_ronly == 0 && fs->lfs_dirops == 0) { @@ -359,9 +351,7 @@ lfs_flush_fs(fs, flags) * work for multiple file systems, put the count into the mount structure. */ void -lfs_flush(fs, flags) - struct lfs *fs; - int flags; +lfs_flush(struct lfs *fs, int flags) { int s; struct mount *mp, *nmp; @@ -401,10 +391,7 @@ lfs_flush(fs, flags) } int -lfs_check(vp, blkno, flags) - struct vnode *vp; - ufs_daddr_t blkno; - int flags; +lfs_check(struct vnode *vp, ufs_daddr_t blkno, int flags) { int error; struct lfs *fs; @@ -453,7 +440,7 @@ lfs_check(vp, blkno, flags) { if(lfs_dostats) ++lfs_stats.wait_exceeded; -#ifdef DEBUG +#ifdef DEBUG_LFS printf("lfs_check: waiting: count=%d, bytes=%ld\n", locked_queue_count, locked_queue_bytes); #endif @@ -485,26 +472,18 @@ lfs_check(vp, blkno, flags) #ifdef MALLOCLOG # define DOMALLOC(S, T, F) _malloc((S), (T), (F), file, line) struct buf * -lfs_newbuf_malloclog(vp, daddr, size, file, line) - struct vnode *vp; - ufs_daddr_t daddr; - size_t size; - char *file; - int line; +lfs_newbuf_malloclog(struct lfs *fs, struct vnode *vp, ufs_daddr_t daddr, size_t size, char *file, int line) #else # define DOMALLOC(S, T, F) malloc((S), (T), (F)) struct buf * -lfs_newbuf(vp, daddr, size) - struct vnode *vp; - ufs_daddr_t daddr; - size_t size; +lfs_newbuf(struct lfs *fs, struct vnode *vp, ufs_daddr_t daddr, size_t size) #endif { struct buf *bp; size_t nbytes; int s; - nbytes = roundup(size, DEV_BSIZE); + nbytes = roundup(size, fsbtob(fs, 1)); bp = DOMALLOC(sizeof(struct buf), M_SEGMENT, M_WAITOK); bzero(bp, sizeof(struct buf)); @@ -538,15 +517,11 @@ lfs_newbuf(vp, daddr, size) #ifdef MALLOCLOG # define DOFREE(A, T) _free((A), (T), file, line) void -lfs_freebuf_malloclog(bp, file, line) - struct buf *bp; - char *file; - int line; +lfs_freebuf_malloclog(struct buf *bp, char *file, int line) #else # define DOFREE(A, T) free((A), (T)) void -lfs_freebuf(bp) - struct buf *bp; +lfs_freebuf(struct buf *bp) #endif { int s; @@ -579,9 +554,7 @@ extern TAILQ_HEAD(bqueues, buf) bufqueues[BQUEUES]; * Don't count malloced buffers, since they don't detract from the total. */ void -lfs_countlocked(count, bytes) - int *count; - long *bytes; +lfs_countlocked(int *count, long *bytes) { struct buf *bp; int n = 0; diff --git a/sys/ufs/lfs/lfs_cksum.c b/sys/ufs/lfs/lfs_cksum.c index 4f0be883bc0..ea460f87803 100644 --- a/sys/ufs/lfs/lfs_cksum.c +++ b/sys/ufs/lfs/lfs_cksum.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_cksum.c,v 1.15 2001/02/04 21:51:19 christos Exp $ */ +/* $NetBSD: lfs_cksum.c,v 1.16 2001/07/13 20:30:23 perseant Exp $ */ /*- * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. @@ -91,9 +91,7 @@ * Use the TCP/IP checksum instead. */ u_int32_t -cksum(str, len) - void *str; - size_t len; +cksum(void *str, size_t len) { u_int32_t sum; @@ -106,8 +104,7 @@ cksum(str, len) } u_int32_t -lfs_sb_cksum(fs) - struct dlfs *fs; +lfs_sb_cksum(struct dlfs *fs) { size_t size; diff --git a/sys/ufs/lfs/lfs_debug.c b/sys/ufs/lfs/lfs_debug.c index ca233082c7b..17268c1dc7b 100644 --- a/sys/ufs/lfs/lfs_debug.c +++ b/sys/ufs/lfs/lfs_debug.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_debug.c,v 1.11 2000/09/09 04:49:54 perseant Exp $ */ +/* $NetBSD: lfs_debug.c,v 1.12 2001/07/13 20:30:23 perseant Exp $ */ /*- * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. @@ -83,8 +83,7 @@ #include <ufs/lfs/lfs_extern.h> void -lfs_dump_super(lfsp) - struct lfs *lfsp; +lfs_dump_super(struct lfs *lfsp) { int i; @@ -146,12 +145,11 @@ lfs_dump_super(lfsp) "nextseg ", lfsp->lfs_nextseg, "curseg ", lfsp->lfs_curseg, "offset ", lfsp->lfs_offset); - printf("tstamp %x\n", lfsp->lfs_tstamp); + printf("tstamp %llx\n", (long long)lfsp->lfs_tstamp); } void -lfs_dump_dinode(dip) - struct dinode *dip; +lfs_dump_dinode(struct dinode *dip) { int i; @@ -195,11 +193,11 @@ lfs_check_segsum(struct lfs *fs, struct segment *sp, char *file, int line) if(sp->sum_bytes_left > 484) { printf("%s:%d: bad value (%d = -%d) for sum_bytes_left\n", - file, line, sp->sum_bytes_left, LFS_SUMMARY_SIZE-sp->sum_bytes_left); + file, line, sp->sum_bytes_left, fs->lfs_sumsize-sp->sum_bytes_left); panic("too many bytes"); } - actual = LFS_SUMMARY_SIZE + actual = fs->lfs_sumsize /* amount taken up by FINFOs */ - ((char *)&(sp->fip->fi_blocks[sp->fip->fi_nblocks]) - (char *)(sp->segsum)) /* amount taken up by inode blocks */ @@ -217,16 +215,16 @@ lfs_check_segsum(struct lfs *fs, struct segment *sp, char *file, int line) if(actual != sp->sum_bytes_left) printf("%s:%d: warning: segsum miscalc at %d (-%d => %d)\n", file, line, sp->sum_bytes_left, - LFS_SUMMARY_SIZE-sp->sum_bytes_left, + fs->lfs_sumsize-sp->sum_bytes_left, actual); #endif if(sp->sum_bytes_left > 0 - && ((char *)(sp->segsum))[LFS_SUMMARY_SIZE + && ((char *)(sp->segsum))[fs->lfs_sumsize - sizeof(ufs_daddr_t) * ((sp->ninodes+INOPB(fs)-1) / INOPB(fs)) - sp->sum_bytes_left] != '\0') { printf("%s:%d: warning: segsum overwrite at %d (-%d => %d)\n", file, line, sp->sum_bytes_left, - LFS_SUMMARY_SIZE-sp->sum_bytes_left, + fs->lfs_sumsize-sp->sum_bytes_left, actual); #ifdef DDB Debugger(); @@ -235,11 +233,7 @@ lfs_check_segsum(struct lfs *fs, struct segment *sp, char *file, int line) } void -lfs_check_bpp(fs, sp, file, line) - struct lfs *fs; - struct segment *sp; - char *file; - int line; +lfs_check_bpp(struct lfs *fs, struct segment *sp, char *file, int line) { daddr_t blkno; struct buf **bpp; @@ -263,7 +257,7 @@ lfs_check_bpp(fs, sp, file, line) (*bpp)->b_blkno); } } - blkno += btodb((*bpp)->b_bcount); + blkno += fsbtodb(fs, btofsb(fs, (*bpp)->b_bcount)); } } #endif /* DEBUG */ diff --git a/sys/ufs/lfs/lfs_extern.h b/sys/ufs/lfs/lfs_extern.h index 443934931e0..dd9bfcfe3a7 100644 --- a/sys/ufs/lfs/lfs_extern.h +++ b/sys/ufs/lfs/lfs_extern.h @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_extern.h,v 1.24 2000/12/03 05:56:27 perseant Exp $ */ +/* $NetBSD: lfs_extern.h,v 1.25 2001/07/13 20:30:23 perseant Exp $ */ /*- * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. @@ -111,122 +111,121 @@ extern struct pool lfs_inode_pool; /* memory pool for inodes */ __BEGIN_DECLS /* lfs_alloc.c */ -int lfs_rf_valloc __P((struct lfs *, ino_t, int, struct proc *, struct vnode **)); -void lfs_vcreate __P((struct mount *, ino_t, struct vnode *)); +int lfs_rf_valloc(struct lfs *, ino_t, int, struct proc *, struct vnode **); +void lfs_vcreate(struct mount *, ino_t, struct vnode *); /* lfs_bio.c */ -int lfs_availwait __P((struct lfs *, int)); -int lfs_bwrite_ext __P((struct buf *, int)); -int lfs_fits __P((struct lfs *, int)); -void lfs_flush_fs __P((struct lfs *, int)); -void lfs_flush __P((struct lfs *, int)); -int lfs_check __P((struct vnode *, ufs_daddr_t, int)); +int lfs_availwait(struct lfs *, int); +int lfs_bwrite_ext(struct buf *, int); +int lfs_fits(struct lfs *, int); +void lfs_flush_fs(struct lfs *, int); +void lfs_flush(struct lfs *, int); +int lfs_check(struct vnode *, ufs_daddr_t, int); #ifdef MALLOCLOG -void lfs_freebuf_malloclog __P((struct buf *, char *, int)); -struct buf *lfs_newbuf_malloclog __P((struct vnode *, ufs_daddr_t, size_t, - char *, int)); +void lfs_freebuf_malloclog(struct buf *, char *, int); +struct buf *lfs_newbuf_malloclog(struct lfs *, struct vnode *, + ufs_daddr_t, size_t, char *, int); #define lfs_freebuf(BP) lfs_freebuf_malloclog((BP), __FILE__, __LINE__) -#define lfs_newbuf(V, A, S) lfs_newbuf_malloclog((V),(A),(S),__FILE__,__LINE__) +#define lfs_newbuf(F, V, A, S) lfs_newbuf_malloclog((F),(V),(A),(S),__FILE__,__LINE__) #else -void lfs_freebuf __P((struct buf *)); -struct buf *lfs_newbuf __P((struct vnode *, ufs_daddr_t, size_t)); +void lfs_freebuf(struct buf *); +struct buf *lfs_newbuf(struct lfs *, struct vnode *, ufs_daddr_t, size_t); #endif -void lfs_countlocked __P((int *, long *)); -int lfs_reserve __P((struct lfs *, struct vnode *, int)); +void lfs_countlocked(int *, long *); +int lfs_reserve(struct lfs *, struct vnode *, int); /* lfs_cksum.c */ -u_int32_t cksum __P((void *, size_t)); -u_int32_t lfs_sb_cksum __P((struct dlfs *)); +u_int32_t cksum(void *, size_t); +u_int32_t lfs_sb_cksum(struct dlfs *); /* lfs_debug.c */ #ifdef DEBUG -void lfs_dump_super __P((struct lfs *)); -void lfs_dump_dinode __P((struct dinode *)); -void lfs_check_bpp __P((struct lfs *, struct segment *, char *, int)); -void lfs_check_segsum __P((struct lfs *, struct segment *, char *, int)); +void lfs_dump_super(struct lfs *); +void lfs_dump_dinode(struct dinode *); +void lfs_check_bpp(struct lfs *, struct segment *, char *, int); +void lfs_check_segsum(struct lfs *, struct segment *, char *, int); #endif /* DEBUG */ /* lfs_inode.c */ -struct dinode *lfs_ifind __P((struct lfs *, ino_t, struct buf *)); +struct dinode *lfs_ifind(struct lfs *, ino_t, struct buf *); /* lfs_segment.c */ -void lfs_imtime __P((struct lfs *)); -int lfs_vflush __P((struct vnode *)); -int lfs_writevnodes __P((struct lfs *, struct mount *, struct segment *, int)); -int lfs_segwrite __P((struct mount *, int)); -void lfs_writefile __P((struct lfs *, struct segment *, struct vnode *)); -int lfs_writeinode __P((struct lfs *, struct segment *, struct inode *)); -int lfs_gatherblock __P((struct segment *, struct buf *, int *)); -int lfs_gather __P((struct lfs *, struct segment *, struct vnode *, int (*match )__P ((struct lfs *, struct buf *)))); -void lfs_updatemeta __P((struct segment *)); -int lfs_initseg __P((struct lfs *)); -void lfs_newseg __P((struct lfs *)); -int lfs_writeseg __P((struct lfs *, struct segment *)); -void lfs_writesuper __P((struct lfs *, daddr_t)); -int lfs_match_data __P((struct lfs *, struct buf *)); -int lfs_match_indir __P((struct lfs *, struct buf *)); -int lfs_match_dindir __P((struct lfs *, struct buf *)); -int lfs_match_tindir __P((struct lfs *, struct buf *)); -void lfs_callback __P((struct buf *)); -void lfs_supercallback __P((struct buf *)); -void lfs_shellsort __P((struct buf **, ufs_daddr_t *, int)); -int lfs_vref __P((struct vnode *)); -void lfs_vunref __P((struct vnode *)); -void lfs_vunref_head __P((struct vnode *)); +void lfs_imtime(struct lfs *); +int lfs_vflush(struct vnode *); +int lfs_writevnodes(struct lfs *, struct mount *, struct segment *, int); +int lfs_segwrite(struct mount *, int); +void lfs_writefile(struct lfs *, struct segment *, struct vnode *); +int lfs_writeinode(struct lfs *, struct segment *, struct inode *); +int lfs_gatherblock(struct segment *, struct buf *, int *); +int lfs_gather(struct lfs *, struct segment *, struct vnode *, int (*match )(struct lfs *, struct buf *)); +void lfs_updatemeta(struct segment *); +int lfs_initseg(struct lfs *); +void lfs_newseg(struct lfs *); +int lfs_writeseg(struct lfs *, struct segment *); +void lfs_writesuper(struct lfs *, daddr_t); +int lfs_match_data(struct lfs *, struct buf *); +int lfs_match_indir(struct lfs *, struct buf *); +int lfs_match_dindir(struct lfs *, struct buf *); +int lfs_match_tindir(struct lfs *, struct buf *); +void lfs_callback(struct buf *); +void lfs_supercallback(struct buf *); +void lfs_shellsort(struct buf **, ufs_daddr_t *, int); +int lfs_vref(struct vnode *); +void lfs_vunref(struct vnode *); +void lfs_vunref_head(struct vnode *); /* lfs_subr.c */ -void lfs_seglock __P((struct lfs *, unsigned long)); -void lfs_segunlock __P((struct lfs *)); +void lfs_seglock(struct lfs *, unsigned long); +void lfs_segunlock(struct lfs *); /* lfs_syscalls.c */ -int lfs_fastvget __P((struct mount *, ino_t, ufs_daddr_t, struct vnode **, struct dinode *, int *)); -struct buf *lfs_fakebuf __P((struct vnode *, int, size_t, caddr_t)); +int lfs_fastvget(struct mount *, ino_t, ufs_daddr_t, struct vnode **, struct dinode *, int *); +struct buf *lfs_fakebuf(struct vnode *, int, size_t, caddr_t); /* lfs_vfsops.c */ -void lfs_init __P((void)); -void lfs_done __P((void)); -int lfs_mountroot __P((void)); -int lfs_mount __P((struct mount *, const char *, void *, struct nameidata *, struct proc *)); -int lfs_mountfs __P((struct vnode *, struct mount *, struct proc *)); -int lfs_unmount __P((struct mount *, int, struct proc *)); -int lfs_statfs __P((struct mount *, struct statfs *, struct proc *)); -int lfs_sync __P((struct mount *, int, struct ucred *, struct proc *)); -int lfs_vget __P((struct mount *, ino_t, struct vnode **)); -int lfs_fhtovp __P((struct mount *, struct fid *, struct vnode **)); -int lfs_vptofh __P((struct vnode *, struct fid *)); -int lfs_sysctl __P((int *, u_int, void *, size_t *, void *, size_t, - struct proc *)); +void lfs_init(void); +void lfs_done(void); +int lfs_mountroot(void); +int lfs_mount(struct mount *, const char *, void *, struct nameidata *, struct proc *); +int lfs_mountfs(struct vnode *, struct mount *, struct proc *); +int lfs_unmount(struct mount *, int, struct proc *); +int lfs_statfs(struct mount *, struct statfs *, struct proc *); +int lfs_sync(struct mount *, int, struct ucred *, struct proc *); +int lfs_vget(struct mount *, ino_t, struct vnode **); +int lfs_fhtovp(struct mount *, struct fid *, struct vnode **); +int lfs_vptofh(struct vnode *, struct fid *); +int lfs_sysctl(int *, u_int, void *, size_t *, void *, size_t, struct proc *); /* lfs_vnops.c */ -void lfs_unmark_vnode __P((struct vnode *)); -void lfs_itimes __P((struct inode *, struct timespec *, struct timespec *, - struct timespec *)); - -int lfs_balloc __P((void *)); -int lfs_valloc __P((void *)); -int lfs_vfree __P((void *)); -int lfs_bwrite __P((void *)); -int lfs_update __P((void *)); -int lfs_truncate __P((void *)); -int lfs_blkatoff __P((void *)); -int lfs_fsync __P((void *)); -int lfs_symlink __P((void *)); -int lfs_mknod __P((void *)); -int lfs_create __P((void *)); -int lfs_mkdir __P((void *)); -int lfs_read __P((void *)); -int lfs_remove __P((void *)); -int lfs_rmdir __P((void *)); -int lfs_link __P((void *)); -int lfs_rename __P((void *)); -int lfs_getattr __P((void *)); -int lfs_close __P((void *)); -int lfs_inactive __P((void *)); -int lfs_reclaim __P((void *)); -int lfs_write __P((void *)); -int lfs_whiteout __P((void *)); +void lfs_unmark_vnode(struct vnode *); +void lfs_itimes(struct inode *, struct timespec *, struct timespec *, + struct timespec *); + +int lfs_balloc (void *); +int lfs_valloc (void *); +int lfs_vfree (void *); +int lfs_bwrite (void *); +int lfs_update (void *); +int lfs_truncate(void *); +int lfs_blkatoff(void *); +int lfs_fsync (void *); +int lfs_symlink (void *); +int lfs_mknod (void *); +int lfs_create (void *); +int lfs_mkdir (void *); +int lfs_read (void *); +int lfs_remove (void *); +int lfs_rmdir (void *); +int lfs_link (void *); +int lfs_rename (void *); +int lfs_getattr (void *); +int lfs_close (void *); +int lfs_inactive(void *); +int lfs_reclaim (void *); +int lfs_write (void *); +int lfs_whiteout(void *); __END_DECLS extern int lfs_mount_type; -extern int (**lfs_vnodeop_p) __P((void *)); -extern int (**lfs_specop_p) __P((void *)); -extern int (**lfs_fifoop_p) __P((void *)); +extern int (**lfs_vnodeop_p)(void *); +extern int (**lfs_specop_p)(void *); +extern int (**lfs_fifoop_p)(void *); diff --git a/sys/ufs/lfs/lfs_inode.c b/sys/ufs/lfs/lfs_inode.c index d7702e9869e..65e1d0596cf 100644 --- a/sys/ufs/lfs/lfs_inode.c +++ b/sys/ufs/lfs/lfs_inode.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_inode.c,v 1.51 2001/05/30 11:57:18 mrg Exp $ */ +/* $NetBSD: lfs_inode.c,v 1.52 2001/07/13 20:30:24 perseant Exp $ */ /*- * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. @@ -106,30 +106,40 @@ static int lfs_vtruncbuf(struct vnode *, daddr_t, int, int); /* Search a block for a specific dinode. */ struct dinode * -lfs_ifind(fs, ino, bp) - struct lfs *fs; - ino_t ino; - struct buf *bp; +lfs_ifind(struct lfs *fs, ino_t ino, struct buf *bp) { - int cnt; struct dinode *dip = (struct dinode *)bp->b_data; - struct dinode *ldip; + struct dinode *ldip, *fin; - for (cnt = INOPB(fs), ldip = dip + (cnt - 1); cnt--; --ldip) +#ifdef LFS_IFILE_FRAG_ADDRESSING + if (fs->lfs_version == 1) + fin = dip + INOPB(fs); + else + fin = dip + INOPF(fs); +#else + fin = dip + INOPB(fs); +#endif + + /* + * XXX we used to go from the top down here, presumably with the + * idea that the same inode could be written twice in the same + * block (which is not supposed to be true). + */ + for (ldip = dip; ldip < fin; ++ldip) if (ldip->di_inumber == ino) return (ldip); - + + printf("searched %d entries\n", (int)(fin - dip)); 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)); + dtosn(fs, fs->lfs_offset)); + printf("block is 0x%x (seg %d)\n", dbtofsb(fs, bp->b_blkno), + dtosn(fs, dbtofsb(fs, bp->b_blkno))); panic("lfs_ifind: dinode %u not found", ino); /* NOTREACHED */ } int -lfs_update(v) - void *v; +lfs_update(void *v) { struct vop_update_args /* { struct vnode *a_vp; @@ -205,8 +215,7 @@ lfs_update(v) */ /* VOP_BWRITE 1 + NIADDR + VOP_BALLOC == 2 + 2*NIADDR times */ int -lfs_truncate(v) - void *v; +lfs_truncate(void *v) { struct vop_truncate_args /* { struct vnode *a_vp; @@ -279,11 +288,11 @@ lfs_truncate(v) aflags = B_CLRBUF; if (ap->a_flags & IO_SYNC) aflags |= B_SYNC; - error = lfs_reserve(fs, ovp, fsbtodb(fs, NIADDR + 2)); + error = lfs_reserve(fs, ovp, btofsb(fs, (NIADDR + 2) << fs->lfs_bshift)); if (error) return (error); error = VOP_BALLOC(ovp, length - 1, 1, ap->a_cred, aflags, &bp); - lfs_reserve(fs, ovp, -fsbtodb(fs, NIADDR + 2)); + lfs_reserve(fs, ovp, -btofsb(fs, (NIADDR + 2) << fs->lfs_bshift)); if (error) return (error); oip->i_ffs_size = length; @@ -293,7 +302,7 @@ lfs_truncate(v) return (VOP_UPDATE(ovp, NULL, NULL, 0)); } - if ((error = lfs_reserve(fs, ovp, fsbtodb(fs, 2 * NIADDR + 3))) != 0) + if ((error = lfs_reserve(fs, ovp, btofsb(fs, (2 * NIADDR + 3) << fs->lfs_bshift))) != 0) return (error); /* * Make sure no writes to this inode can happen while we're @@ -330,11 +339,11 @@ lfs_truncate(v) aflags |= B_SYNC; error = VOP_BALLOC(ovp, length - 1, 1, ap->a_cred, aflags, &bp); if (error) { - lfs_reserve(fs, ovp, -fsbtodb(fs, 2 * NIADDR + 3)); + lfs_reserve(fs, ovp, -btofsb(fs, (2 * NIADDR + 3) << fs->lfs_bshift)); return (error); } obufsize = bp->b_bufsize; - odb = btodb(bp->b_bcount); + odb = btofsb(fs, bp->b_bcount); oip->i_ffs_size = length; size = blksize(fs, oip, lbn); if (ovp->v_type != VDIR) @@ -344,7 +353,7 @@ lfs_truncate(v) if (bp->b_flags & B_DELWRI) { if ((bp->b_flags & (B_LOCKED | B_CALL)) == B_LOCKED) locked_queue_bytes -= obufsize - bp->b_bufsize; - fs->lfs_avail += odb - btodb(size); + fs->lfs_avail += odb - btofsb(fs, size); } (void) VOP_BWRITE(bp); } @@ -359,7 +368,7 @@ lfs_truncate(v) lastiblock[SINGLE] = lastblock - NDADDR; lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs); lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs); - nblocks = btodb(fs->lfs_bsize); + nblocks = btofsb(fs, fs->lfs_bsize); /* * Record changed file and block pointers before we start * freeing blocks. lastiblock values are also normalized to -1 @@ -419,8 +428,8 @@ lfs_truncate(v) continue; bsize = blksize(fs, oip, i); if (oip->i_ffs_db[i] > 0) - real_released += btodb(bsize); - blocksreleased += btodb(bsize); + real_released += btofsb(fs, bsize); + blocksreleased += btofsb(fs, bsize); oip->i_ffs_db[i] = 0; lfs_blkfree(fs, bn, bsize, &lastseg, &bc); } @@ -447,8 +456,8 @@ lfs_truncate(v) if (oldspace - newspace > 0) { lfs_blkfree(fs, bn, oldspace - newspace, &lastseg, &bc); if (bn > 0) - real_released += btodb(oldspace - newspace); - blocksreleased += btodb(oldspace - newspace); + real_released += btofsb(fs, oldspace - newspace); + blocksreleased += btofsb(fs, oldspace - newspace); } } @@ -484,7 +493,7 @@ done: #ifdef QUOTA (void) chkdq(oip, -blocksreleased, NOCRED, 0); #endif - lfs_reserve(fs, ovp, -fsbtodb(fs, 2 * NIADDR + 3)); + lfs_reserve(fs, ovp, -btofsb(fs, (2 * NIADDR + 3) << fs->lfs_bshift)); return (allerror); } @@ -498,7 +507,7 @@ lfs_blkfree(struct lfs *fs, daddr_t daddr, size_t bsize, long *lastseg, bsize = fragroundup(fs, bsize); if (daddr > 0) { - if (*lastseg != (seg = datosn(fs, daddr))) { + if (*lastseg != (seg = dtosn(fs, daddr))) { error = lfs_update_seguse(fs, *lastseg, *num); *num = bsize; *lastseg = seg; @@ -565,7 +574,7 @@ lfs_indirtrunc(struct inode *ip, ufs_daddr_t lbn, daddr_t dbn, last = lastbn; if (lastbn > 0) last /= factor; - nblocks = btodb(fs->lfs_bsize); + nblocks = btofsb(fs, fs->lfs_bsize); /* * Get buffer of block pointers, zero those entries corresponding * to blocks to be free'd, and update on disk copy first. Since @@ -585,7 +594,7 @@ lfs_indirtrunc(struct inode *ip, ufs_daddr_t lbn, daddr_t dbn, bp->b_flags |= B_READ; if (bp->b_bcount > bp->b_bufsize) panic("lfs_indirtrunc: bad buffer size"); - bp->b_blkno = dbn; + bp->b_blkno = fsbtodb(fs, dbn); VOP_STRATEGY(bp); error = biowait(bp); } @@ -653,7 +662,7 @@ lfs_indirtrunc(struct inode *ip, ufs_daddr_t lbn, daddr_t dbn, } else { if (bp->b_flags & B_DELWRI) { LFS_UNLOCK_BUF(bp); - fs->lfs_avail += btodb(bp->b_bcount); + fs->lfs_avail += btofsb(fs, bp->b_bcount); wakeup(&fs->lfs_avail); } bp->b_flags |= B_INVAL; @@ -670,10 +679,7 @@ lfs_indirtrunc(struct inode *ip, ufs_daddr_t lbn, daddr_t dbn, * Inlined from vtruncbuf, so that lfs_avail could be updated. */ static int -lfs_vtruncbuf(vp, lbn, slpflag, slptimeo) - struct vnode *vp; - daddr_t lbn; - int slpflag, slptimeo; +lfs_vtruncbuf(struct vnode *vp, daddr_t lbn, int slpflag, int slptimeo) { struct buf *bp, *nbp; int s, error; @@ -700,7 +706,7 @@ restart: bp->b_flags |= B_BUSY | B_INVAL | B_VFLUSH; if (bp->b_flags & B_DELWRI) { bp->b_flags &= ~B_DELWRI; - fs->lfs_avail += btodb(bp->b_bcount); + fs->lfs_avail += btofsb(fs, bp->b_bcount); wakeup(&fs->lfs_avail); } LFS_UNLOCK_BUF(bp); @@ -724,7 +730,7 @@ restart: bp->b_flags |= B_BUSY | B_INVAL | B_VFLUSH; if (bp->b_flags & B_DELWRI) { bp->b_flags &= ~B_DELWRI; - fs->lfs_avail += btodb(bp->b_bcount); + fs->lfs_avail += btofsb(fs, bp->b_bcount); wakeup(&fs->lfs_avail); } LFS_UNLOCK_BUF(bp); diff --git a/sys/ufs/lfs/lfs_segment.c b/sys/ufs/lfs/lfs_segment.c index ffd1f6a057b..3f67278822f 100644 --- a/sys/ufs/lfs/lfs_segment.c +++ b/sys/ufs/lfs/lfs_segment.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_segment.c,v 1.68 2001/05/30 11:57:18 mrg Exp $ */ +/* $NetBSD: lfs_segment.c,v 1.69 2001/07/13 20:30:24 perseant Exp $ */ /*- * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. @@ -102,7 +102,7 @@ #include <ufs/lfs/lfs.h> #include <ufs/lfs/lfs_extern.h> -extern int count_lock_queue __P((void)); +extern int count_lock_queue(void); extern struct simplelock vnode_free_list_slock; /* XXX */ /* @@ -110,31 +110,31 @@ extern struct simplelock vnode_free_list_slock; /* XXX */ * to go on to a new segment. */ #define LFS_PARTIAL_FITS(fs) \ - ((fs)->lfs_dbpseg - ((fs)->lfs_offset - (fs)->lfs_curseg) > \ - 1 << (fs)->lfs_fsbtodb) - -void lfs_callback __P((struct buf *)); -int lfs_gather __P((struct lfs *, struct segment *, - struct vnode *, int (*) __P((struct lfs *, struct buf *)))); -int lfs_gatherblock __P((struct segment *, struct buf *, int *)); -void lfs_iset __P((struct inode *, ufs_daddr_t, time_t)); -int lfs_match_fake __P((struct lfs *, struct buf *)); -int lfs_match_data __P((struct lfs *, struct buf *)); -int lfs_match_dindir __P((struct lfs *, struct buf *)); -int lfs_match_indir __P((struct lfs *, struct buf *)); -int lfs_match_tindir __P((struct lfs *, struct buf *)); -void lfs_newseg __P((struct lfs *)); -void lfs_shellsort __P((struct buf **, ufs_daddr_t *, int)); -void lfs_supercallback __P((struct buf *)); -void lfs_updatemeta __P((struct segment *)); -int lfs_vref __P((struct vnode *)); -void lfs_vunref __P((struct vnode *)); -void lfs_writefile __P((struct lfs *, struct segment *, struct vnode *)); -int lfs_writeinode __P((struct lfs *, struct segment *, struct inode *)); -int lfs_writeseg __P((struct lfs *, struct segment *)); -void lfs_writesuper __P((struct lfs *, daddr_t)); -int lfs_writevnodes __P((struct lfs *fs, struct mount *mp, - struct segment *sp, int dirops)); + ((fs)->lfs_fsbpseg - ((fs)->lfs_offset - (fs)->lfs_curseg) > \ + fragstofsb((fs), (fs)->lfs_frag)) + +void lfs_callback(struct buf *); +int lfs_gather(struct lfs *, struct segment *, + struct vnode *, int (*)(struct lfs *, struct buf *)); +int lfs_gatherblock(struct segment *, struct buf *, int *); +void lfs_iset(struct inode *, ufs_daddr_t, time_t); +int lfs_match_fake(struct lfs *, struct buf *); +int lfs_match_data(struct lfs *, struct buf *); +int lfs_match_dindir(struct lfs *, struct buf *); +int lfs_match_indir(struct lfs *, struct buf *); +int lfs_match_tindir(struct lfs *, struct buf *); +void lfs_newseg(struct lfs *); +void lfs_shellsort(struct buf **, ufs_daddr_t *, int); +void lfs_supercallback(struct buf *); +void lfs_updatemeta(struct segment *); +int lfs_vref(struct vnode *); +void lfs_vunref(struct vnode *); +void lfs_writefile(struct lfs *, struct segment *, struct vnode *); +int lfs_writeinode(struct lfs *, struct segment *, struct inode *); +int lfs_writeseg(struct lfs *, struct segment *); +void lfs_writesuper(struct lfs *, daddr_t); +int lfs_writevnodes(struct lfs *fs, struct mount *mp, + struct segment *sp, int dirops); int lfs_allclean_wakeup; /* Cleaner wakeup address. */ int lfs_writeindir = 1; /* whether to flush indir on non-ckp */ @@ -163,8 +163,7 @@ extern long locked_queue_bytes; * case that wouldn't happen to the Ifile until we checkpoint). */ void -lfs_imtime(fs) - struct lfs *fs; +lfs_imtime(struct lfs *fs) { struct timespec ts; struct inode *ip; @@ -187,8 +186,7 @@ lfs_imtime(fs) #define CLR_FLUSHING(fs,vp) (fs)->lfs_flushvp = NULL int -lfs_vflush(vp) - struct vnode *vp; +lfs_vflush(struct vnode *vp) { struct inode *ip; struct lfs *fs; @@ -222,9 +220,11 @@ lfs_vflush(vp) && tbp->b_lblkno == bp->b_lblkno && tbp != bp) { - fs->lfs_avail += btodb(bp->b_bcount); + fs->lfs_avail += btofsb(fs, bp->b_bcount); wakeup(&fs->lfs_avail); lfs_freebuf(bp); + bp = NULL; + break; } } } @@ -252,13 +252,14 @@ lfs_vflush(vp) for(bp=vp->v_dirtyblkhd.lh_first; bp; bp=nbp) { nbp = bp->b_vnbufs.le_next; if (bp->b_flags & B_DELWRI) { /* XXX always true? */ - fs->lfs_avail += btodb(bp->b_bcount); + fs->lfs_avail += btofsb(fs, bp->b_bcount); wakeup(&fs->lfs_avail); } /* Copied from lfs_writeseg */ if (bp->b_flags & B_CALL) { /* if B_CALL, it was created with newbuf */ lfs_freebuf(bp); + bp = NULL; } else { bremfree(bp); LFS_UNLOCK_BUF(bp); @@ -312,7 +313,7 @@ lfs_vflush(vp) /* panic("VDIROP being flushed...this can\'t happen"); */ } if(vp->v_usecount<0) { - printf("usecount=%d\n",vp->v_usecount); + printf("usecount=%ld\n", (long)vp->v_usecount); panic("lfs_vflush: usecount<0"); } #endif @@ -344,11 +345,7 @@ lfs_vflush(vp) #endif int -lfs_writevnodes(fs, mp, sp, op) - struct lfs *fs; - struct mount *mp; - struct segment *sp; - int op; +lfs_writevnodes(struct lfs *fs, struct mount *mp, struct segment *sp, int op) { struct inode *ip; struct vnode *vp; @@ -468,10 +465,11 @@ lfs_writevnodes(fs, mp, sp, op) return inodes_written; } +/* + * Do a checkpoint. + */ int -lfs_segwrite(mp, flags) - struct mount *mp; - int flags; /* Do a checkpoint. */ +lfs_segwrite(struct mount *mp, int flags) { struct buf *bp; struct inode *ip; @@ -543,8 +541,11 @@ lfs_segwrite(mp, flags) if((error = tsleep(&fs->lfs_writer, PRIBIO + 1, "lfs writer", 0))) { + /* XXX why not segunlock? */ free(sp->bpp, M_SEGMENT); + sp->bpp = NULL; free(sp, M_SEGMENT); + fs->lfs_sp = NULL; return (error); } fs->lfs_writer++; @@ -566,19 +567,32 @@ lfs_segwrite(mp, flags) panic("lfs_segwrite: ifile read"); segusep = (SEGUSE *)bp->b_data; - for (i = fs->lfs_sepb; i--; segusep++) { + for (i = fs->lfs_sepb; i--;) { if (segusep->su_flags & SEGUSE_ACTIVE) { segusep->su_flags &= ~SEGUSE_ACTIVE; ++dirty; } + if (fs->lfs_version > 1) + ++segusep; + else + segusep = (SEGUSE *) + ((SEGUSE_V1 *)segusep + 1); } /* But the current segment is still ACTIVE */ segusep = (SEGUSE *)bp->b_data; - if (datosn(fs, fs->lfs_curseg) / fs->lfs_sepb == + if (dtosn(fs, fs->lfs_curseg) / fs->lfs_sepb == (ibno-fs->lfs_cleansz)) { - segusep[datosn(fs, fs->lfs_curseg) % - fs->lfs_sepb].su_flags |= SEGUSE_ACTIVE; + if (fs->lfs_version > 1) + segusep[dtosn(fs, fs->lfs_curseg) % + fs->lfs_sepb].su_flags |= + SEGUSE_ACTIVE; + else + ((SEGUSE *) + ((SEGUSE_V1 *)(bp->b_data) + + (dtosn(fs, fs->lfs_curseg) % + fs->lfs_sepb)))->su_flags + |= SEGUSE_ACTIVE; --dirty; } if (dirty) @@ -648,10 +662,7 @@ lfs_segwrite(mp, flags) * Write the dirty blocks associated with a vnode. */ void -lfs_writefile(fs, sp, vp) - struct lfs *fs; - struct segment *sp; - struct vnode *vp; +lfs_writefile(struct lfs *fs, struct segment *sp, struct vnode *vp) { struct buf *bp; struct finfo *fip; @@ -719,10 +730,7 @@ lfs_writefile(fs, sp, vp) } int -lfs_writeinode(fs, sp, ip) - struct lfs *fs; - struct segment *sp; - struct inode *ip; +lfs_writeinode(struct lfs *fs, struct segment *sp, struct inode *ip) { struct buf *bp, *ibp; struct dinode *cdp; @@ -731,10 +739,10 @@ lfs_writeinode(fs, sp, ip) ufs_daddr_t daddr; daddr_t *daddrp; ino_t ino; - int error, i, ndx; + int error, i, ndx, fsb = 0; int redo_ifile = 0; struct timespec ts; - int gotblk=0; + int gotblk = 0; if (!(ip->i_flag & IN_ALLMOD)) return(0); @@ -742,15 +750,16 @@ lfs_writeinode(fs, sp, ip) /* Allocate a new inode block if necessary. */ if ((ip->i_number != LFS_IFILE_INUM || sp->idp==NULL) && sp->ibp == NULL) { /* Allocate a new segment if necessary. */ - if (sp->seg_bytes_left < fs->lfs_bsize || + if (sp->seg_bytes_left < fs->lfs_ibsize || sp->sum_bytes_left < sizeof(ufs_daddr_t)) (void) lfs_writeseg(fs, sp); /* Get next inode block. */ daddr = fs->lfs_offset; - fs->lfs_offset += fsbtodb(fs, 1); + fs->lfs_offset += btofsb(fs, fs->lfs_ibsize); sp->ibp = *sp->cbpp++ = - getblk(VTOI(fs->lfs_ivnode)->i_devvp, daddr, fs->lfs_bsize, 0, 0); + getblk(VTOI(fs->lfs_ivnode)->i_devvp, fsbtodb(fs, daddr), + fs->lfs_ibsize, 0, 0); gotblk++; /* Zero out inode numbers */ @@ -758,11 +767,11 @@ lfs_writeinode(fs, sp, ip) ((struct dinode *)sp->ibp->b_data)[i].di_inumber = 0; ++sp->start_bpp; - fs->lfs_avail -= fsbtodb(fs, 1); + fs->lfs_avail -= btofsb(fs, fs->lfs_ibsize); /* Set remaining space counters. */ - sp->seg_bytes_left -= fs->lfs_bsize; + sp->seg_bytes_left -= fs->lfs_ibsize; sp->sum_bytes_left -= sizeof(ufs_daddr_t); - ndx = LFS_SUMMARY_SIZE / sizeof(ufs_daddr_t) - + ndx = fs->lfs_sumsize / sizeof(ufs_daddr_t) - sp->ninodes / INOPB(fs) - 1; ((ufs_daddr_t *)(sp->segsum))[ndx] = daddr; } @@ -787,6 +796,10 @@ lfs_writeinode(fs, sp, ip) bp = sp->ibp; cdp = ((struct dinode *)bp->b_data) + (sp->ninodes % INOPB(fs)); *cdp = ip->i_din.ffs_din; +#ifdef LFS_IFILE_FRAG_ADDRESSING + if (fs->lfs_version > 1) + fsb = (sp->ninodes % INOPB(fs)) / INOPF(fs); +#endif /* * If we are cleaning, ensure that we don't write UNWRITTEN disk @@ -846,11 +859,11 @@ lfs_writeinode(fs, sp, ip) ino = ip->i_number; if (ino == LFS_IFILE_INUM) { daddr = fs->lfs_idaddr; - fs->lfs_idaddr = bp->b_blkno; + fs->lfs_idaddr = dbtofsb(fs, bp->b_blkno); } else { LFS_IENTRY(ifp, fs, ino, ibp); daddr = ifp->if_daddr; - ifp->if_daddr = bp->b_blkno; + ifp->if_daddr = dbtofsb(fs, bp->b_blkno) + fsb; #ifdef LFS_DEBUG_NEXTFREE if(ino > 3 && ifp->if_nextfree) { vprint("lfs_writeinode",ITOV(ip)); @@ -875,22 +888,26 @@ lfs_writeinode(fs, sp, ip) * su_nbytes until lfs_writeseg, this shouldn't be a problem as we * have more data blocks in the current partial segment. */ - if (daddr >= fs->lfs_lastpseg && daddr <= bp->b_blkno) + if (daddr >= fs->lfs_lastpseg && daddr <= dbtofsb(fs, bp->b_blkno)) printf("lfs_writeinode: last inode addr in current pseg " "(ino %d daddr 0x%x)\n", ino, daddr); #endif if (daddr != LFS_UNUSED_DADDR) { - LFS_SEGENTRY(sup, fs, datosn(fs, daddr), bp); + LFS_SEGENTRY(sup, fs, dtosn(fs, daddr), bp); #ifdef DIAGNOSTIC if (sup->su_nbytes < DINODE_SIZE) { printf("lfs_writeinode: negative bytes " "(segment %d short by %d)\n", - datosn(fs, daddr), + dtosn(fs, daddr), (int)DINODE_SIZE - sup->su_nbytes); panic("lfs_writeinode: negative bytes"); sup->su_nbytes = DINODE_SIZE; } #endif +#ifdef DEBUG_SU_NBYTES + printf("seg %d -= %d for ino %d inode\n", + dtosn(fs, daddr), DINODE_SIZE, ino); +#endif sup->su_nbytes -= DINODE_SIZE; redo_ifile = (ino == LFS_IFILE_INUM && !(bp->b_flags & B_GATHERED)); @@ -900,10 +917,7 @@ lfs_writeinode(fs, sp, ip) } int -lfs_gatherblock(sp, bp, sptr) - struct segment *sp; - struct buf *bp; - int *sptr; +lfs_gatherblock(struct segment *sp, struct buf *bp, int *sptr) { struct lfs *fs; int version; @@ -956,11 +970,7 @@ lfs_gatherblock(sp, bp, sptr) } int -lfs_gather(fs, sp, vp, match) - struct lfs *fs; - struct segment *sp; - struct vnode *vp; - int (*match) __P((struct lfs *, struct buf *)); +lfs_gather(struct lfs *fs, struct segment *sp, struct vnode *vp, int (*match)(struct lfs *, struct buf *)) { struct buf *bp; int s, count=0; @@ -1006,7 +1016,7 @@ loop: for (bp = vp->v_dirtyblkhd.lh_first; bp && bp->b_vnbufs.le_next != NULL; if (!(bp->b_flags & B_LOCKED)) { printf("lfs_gather: lbn %d blk %d" " not B_LOCKED\n", bp->b_lblkno, - bp->b_blkno); + dbtofsb(fs, bp->b_blkno)); VOP_PRINT(bp->b_vp); panic("lfs_gather: bp not B_LOCKED"); } @@ -1032,8 +1042,7 @@ loop: for (bp = vp->v_dirtyblkhd.lh_first; bp && bp->b_vnbufs.le_next != NULL; * array. */ void -lfs_updatemeta(sp) - struct segment *sp; +lfs_updatemeta(struct segment *sp) { SEGUSE *sup; struct buf *bp; @@ -1079,7 +1088,8 @@ lfs_updatemeta(sp) for (i = nblocks; i--; ++sp->start_bpp) { lbn = *sp->start_lbp++; - (*sp->start_bpp)->b_blkno = off = fs->lfs_offset; + (*sp->start_bpp)->b_blkno = fsbtodb(fs, fs->lfs_offset); + off = fs->lfs_offset; if((*sp->start_bpp)->b_blkno == (*sp->start_bpp)->b_lblkno) { printf("lfs_updatemeta: ino %d blk %d" " has same lbn and daddr\n", @@ -1089,9 +1099,11 @@ lfs_updatemeta(sp) if((*sp->start_bpp)->b_bcount < fs->lfs_bsize && i != 0) panic("lfs_updatemeta: fragment is not last block\n"); #endif - bb = fragstodb(fs, numfrags(fs, (*sp->start_bpp)->b_bcount)); + bb = fragstofsb(fs, numfrags(fs, (*sp->start_bpp)->b_bcount)); fs->lfs_offset += bb; error = ufs_bmaparray(vp, lbn, &daddr, a, &num, NULL); + if (daddr > 0) + daddr = dbtofsb(fs, daddr); if (error) panic("lfs_updatemeta: ufs_bmaparray %d", error); ip = VTOI(vp); @@ -1150,22 +1162,28 @@ lfs_updatemeta(sp) #endif /* Update segment usage information. */ if (daddr > 0) { - LFS_SEGENTRY(sup, fs, datosn(fs, daddr), bp); + LFS_SEGENTRY(sup, fs, dtosn(fs, daddr), bp); #ifdef DIAGNOSTIC if (sup->su_nbytes < (*sp->start_bpp)->b_bcount) { /* XXX -- Change to a panic. */ printf("lfs_updatemeta: negative bytes " "(segment %d short by %ld)\n", - datosn(fs, daddr), + dtosn(fs, daddr), (*sp->start_bpp)->b_bcount - sup->su_nbytes); printf("lfs_updatemeta: ino %d, lbn %d, " - "addr = %x\n", VTOI(sp->vp)->i_number, + "addr = 0x%x\n", VTOI(sp->vp)->i_number, (*sp->start_bpp)->b_lblkno, daddr); panic("lfs_updatemeta: negative bytes"); sup->su_nbytes = (*sp->start_bpp)->b_bcount; } #endif +#ifdef DEBUG_SU_NBYTES + printf("seg %d -= %ld for ino %d lbn %d db 0x%x\n", + dtosn(fs, daddr), (*sp->start_bpp)->b_bcount, + VTOI(sp->vp)->i_number, + (*sp->start_bpp)->b_lblkno, daddr); +#endif sup->su_nbytes -= (*sp->start_bpp)->b_bcount; error = VOP_BWRITE(bp); /* Ifile */ } @@ -1176,8 +1194,7 @@ lfs_updatemeta(sp) * Start a new segment. */ int -lfs_initseg(fs) - struct lfs *fs; +lfs_initseg(struct lfs *fs) { struct segment *sp; SEGUSE *sup; @@ -1186,12 +1203,12 @@ lfs_initseg(fs) int repeat; sp = fs->lfs_sp; - + repeat = 0; /* Advance to the next segment. */ if (!LFS_PARTIAL_FITS(fs)) { /* lfs_avail eats the remaining space */ - fs->lfs_avail -= fs->lfs_dbpseg - (fs->lfs_offset - + fs->lfs_avail -= fs->lfs_fsbpseg - (fs->lfs_offset - fs->lfs_curseg); /* Wake up any cleaning procs waiting on this file system. */ wakeup(&lfs_allclean_wakeup); @@ -1199,21 +1216,27 @@ lfs_initseg(fs) lfs_newseg(fs); repeat = 1; fs->lfs_offset = fs->lfs_curseg; - sp->seg_number = datosn(fs, fs->lfs_curseg); - sp->seg_bytes_left = dbtob(fs->lfs_dbpseg); + sp->seg_number = dtosn(fs, fs->lfs_curseg); + sp->seg_bytes_left = fsbtob(fs, fs->lfs_fsbpseg); /* * If the segment contains a superblock, update the offset * and summary address to skip over it. */ LFS_SEGENTRY(sup, fs, sp->seg_number, bp); if (sup->su_flags & SEGUSE_SUPERBLOCK) { - fs->lfs_offset += btodb(LFS_SBPAD); + fs->lfs_offset += btofsb(fs, LFS_SBPAD); sp->seg_bytes_left -= LFS_SBPAD; } brelse(bp); + /* Segment zero could also contain the labelpad */ + if (fs->lfs_version > 1 && sp->seg_number == 0 && + fs->lfs_start < btofsb(fs, LFS_LABELPAD)) { + fs->lfs_offset += btofsb(fs, LFS_LABELPAD) - fs->lfs_start; + sp->seg_bytes_left -= LFS_LABELPAD - fsbtob(fs, fs->lfs_start); + } } else { - sp->seg_number = datosn(fs, fs->lfs_curseg); - sp->seg_bytes_left = dbtob(fs->lfs_dbpseg - + sp->seg_number = dtosn(fs, fs->lfs_curseg); + sp->seg_bytes_left = fsbtob(fs, fs->lfs_fsbpseg - (fs->lfs_offset - fs->lfs_curseg)); } fs->lfs_lastpseg = fs->lfs_offset; @@ -1222,15 +1245,15 @@ lfs_initseg(fs) sp->ibp = NULL; sp->idp = NULL; sp->ninodes = 0; - + /* Get a new buffer for SEGSUM and enter it into the buffer list. */ sp->cbpp = sp->bpp; - *sp->cbpp = lfs_newbuf(VTOI(fs->lfs_ivnode)->i_devvp, - fs->lfs_offset, LFS_SUMMARY_SIZE); + *sp->cbpp = lfs_newbuf(fs, VTOI(fs->lfs_ivnode)->i_devvp, + fsbtodb(fs, fs->lfs_offset), fs->lfs_sumsize); sp->segsum = (*sp->cbpp)->b_data; - bzero(sp->segsum, LFS_SUMMARY_SIZE); + bzero(sp->segsum, fs->lfs_sumsize); sp->start_bpp = ++sp->cbpp; - fs->lfs_offset += btodb(LFS_SUMMARY_SIZE); + fs->lfs_offset += btofsb(fs, fs->lfs_sumsize); /* Set point to SEGSUM, initialize it. */ ssp = sp->segsum; @@ -1239,13 +1262,13 @@ lfs_initseg(fs) ssp->ss_magic = SS_MAGIC; /* Set pointer to first FINFO, initialize it. */ - sp->fip = (struct finfo *)((caddr_t)sp->segsum + sizeof(SEGSUM)); + sp->fip = (struct finfo *)((caddr_t)sp->segsum + SEGSUM_SIZE(fs)); sp->fip->fi_nblocks = 0; sp->start_lbp = &sp->fip->fi_blocks[0]; sp->fip->fi_lastlength = 0; - sp->seg_bytes_left -= LFS_SUMMARY_SIZE; - sp->sum_bytes_left = LFS_SUMMARY_SIZE - sizeof(SEGSUM); + sp->seg_bytes_left -= fs->lfs_sumsize; + sp->sum_bytes_left = fs->lfs_sumsize - SEGSUM_SIZE(fs); return(repeat); } @@ -1254,15 +1277,18 @@ lfs_initseg(fs) * Return the next segment to write. */ void -lfs_newseg(fs) - struct lfs *fs; +lfs_newseg(struct lfs *fs) { CLEANERINFO *cip; SEGUSE *sup; struct buf *bp; int curseg, isdirty, sn; - LFS_SEGENTRY(sup, fs, datosn(fs, fs->lfs_nextseg), bp); + LFS_SEGENTRY(sup, fs, dtosn(fs, fs->lfs_nextseg), bp); +#ifdef DEBUG_SU_NBYTES + printf("lfs_newseg: seg %d := 0 in newseg\n", /* XXXDEBUG */ + dtosn(fs, fs->lfs_nextseg)); /* XXXDEBUG */ +#endif sup->su_flags |= SEGUSE_DIRTY | SEGUSE_ACTIVE; sup->su_nbytes = 0; sup->su_nsums = 0; @@ -1277,7 +1303,7 @@ lfs_newseg(fs) fs->lfs_lastseg = fs->lfs_curseg; fs->lfs_curseg = fs->lfs_nextseg; - for (sn = curseg = datosn(fs, fs->lfs_curseg);;) { + for (sn = curseg = dtosn(fs, fs->lfs_curseg) + fs->lfs_interleave;;) { sn = (sn + 1) % fs->lfs_nseg; if (sn == curseg) panic("lfs_nextseg: no clean segments"); @@ -1289,32 +1315,30 @@ lfs_newseg(fs) } ++fs->lfs_nactive; - fs->lfs_nextseg = sntoda(fs, sn); + fs->lfs_nextseg = sntod(fs, sn); if(lfs_dostats) { ++lfs_stats.segsused; } } int -lfs_writeseg(fs, sp) - struct lfs *fs; - struct segment *sp; +lfs_writeseg(struct lfs *fs, struct segment *sp) { struct buf **bpp, *bp, *cbp, *newbp; SEGUSE *sup; SEGSUM *ssp; dev_t i_dev; - u_long *datap, *dp; - int do_again, i, nblocks, s; + char *datap, *dp; + int do_again, i, nblocks, s, el_size; #ifdef LFS_TRACK_IOS int j; #endif - int (*strategy)__P((void *)); + int (*strategy)(void *); struct vop_strategy_args vop_strategy_a; u_short ninos; struct vnode *devvp; char *p; - struct vnode *vn; + struct vnode *vp; struct inode *ip; daddr_t *daddrp; int changed; @@ -1343,20 +1367,36 @@ lfs_writeseg(fs, sp) /* Loop through all blocks, except the segment summary. */ for (bpp = sp->bpp; ++bpp < sp->cbpp; ) { - if((*bpp)->b_vp != devvp) + if((*bpp)->b_vp != devvp) { sup->su_nbytes += (*bpp)->b_bcount; +#ifdef DEBUG_SU_NBYTES + printf("seg %d += %ld for ino %d lbn %d db 0x%x\n", + sp->seg_number, (*bpp)->b_bcount, + VTOI((*bpp)->b_vp)->i_number, + (*bpp)->b_lblkno, (*bpp)->b_blkno); +#endif + } } ssp = (SEGSUM *)sp->segsum; ninos = (ssp->ss_ninos + INOPB(fs) - 1) / INOPB(fs); +#ifdef DEBUG_SU_NBYTES + printf("seg %d += %d for %d inodes\n", /* XXXDEBUG */ + sp->seg_number, ssp->ss_ninos * DINODE_SIZE, + ssp->ss_ninos); +#endif sup->su_nbytes += ssp->ss_ninos * DINODE_SIZE; - /* sup->su_nbytes += LFS_SUMMARY_SIZE; */ - sup->su_lastmod = time.tv_sec; + /* sup->su_nbytes += fs->lfs_sumsize; */ + if (fs->lfs_version == 1) + sup->su_olastmod = time.tv_sec; + else + sup->su_lastmod = time.tv_sec; sup->su_ninos += ninos; ++sup->su_nsums; - fs->lfs_dmeta += (btodb(LFS_SUMMARY_SIZE) + fsbtodb(fs, ninos)); - fs->lfs_avail -= btodb(LFS_SUMMARY_SIZE); + fs->lfs_dmeta += (btofsb(fs, fs->lfs_sumsize) + btofsb(fs, ninos * + fs->lfs_ibsize)); + fs->lfs_avail -= btofsb(fs, fs->lfs_sumsize); do_again = !(bp->b_flags & B_GATHERED); (void)VOP_BWRITE(bp); /* Ifile */ @@ -1399,7 +1439,7 @@ lfs_writeseg(fs, sp) VTOI(bp->b_vp)->i_ffs_blocks); #endif /* Make a copy we'll make changes to */ - newbp = lfs_newbuf(bp->b_vp, bp->b_lblkno, + newbp = lfs_newbuf(fs, bp->b_vp, bp->b_lblkno, bp->b_bcount); newbp->b_blkno = bp->b_blkno; memcpy(newbp->b_data, bp->b_data, @@ -1424,9 +1464,10 @@ lfs_writeseg(fs, sp) */ if (changed) { bp->b_flags &= ~(B_ERROR | B_GATHERED); - if (bp->b_flags & B_CALL) + if (bp->b_flags & B_CALL) { lfs_freebuf(bp); - else { + bp = NULL; + } else { /* Still on free list, leave it there */ s = splbio(); bp->b_flags &= ~B_BUSY; @@ -1439,22 +1480,23 @@ lfs_writeseg(fs, sp) * back around to us in the next * segment. */ - fs->lfs_avail -= btodb(bp->b_bcount); + fs->lfs_avail -= btofsb(fs, bp->b_bcount); } } else { bp->b_flags &= ~(B_ERROR | B_READ | B_DELWRI | B_GATHERED); LFS_UNLOCK_BUF(bp); - if (bp->b_flags & B_CALL) + if (bp->b_flags & B_CALL) { lfs_freebuf(bp); - else { + bp = NULL; + } else { bremfree(bp); bp->b_flags |= B_DONE; reassignbuf(bp, bp->b_vp); brelse(bp); } } - + } } /* @@ -1465,24 +1507,40 @@ lfs_writeseg(fs, sp) * XXX * Fix this to do it inline, instead of malloc/copy. */ - datap = dp = malloc(nblocks * sizeof(u_long), M_SEGMENT, M_WAITOK); + if (fs->lfs_version == 1) + el_size = sizeof(u_long); + else + el_size = sizeof(u_int32_t); + datap = dp = malloc(nblocks * el_size, M_SEGMENT, M_WAITOK); 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))) + if (copyin((*bpp)->b_saveaddr, dp, el_size)) 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]; + memcpy(dp, (*bpp)->b_data, el_size); + dp += el_size; + } + if (fs->lfs_version == 1) + ssp->ss_ocreate = time.tv_sec; + else { + ssp->ss_create = time.tv_sec; + ssp->ss_serial = ++fs->lfs_serial; + ssp->ss_ident = fs->lfs_ident; } - ssp->ss_create = time.tv_sec; - ssp->ss_datasum = cksum(datap, (nblocks - 1) * sizeof(u_long)); + ssp->ss_datasum = cksum(datap, (nblocks - 1) * el_size); ssp->ss_sumsum = - cksum(&ssp->ss_datasum, LFS_SUMMARY_SIZE - sizeof(ssp->ss_sumsum)); + cksum(&ssp->ss_datasum, fs->lfs_sumsize - sizeof(ssp->ss_sumsum)); free(datap, M_SEGMENT); - - fs->lfs_bfree -= (fsbtodb(fs, ninos) + btodb(LFS_SUMMARY_SIZE)); + datap = dp = NULL; +#ifdef DIAGNOSTIC + if (fs->lfs_bfree < btofsb(fs, ninos * fs->lfs_ibsize) + btofsb(fs, fs->lfs_sumsize)) + panic("lfs_writeseg: No diskspace for summary"); +#endif + fs->lfs_bfree -= (btofsb(fs, ninos * fs->lfs_ibsize) + + btofsb(fs, fs->lfs_sumsize)); strategy = devvp->v_op[VOFFSET(vop_strategy)]; @@ -1507,14 +1565,14 @@ lfs_writeseg(fs, sp) if(devvp==NULL) panic("devvp is NULL"); for (bpp = sp->bpp,i = nblocks; i;) { - cbp = lfs_newbuf(devvp, (*bpp)->b_blkno, CHUNKSIZE); + cbp = lfs_newbuf(fs, devvp, (*bpp)->b_blkno, CHUNKSIZE); cbp->b_dev = i_dev; cbp->b_flags |= B_ASYNC | B_BUSY; cbp->b_bcount = 0; #ifdef DIAGNOSTIC - if(datosn(fs, (*bpp)->b_blkno + btodb((*bpp)->b_bcount) - 1) != - datosn(fs, cbp->b_blkno)) { + if(dtosn(fs, dbtofsb(fs, (*bpp)->b_blkno) + btofsb(fs, (*bpp)->b_bcount) - 1) != + dtosn(fs, dbtofsb(fs, cbp->b_blkno))) { panic("lfs_writeseg: Segment overwrite"); } #endif @@ -1527,7 +1585,7 @@ lfs_writeseg(fs, sp) #ifdef LFS_TRACK_IOS for(j=0;j<LFS_THROTTLE;j++) { if(fs->lfs_pending[j]==LFS_UNUSED_DADDR) { - fs->lfs_pending[j] = cbp->b_blkno; + fs->lfs_pending[j] = dbtofsb(fs, cbp->b_blkno); break; } } @@ -1554,15 +1612,16 @@ lfs_writeseg(fs, sp) LFS_UNLOCK_BUF(bp); bp->b_flags &= ~(B_ERROR | B_READ | B_DELWRI | B_GATHERED); - vn = bp->b_vp; + vp = bp->b_vp; if (bp->b_flags & B_CALL) { /* if B_CALL, it was created with newbuf */ lfs_freebuf(bp); + bp = NULL; } else { bremfree(bp); bp->b_flags |= B_DONE; - if(vn) - reassignbuf(bp, vn); + if(vp) + reassignbuf(bp, vp); brelse(bp); } @@ -1575,22 +1634,25 @@ lfs_writeseg(fs, sp) * sort of block. Only do this for our mount point, * not for, e.g., inode blocks that are attached to * the devvp. + * XXX KS - Shouldn't we set *both* if both types + * of blocks are present (traverse the dirty list?) */ - if(i>1 && vn && *bpp && (*bpp)->b_vp != vn - && (*bpp)->b_vp && (bp=vn->v_dirtyblkhd.lh_first)!=NULL && - vn->v_mount == fs->lfs_ivnode->v_mount) + if((i == 1 || + (i > 1 && vp && *bpp && (*bpp)->b_vp != vp)) && + (bp = vp->v_dirtyblkhd.lh_first) != NULL && + vp->v_mount == fs->lfs_ivnode->v_mount) { - ip = VTOI(vn); + ip = VTOI(vp); #ifdef DEBUG_LFS - printf("lfs_writeseg: marking ino %d\n",ip->i_number); + printf("lfs_writeseg: marking ino %d\n", + ip->i_number); #endif if(bp->b_flags & B_CALL) LFS_SET_UINO(ip, IN_CLEANING); else LFS_SET_UINO(ip, IN_MODIFIED); } - /* if(vn->v_dirtyblkhd.lh_first == NULL) */ - wakeup(vn); + wakeup(vp); } ++cbp->b_vp->v_numoutput; splx(s); @@ -1632,17 +1694,14 @@ lfs_writeseg(fs, sp) } void -lfs_writesuper(fs, daddr) - struct lfs *fs; - daddr_t daddr; +lfs_writesuper(struct lfs *fs, daddr_t daddr) { struct buf *bp; dev_t i_dev; - int (*strategy) __P((void *)); + int (*strategy)(void *); int s; struct vop_strategy_args vop_strategy_a; -#ifdef LFS_CANNOT_ROLLFW /* * If we can write one superblock while another is in * progress, we risk not having a complete checkpoint if we crash. @@ -1654,16 +1713,17 @@ lfs_writesuper(fs, daddr) } fs->lfs_sbactive = daddr; splx(s); -#endif i_dev = VTOI(fs->lfs_ivnode)->i_dev; strategy = VTOI(fs->lfs_ivnode)->i_devvp->v_op[VOFFSET(vop_strategy)]; /* Set timestamp of this version of the superblock */ + if (fs->lfs_version == 1) + fs->lfs_otstamp = time.tv_sec; fs->lfs_tstamp = time.tv_sec; /* Checksum the superblock and copy it into a buffer. */ fs->lfs_cksum = lfs_sb_cksum(&(fs->lfs_dlfs)); - bp = lfs_newbuf(VTOI(fs->lfs_ivnode)->i_devvp, daddr, LFS_SBPAD); + bp = lfs_newbuf(fs, VTOI(fs->lfs_ivnode)->i_devvp, fsbtodb(fs, daddr), LFS_SBPAD); *(struct dlfs *)bp->b_data = fs->lfs_dlfs; bp->b_dev = i_dev; @@ -1687,25 +1747,19 @@ lfs_writesuper(fs, daddr) * chain. */ int -lfs_match_fake(fs, bp) - struct lfs *fs; - struct buf *bp; +lfs_match_fake(struct lfs *fs, struct buf *bp) { return (bp->b_flags & B_CALL); } int -lfs_match_data(fs, bp) - struct lfs *fs; - struct buf *bp; +lfs_match_data(struct lfs *fs, struct buf *bp) { return (bp->b_lblkno >= 0); } int -lfs_match_indir(fs, bp) - struct lfs *fs; - struct buf *bp; +lfs_match_indir(struct lfs *fs, struct buf *bp) { int lbn; @@ -1714,9 +1768,7 @@ lfs_match_indir(fs, bp) } int -lfs_match_dindir(fs, bp) - struct lfs *fs; - struct buf *bp; +lfs_match_dindir(struct lfs *fs, struct buf *bp) { int lbn; @@ -1725,9 +1777,7 @@ lfs_match_dindir(fs, bp) } int -lfs_match_tindir(fs, bp) - struct lfs *fs; - struct buf *bp; +lfs_match_tindir(struct lfs *fs, struct buf *bp) { int lbn; @@ -1743,8 +1793,7 @@ lfs_match_tindir(fs, bp) * released via brelse. */ void -lfs_callback(bp) - struct buf *bp; +lfs_callback(struct buf *bp) { struct lfs *fs; #ifdef LFS_TRACK_IOS @@ -1760,7 +1809,7 @@ lfs_callback(bp) wakeup(&fs->lfs_iocount); #ifdef LFS_TRACK_IOS for(j=0;j<LFS_THROTTLE;j++) { - if(fs->lfs_pending[j]==bp->b_blkno) { + if(fs->lfs_pending[j]==dbtofsb(fs, bp->b_blkno)) { fs->lfs_pending[j] = LFS_UNUSED_DADDR; wakeup(&(fs->lfs_pending[j])); break; @@ -1772,16 +1821,13 @@ lfs_callback(bp) } void -lfs_supercallback(bp) - struct buf *bp; +lfs_supercallback(struct buf *bp) { struct lfs *fs; fs = (struct lfs *)bp->b_saveaddr; -#ifdef LFS_CANNOT_ROLLFW fs->lfs_sbactive = 0; wakeup(&fs->lfs_sbactive); -#endif if (--fs->lfs_iocount < LFS_THROTTLE) wakeup(&fs->lfs_iocount); lfs_freebuf(bp); @@ -1802,10 +1848,7 @@ lfs_supercallback(bp) */ void -lfs_shellsort(bp_array, lb_array, nmemb) - struct buf **bp_array; - ufs_daddr_t *lb_array; - int nmemb; +lfs_shellsort(struct buf **bp_array, ufs_daddr_t *lb_array, int nmemb) { static int __rsshell_increments[] = { 4, 1, 0 }; int incr, *incrp, t1, t2; @@ -1831,8 +1874,7 @@ lfs_shellsort(bp_array, lb_array, nmemb) * Check VXLOCK. Return 1 if the vnode is locked. Otherwise, vget it. */ int -lfs_vref(vp) - struct vnode *vp; +lfs_vref(struct vnode *vp) { /* * If we return 1 here during a flush, we risk vinvalbuf() not @@ -1853,8 +1895,7 @@ lfs_vref(vp) * inline vrele here to avoid the vn_lock and VOP_INACTIVE call at the end. */ void -lfs_vunref(vp) - struct vnode *vp; +lfs_vunref(struct vnode *vp) { /* * Analogous to lfs_vref, if the node is flushing, fake it. @@ -1867,8 +1908,8 @@ lfs_vunref(vp) #ifdef DIAGNOSTIC if(vp->v_usecount<=0) { printf("lfs_vunref: inum is %d\n", VTOI(vp)->i_number); - printf("lfs_vunref: flags are 0x%x\n", vp->v_flag); - printf("lfs_vunref: usecount = %d\n", vp->v_usecount); + printf("lfs_vunref: flags are 0x%lx\n", (u_long)vp->v_flag); + printf("lfs_vunref: usecount = %ld\n", (long)vp->v_usecount); panic("lfs_vunref: v_usecount<0"); } #endif @@ -1898,8 +1939,7 @@ lfs_vunref(vp) * cleaning at the head of the list, instead. */ void -lfs_vunref_head(vp) - struct vnode *vp; +lfs_vunref_head(struct vnode *vp) { simple_lock(&vp->v_interlock); #ifdef DIAGNOSTIC diff --git a/sys/ufs/lfs/lfs_subr.c b/sys/ufs/lfs/lfs_subr.c index 505ccaf6269..f7d83144776 100644 --- a/sys/ufs/lfs/lfs_subr.c +++ b/sys/ufs/lfs/lfs_subr.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_subr.c,v 1.17 2000/09/09 04:49:55 perseant Exp $ */ +/* $NetBSD: lfs_subr.c,v 1.18 2001/07/13 20:30:24 perseant Exp $ */ /*- * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. @@ -90,8 +90,7 @@ * remaining space in the directory. */ int -lfs_blkatoff(v) - void *v; +lfs_blkatoff(void *v) { struct vop_blkatoff_args /* { struct vnode *a_vp; @@ -127,9 +126,7 @@ lfs_blkatoff(v) * Single thread the segment writer. */ void -lfs_seglock(fs, flags) - struct lfs *fs; - unsigned long flags; +lfs_seglock(struct lfs *fs, unsigned long flags) { struct segment *sp; int s; @@ -148,7 +145,7 @@ lfs_seglock(fs, flags) fs->lfs_lockpid = curproc->p_pid; sp = fs->lfs_sp = malloc(sizeof(struct segment), M_SEGMENT, M_WAITOK); - sp->bpp = malloc(((LFS_SUMMARY_SIZE - sizeof(SEGSUM)) / + sp->bpp = malloc(((fs->lfs_sumsize - SEGSUM_SIZE(fs)) / sizeof(ufs_daddr_t) + 1) * sizeof(struct buf *), M_SEGMENT, M_WAITOK); sp->seg_flags = flags; @@ -171,8 +168,7 @@ lfs_seglock(fs, flags) * Single thread the segment writer. */ void -lfs_segunlock(fs) - struct lfs *fs; +lfs_segunlock(struct lfs *fs) { struct segment *sp; unsigned long sync, ckp; @@ -240,13 +236,15 @@ lfs_segunlock(fs) ckp = sp->seg_flags & SEGM_CKP; if (sp->bpp != sp->cbpp) { /* Free allocated segment summary */ - fs->lfs_offset -= btodb(LFS_SUMMARY_SIZE); + fs->lfs_offset -= btofsb(fs, fs->lfs_sumsize); lfs_freebuf(*sp->bpp); } else printf ("unlock to 0 with no summary"); free(sp->bpp, M_SEGMENT); + sp->bpp = NULL; free(sp, M_SEGMENT); + fs->lfs_sp = NULL; /* * If the I/O count is non-zero, sleep until it reaches zero. diff --git a/sys/ufs/lfs/lfs_syscalls.c b/sys/ufs/lfs/lfs_syscalls.c index 4fd33a803ee..b650e8956e2 100644 --- a/sys/ufs/lfs/lfs_syscalls.c +++ b/sys/ufs/lfs/lfs_syscalls.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_syscalls.c,v 1.56 2000/12/03 07:34:49 perseant Exp $ */ +/* $NetBSD: lfs_syscalls.c,v 1.57 2001/07/13 20:30:24 perseant Exp $ */ /*- * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. @@ -95,8 +95,8 @@ #define FVG_UNLOCK 0x01 /* Needs to be unlocked */ #define FVG_PUT 0x02 /* Needs to be vput() */ -struct buf *lfs_fakebuf __P((struct vnode *, int, size_t, caddr_t)); -int lfs_fasthashget __P((dev_t, ino_t, int *, struct vnode **)); +struct buf *lfs_fakebuf(struct vnode *, int, size_t, caddr_t); +int lfs_fasthashget(dev_t, ino_t, int *, struct vnode **); int debug_cleaner = 0; int clean_vnlocked = 0; @@ -121,6 +121,9 @@ extern TAILQ_HEAD(bqueues, buf) bufqueues[BQUEUES]; #define LFS_VREF_THRESHOLD 128 +static int lfs_bmapv(struct proc *, fsid_t *, BLOCK_INFO *, int); +static int lfs_markv(struct proc *, fsid_t *, BLOCK_INFO *, int); + /* * sys_lfs_markv: * @@ -134,17 +137,98 @@ extern TAILQ_HEAD(bqueues, buf) bufqueues[BQUEUES]; * 0 on success * -1/errno is return on error. */ +#ifdef USE_64BIT_SYSCALLS +int +sys_lfs_markv(struct proc *p, void *v, register_t *retval) +{ + struct sys_lfs_markv_args /* { + syscallarg(fsid_t *) fsidp; + syscallarg(struct block_info *) blkiov; + syscallarg(int) blkcnt; + } */ *uap = v; + BLOCK_INFO *blkiov; + int blkcnt, error; + fsid_t fsid; + + if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) + return (error); + + if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0) + return (error); + + blkcnt = SCARG(uap, blkcnt); + blkiov = malloc(blkcnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK); + if ((error = copyin(SCARG(uap, blkiov), blkiov, + blkcnt * sizeof(BLOCK_INFO))) != 0) + goto out; + + if ((error = lfs_markv(p, &fsid, blkiov, blkcnt)) == 0) + copyout(blkiov, SCARG(uap, blkiov), + blkcnt * sizeof(BLOCK_INFO)); + out: + free(blkiov, M_SEGMENT); + return error; +} +#else int -sys_lfs_markv(p, v, retval) - struct proc *p; - void *v; - register_t *retval; +sys_lfs_markv(struct proc *p, void *v, register_t *retval) { struct sys_lfs_markv_args /* { syscallarg(fsid_t *) fsidp; syscallarg(struct block_info *) blkiov; syscallarg(int) blkcnt; } */ *uap = v; + BLOCK_INFO *blkiov; + BLOCK_INFO_15 *blkiov15; + int i, blkcnt, error; + fsid_t fsid; + + if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) + return (error); + + if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0) + return (error); + + blkcnt = SCARG(uap, blkcnt); + blkiov = malloc(blkcnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK); + blkiov15 = malloc(blkcnt * sizeof(BLOCK_INFO_15), M_SEGMENT, M_WAITOK); + if ((error = copyin(SCARG(uap, blkiov), blkiov15, + blkcnt * sizeof(BLOCK_INFO_15))) != 0) + goto out; + + for (i = 0; i < blkcnt; i++) { + blkiov[i].bi_inode = blkiov15[i].bi_inode; + blkiov[i].bi_lbn = blkiov15[i].bi_lbn; + blkiov[i].bi_daddr = blkiov15[i].bi_daddr; + blkiov[i].bi_segcreate = blkiov15[i].bi_segcreate; + blkiov[i].bi_version = blkiov15[i].bi_version; + blkiov[i].bi_bp = blkiov15[i].bi_bp; + blkiov[i].bi_size = blkiov15[i].bi_size; + } + + if ((error = lfs_markv(p, &fsid, blkiov, blkcnt)) == 0) { + for (i = 0; i < blkcnt; i++) { + blkiov15[i].bi_inode = blkiov[i].bi_inode; + blkiov15[i].bi_lbn = blkiov[i].bi_lbn; + blkiov15[i].bi_daddr = blkiov[i].bi_daddr; + blkiov15[i].bi_segcreate = blkiov[i].bi_segcreate; + blkiov15[i].bi_version = blkiov[i].bi_version; + blkiov15[i].bi_bp = blkiov[i].bi_bp; + blkiov15[i].bi_size = blkiov[i].bi_size; + } + copyout(blkiov15, SCARG(uap, blkiov), + blkcnt * sizeof(BLOCK_INFO_15)); + } + out: + free(blkiov, M_SEGMENT); + free(blkiov15, M_SEGMENT); + return error; +} +#endif + +static int +lfs_markv(struct proc *p, fsid_t *fsidp, BLOCK_INFO *blkiov, int blkcnt) +{ BLOCK_INFO *blkp; IFILE *ifp; struct buf *bp, *nbp; @@ -155,11 +239,9 @@ sys_lfs_markv(p, v, retval) #ifdef DEBUG_LFS int vputc=0, iwritten=0; #endif - fsid_t fsid; - void *start; ino_t lastino; ufs_daddr_t b_daddr, v_daddr; - int origcnt, cnt, error, lfs_fastvget_unlock; + int cnt, error, lfs_fastvget_unlock; int do_again=0; int s; #ifdef CHECK_COPYIN @@ -171,26 +253,14 @@ sys_lfs_markv(p, v, retval) int numlocked=0, numrefed=0; ino_t maxino; - if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0) - return (error); - - if ((mntp = vfs_getvfs(&fsid)) == NULL) + if ((mntp = vfs_getvfs(fsidp)) == NULL) return (ENOENT); fs = VFSTOUFS(mntp)->um_lfs; - - if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) - return (error); - - - maxino = (dbtofsb(fs, VTOI(fs->lfs_ivnode)->i_ffs_blocks) - + maxino = (fragstoblks(fs, fsbtofrags(fs, VTOI(fs->lfs_ivnode)->i_ffs_blocks)) - fs->lfs_cleansz - fs->lfs_segtabsz) * fs->lfs_ifpb; - origcnt = cnt = SCARG(uap, blkcnt); - start = malloc(cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK); - error = copyin(SCARG(uap, blkiov), start, cnt * sizeof(BLOCK_INFO)); - if (error) - goto err1; + cnt = blkcnt; if ((error = vfs_busy(mntp, LK_NOWAIT, NULL)) != 0) return (error); @@ -212,20 +282,20 @@ sys_lfs_markv(p, v, retval) #ifdef DEBUG_LFS /* Run through and count the inodes */ lastino = LFS_UNUSED_INUM; - for(blkp = start; cnt--; ++blkp) { + for(blkp = blkiov; cnt--; ++blkp) { if(lastino != blkp->bi_inode) { lastino = blkp->bi_inode; vputc++; } } - cnt = origcnt; + cnt = blkcnt; printf("[%d/",vputc); iwritten=0; #endif /* DEBUG_LFS */ /* these were inside the initialization for the for loop */ v_daddr = LFS_UNUSED_DADDR; lastino = LFS_UNUSED_INUM; - for (blkp = start; cnt--; ++blkp) + for (blkp = blkiov; cnt--; ++blkp) { if(blkp->bi_daddr == LFS_FORCE_WRITE) printf("lfs_markv: warning: force-writing ino %d lbn %d\n", @@ -238,12 +308,11 @@ sys_lfs_markv(p, v, retval) */ for(j=0;j<LFS_THROTTLE;j++) { if(fs->lfs_pending[j] != LFS_UNUSED_DADDR - && datosn(fs,fs->lfs_pending[j])==datosn(fs,blkp->bi_daddr) + && dtosn(fs,fs->lfs_pending[j])==dtosn(fs,blkp->bi_daddr) && blkp->bi_daddr != LFS_FORCE_WRITE) { printf("lfs_markv: attempt to clean pending segment? (#%d)\n", - datosn(fs, fs->lfs_pending[j])); - /* free(start,M_SEGMENT); */ + dtosn(fs, fs->lfs_pending[j])); /* return (EBUSY); */ } } @@ -316,7 +385,7 @@ sys_lfs_markv(p, v, retval) #ifdef DEBUG_LFS printf("lfs_markv: lfs_fastvget failed with %d (ino %d, segment %d)\n", error, blkp->bi_inode, - datosn(fs, blkp->bi_daddr)); + dtosn(fs, blkp->bi_daddr)); #endif /* DEBUG_LFS */ /* * If we got EAGAIN, that means that the @@ -376,13 +445,13 @@ sys_lfs_markv(p, v, retval) b_daddr = 0; if(blkp->bi_daddr != LFS_FORCE_WRITE) { if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &b_daddr, NULL) || - b_daddr != blkp->bi_daddr) + dbtofsb(fs, b_daddr) != blkp->bi_daddr) { - if(datosn(fs,b_daddr) - == datosn(fs,blkp->bi_daddr)) + if(dtosn(fs,dbtofsb(fs, b_daddr)) + == dtosn(fs,blkp->bi_daddr)) { printf("lfs_markv: wrong da same seg: %x vs %x\n", - blkp->bi_daddr, b_daddr); + blkp->bi_daddr, dbtofsb(fs, b_daddr)); } continue; } @@ -416,7 +485,7 @@ sys_lfs_markv(p, v, retval) bp = lfs_fakebuf(vp, blkp->bi_lbn, blkp->bi_size, blkp->bi_bp); /* Pretend we used bread() to get it */ - bp->b_blkno = blkp->bi_daddr; + bp->b_blkno = fsbtodb(fs, blkp->bi_daddr); } else { /* Indirect block */ bp = getblk(vp, blkp->bi_lbn, blkp->bi_size, 0, 0); @@ -465,7 +534,6 @@ sys_lfs_markv(p, v, retval) * we'd be unhappy at recovery time. */ lfs_segwrite(mntp, SEGM_SYNC|SEGM_CLEAN|SEGM_CKP); - free(start, M_SEGMENT); lfs_segunlock(fs); @@ -506,7 +574,7 @@ sys_lfs_markv(p, v, retval) goto again; } if(bp->b_flags & B_DELWRI) - fs->lfs_avail += btodb(bp->b_bcount); + fs->lfs_avail += btofsb(fs, bp->b_bcount); bremfree(bp); splx(s); brelse(bp); @@ -514,7 +582,6 @@ sys_lfs_markv(p, v, retval) } } splx(s); - free(start, M_SEGMENT); lfs_segunlock(fs); vfs_unbusy(mntp); #ifdef DEBUG_LFS @@ -524,11 +591,6 @@ sys_lfs_markv(p, v, retval) #endif return (error); - - err1: - printf("lfs_markv err1\n"); - free(start, M_SEGMENT); - return (error); } /* @@ -539,18 +601,98 @@ sys_lfs_markv(p, v, retval) * 0 on success * -1/errno is return on error. */ +#ifdef USE_64BIT_SYSCALLS +int +sys_lfs_bmapv(struct proc *p, void *v, register_t *retval) +{ + struct sys_lfs_bmapv_args /* { + syscallarg(fsid_t *) fsidp; + syscallarg(struct block_info *) blkiov; + syscallarg(int) blkcnt; + } */ *uap = v; + BLOCK_INFO *blkiov; + int blkcnt, error; + fsid_t fsid; + + if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) + return (error); + + if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0) + return (error); + + blkcnt = SCARG(uap, blkcnt); + blkiov = malloc(blkcnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK); + if ((error = copyin(SCARG(uap, blkiov), blkiov, + blkcnt * sizeof(BLOCK_INFO))) != 0) + goto out; + if ((error = lfs_bmapv(p, &fsid, blkiov, blkcnt)) == 0) + copyout(blkiov, SCARG(uap, blkiov), + blkcnt * sizeof(BLOCK_INFO)); + out: + free(blkiov, M_SEGMENT); + return error; +} +#else int -sys_lfs_bmapv(p, v, retval) - struct proc *p; - void *v; - register_t *retval; +sys_lfs_bmapv(struct proc *p, void *v, register_t *retval) { struct sys_lfs_bmapv_args /* { syscallarg(fsid_t *) fsidp; syscallarg(struct block_info *) blkiov; syscallarg(int) blkcnt; } */ *uap = v; + BLOCK_INFO *blkiov; + BLOCK_INFO_15 *blkiov15; + int i, blkcnt, error; + fsid_t fsid; + + if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) + return (error); + + if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0) + return (error); + + blkcnt = SCARG(uap, blkcnt); + blkiov = malloc(blkcnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK); + blkiov15 = malloc(blkcnt * sizeof(BLOCK_INFO_15), M_SEGMENT, M_WAITOK); + if ((error = copyin(SCARG(uap, blkiov), blkiov15, + blkcnt * sizeof(BLOCK_INFO_15))) != 0) + goto out; + + for (i = 0; i < blkcnt; i++) { + blkiov[i].bi_inode = blkiov15[i].bi_inode; + blkiov[i].bi_lbn = blkiov15[i].bi_lbn; + blkiov[i].bi_daddr = blkiov15[i].bi_daddr; + blkiov[i].bi_segcreate = blkiov15[i].bi_segcreate; + blkiov[i].bi_version = blkiov15[i].bi_version; + blkiov[i].bi_bp = blkiov15[i].bi_bp; + blkiov[i].bi_size = blkiov15[i].bi_size; + } + + if ((error = lfs_bmapv(p, &fsid, blkiov, blkcnt)) == 0) { + for (i = 0; i < blkcnt; i++) { + blkiov15[i].bi_inode = blkiov[i].bi_inode; + blkiov15[i].bi_lbn = blkiov[i].bi_lbn; + blkiov15[i].bi_daddr = blkiov[i].bi_daddr; + blkiov15[i].bi_segcreate = blkiov[i].bi_segcreate; + blkiov15[i].bi_version = blkiov[i].bi_version; + blkiov15[i].bi_bp = blkiov[i].bi_bp; + blkiov15[i].bi_size = blkiov[i].bi_size; + } + copyout(blkiov15, SCARG(uap, blkiov), + blkcnt * sizeof(BLOCK_INFO_15)); + } + out: + free(blkiov, M_SEGMENT); + free(blkiov15, M_SEGMENT); + return error; +} +#endif + +static int +lfs_bmapv(struct proc *p, fsid_t *fsidp, BLOCK_INFO *blkiov, int blkcnt) +{ BLOCK_INFO *blkp; IFILE *ifp; struct buf *bp; @@ -559,11 +701,9 @@ sys_lfs_bmapv(p, v, retval) struct mount *mntp; struct ufsmount *ump; struct vnode *vp; - fsid_t fsid; - void *start; ino_t lastino; ufs_daddr_t v_daddr; - int origcnt, cnt, error, need_unlock=0; + int cnt, error, need_unlock=0; int numlocked=0, numrefed=0; #ifdef LFS_TRACK_IOS int j; @@ -571,26 +711,14 @@ sys_lfs_bmapv(p, v, retval) lfs_cleaner_pid = p->p_pid; - if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) - return (error); - - if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0) - return (error); - if ((mntp = vfs_getvfs(&fsid)) == NULL) + if ((mntp = vfs_getvfs(fsidp)) == NULL) return (ENOENT); ump = VFSTOUFS(mntp); if ((error = vfs_busy(mntp, LK_NOWAIT, NULL)) != 0) return (error); - origcnt = cnt = SCARG(uap, blkcnt); - start = malloc(cnt * sizeof(BLOCK_INFO), M_SEGMENT, M_WAITOK); - error = copyin(SCARG(uap, blkiov), start, cnt * sizeof(BLOCK_INFO)); - if (error) { - free(start, M_SEGMENT); - vfs_unbusy(mntp); - return (error); - } + cnt = blkcnt; fs = VFSTOUFS(mntp)->um_lfs; @@ -599,13 +727,12 @@ sys_lfs_bmapv(p, v, retval) /* these were inside the initialization for the for loop */ v_daddr = LFS_UNUSED_DADDR; lastino = LFS_UNUSED_INUM; - for (blkp = start; cnt--; ++blkp) + for (blkp = blkiov; cnt--; ++blkp) { #ifdef DEBUG - if (datosn(fs, fs->lfs_curseg) == datosn(fs, blkp->bi_daddr)) { + if (dtosn(fs, fs->lfs_curseg) == dtosn(fs, blkp->bi_daddr)) { printf("lfs_bmapv: attempt to clean current segment? (#%d)\n", - datosn(fs, fs->lfs_curseg)); - free(start,M_SEGMENT); + dtosn(fs, fs->lfs_curseg)); vfs_unbusy(mntp); return (EBUSY); } @@ -618,11 +745,10 @@ sys_lfs_bmapv(p, v, retval) */ for(j=0;j<LFS_THROTTLE;j++) { if(fs->lfs_pending[j] != LFS_UNUSED_DADDR - && datosn(fs,fs->lfs_pending[j])==datosn(fs,blkp->bi_daddr)) + && dtosn(fs,fs->lfs_pending[j])==dtosn(fs,blkp->bi_daddr)) { printf("lfs_bmapv: attempt to clean pending segment? (#%d)\n", - datosn(fs, fs->lfs_pending[j])); - free(start,M_SEGMENT); + dtosn(fs, fs->lfs_pending[j])); vfs_unbusy(mntp); return (EBUSY); } @@ -737,6 +863,7 @@ sys_lfs_bmapv(p, v, retval) blkp->bi_daddr = LFS_UNUSED_DADDR; continue; } + blkp->bi_daddr = dbtofsb(fs, blkp->bi_daddr); } } @@ -758,8 +885,6 @@ sys_lfs_bmapv(p, v, retval) numrefed); } - copyout(start, SCARG(uap, blkiov), origcnt * sizeof(BLOCK_INFO)); - free(start, M_SEGMENT); vfs_unbusy(mntp); return 0; @@ -774,10 +899,7 @@ sys_lfs_bmapv(p, v, retval) * -1/errno is return on error. */ int -sys_lfs_segclean(p, v, retval) - struct proc *p; - void *v; - register_t *retval; +sys_lfs_segclean(struct proc *p, void *v, register_t *retval) { struct sys_lfs_segclean_args /* { syscallarg(fsid_t *) fsidp; @@ -801,7 +923,7 @@ sys_lfs_segclean(p, v, retval) fs = VFSTOUFS(mntp)->um_lfs; - if (datosn(fs, fs->lfs_curseg) == SCARG(uap, segment)) + if (dtosn(fs, fs->lfs_curseg) == SCARG(uap, segment)) return (EBUSY); if ((error = vfs_busy(mntp, LK_NOWAIT, NULL)) != 0) @@ -818,13 +940,16 @@ sys_lfs_segclean(p, v, retval) return (EALREADY); } - fs->lfs_avail += fsbtodb(fs, fs->lfs_ssize); + fs->lfs_avail += segtod(fs, 1); if (sup->su_flags & SEGUSE_SUPERBLOCK) - fs->lfs_avail -= btodb(LFS_SBPAD); - fs->lfs_bfree += sup->su_nsums * btodb(LFS_SUMMARY_SIZE) + - fsbtodb(fs, sup->su_ninos); - fs->lfs_dmeta -= sup->su_nsums * btodb(LFS_SUMMARY_SIZE) + - fsbtodb(fs, sup->su_ninos); + fs->lfs_avail -= btofsb(fs, LFS_SBPAD); + if (fs->lfs_version > 1 && SCARG(uap, segment) == 0 && + fs->lfs_start < btofsb(fs, LFS_LABELPAD)) + fs->lfs_avail -= btofsb(fs, LFS_LABELPAD) - fs->lfs_start; + fs->lfs_bfree += sup->su_nsums * btofsb(fs, fs->lfs_sumsize) + + btofsb(fs, sup->su_ninos * fs->lfs_ibsize); + fs->lfs_dmeta -= sup->su_nsums * btofsb(fs, fs->lfs_sumsize) + + btofsb(fs, sup->su_ninos * fs->lfs_ibsize); if (fs->lfs_dmeta < 0) fs->lfs_dmeta = 0; sup->su_flags &= ~SEGUSE_DIRTY; @@ -855,10 +980,7 @@ sys_lfs_segclean(p, v, retval) * -1/errno is return on error. */ int -sys_lfs_segwait(p, v, retval) - struct proc *p; - void *v; - register_t *retval; +sys_lfs_segwait(struct proc *p, void *v, register_t *retval) { struct sys_lfs_segwait_args /* { syscallarg(fsid_t *) fsidp; @@ -921,11 +1043,7 @@ sys_lfs_segwait(p, v, retval) extern struct lock ufs_hashlock; int -lfs_fasthashget(dev, ino, need_unlock, vpp) - dev_t dev; - ino_t ino; - int *need_unlock; - struct vnode **vpp; +lfs_fasthashget(dev_t dev, ino_t ino, int *need_unlock, struct vnode **vpp) { struct inode *ip; @@ -969,13 +1087,7 @@ lfs_fasthashget(dev, ino, need_unlock, vpp) } int -lfs_fastvget(mp, ino, daddr, vpp, dinp, need_unlock) - struct mount *mp; - ino_t ino; - ufs_daddr_t daddr; - struct vnode **vpp; - struct dinode *dinp; - int *need_unlock; +lfs_fastvget(struct mount *mp, ino_t ino, ufs_daddr_t daddr, struct vnode **vpp, struct dinode *dinp, int *need_unlock) { struct inode *ip; struct vnode *vp; @@ -983,17 +1095,19 @@ lfs_fastvget(mp, ino, daddr, vpp, dinp, need_unlock) dev_t dev; int error; struct buf *bp; + struct lfs *fs; ump = VFSTOUFS(mp); dev = ump->um_dev; + fs = ump->um_lfs; *need_unlock = 0; /* * Wait until the filesystem is fully mounted before allowing vget * to complete. This prevents possible problems with roll-forward. */ - while(ump->um_lfs->lfs_flags & LFS_NOTYET) { - tsleep(&ump->um_lfs->lfs_flags, PRIBIO+1, "lfs_fnotyet", 0); + while(fs->lfs_flags & LFS_NOTYET) { + tsleep(&fs->lfs_flags, PRIBIO+1, "lfs_fnotyet", 0); } /* * This is playing fast and loose. Someone may have the inode @@ -1037,7 +1151,7 @@ lfs_fastvget(mp, ino, daddr, vpp, dinp, need_unlock) * the i_devvp initialization. * Ask Kirk. */ - ip->i_lfs = ump->um_lfs; + ip->i_lfs = fs; /* Read in the disk contents for the inode, copy into the inode. */ if (dinp) { @@ -1055,8 +1169,8 @@ lfs_fastvget(mp, ino, daddr, vpp, dinp, need_unlock) if(ip->i_number != ino) panic("lfs_fastvget: I was fed the wrong inode!"); } else { - error = bread(ump->um_devvp, daddr, - (int)ump->um_lfs->lfs_bsize, NOCRED, &bp); + error = bread(ump->um_devvp, fsbtodb(fs, daddr), fs->lfs_ibsize, + NOCRED, &bp); if (error) { printf("lfs_fastvget: bread failed with %d\n",error); /* @@ -1073,8 +1187,7 @@ lfs_fastvget(mp, ino, daddr, vpp, dinp, need_unlock) *vpp = NULL; return (error); } - ip->i_din.ffs_din = - *lfs_ifind(ump->um_lfs, ino, bp); + ip->i_din.ffs_din = *lfs_ifind(fs, ino, bp); brelse(bp); } ip->i_ffs_effnlink = ip->i_ffs_nlink; @@ -1117,24 +1230,20 @@ lfs_fastvget(mp, ino, daddr, vpp, dinp, need_unlock) } struct buf * -lfs_fakebuf(vp, lbn, size, uaddr) - struct vnode *vp; - int lbn; - size_t size; - caddr_t uaddr; +lfs_fakebuf(struct vnode *vp, int lbn, size_t size, caddr_t uaddr) { struct buf *bp; int error; #ifndef ALLOW_VFLUSH_CORRUPTION - bp = lfs_newbuf(vp, lbn, size); + bp = lfs_newbuf(VTOI(vp)->i_lfs, vp, lbn, size); error = copyin(uaddr, bp->b_data, size); if(error) { lfs_freebuf(bp); return NULL; } #else - bp = lfs_newbuf(vp, lbn, 0); + bp = lfs_newbuf(VTOI(vp)->i_lfs, vp, lbn, 0); bp->b_flags |= B_INVAL; bp->b_saveaddr = uaddr; #endif diff --git a/sys/ufs/lfs/lfs_vfsops.c b/sys/ufs/lfs/lfs_vfsops.c index 88bc550ccb5..45c809f68b6 100644 --- a/sys/ufs/lfs/lfs_vfsops.c +++ b/sys/ufs/lfs/lfs_vfsops.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_vfsops.c,v 1.65 2001/05/30 11:57:19 mrg Exp $ */ +/* $NetBSD: lfs_vfsops.c,v 1.66 2001/07/13 20:30:25 perseant Exp $ */ /*- * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. @@ -104,7 +104,7 @@ #include <ufs/lfs/lfs.h> #include <ufs/lfs/lfs_extern.h> -int lfs_mountfs __P((struct vnode *, struct mount *, struct proc *)); +int lfs_mountfs(struct vnode *, struct mount *, struct proc *); extern const struct vnodeopv_desc lfs_vnodeop_opv_desc; extern const struct vnodeopv_desc lfs_specop_opv_desc; @@ -214,12 +214,7 @@ lfs_mountroot() * mount system call */ int -lfs_mount(mp, path, data, ndp, p) - struct mount *mp; - const char *path; - void *data; - struct nameidata *ndp; - struct proc *p; +lfs_mount(struct mount *mp, const char *path, void *data, struct nameidata *ndp, struct proc *p) { struct vnode *devvp; struct ufs_args args; @@ -323,7 +318,6 @@ lfs_mount(mp, path, data, ndp, p) return (0); } -#ifdef LFS_DO_ROLLFORWARD /* * Roll-forward code. */ @@ -346,8 +340,10 @@ update_meta(struct lfs *fs, ino_t ino, int version, ufs_daddr_t lbn, int num; if ((error = lfs_rf_valloc(fs, ino, version, p, &vp)) != 0) { +#ifdef DEBUG_LFS_RFW printf("update_meta: ino %d: lfs_rf_valloc returned %d\n", ino, error); +#endif return error; } @@ -359,7 +355,7 @@ update_meta(struct lfs *fs, ino_t ino, int version, ufs_daddr_t lbn, /* No need to write, the block is already on disk */ if (bp->b_flags & B_DELWRI) { LFS_UNLOCK_BUF(bp); - fs->lfs_avail += btodb(bp->b_bcount); + fs->lfs_avail += btofsb(fs, bp->b_bcount); } bp->b_flags |= B_INVAL; brelse(bp); @@ -381,7 +377,9 @@ update_meta(struct lfs *fs, ino_t ino, int version, ufs_daddr_t lbn, error = ufs_bmaparray(vp, lbn, &odaddr, &a[0], &num, NULL); if (error) { +#ifdef DEBUG_LFS_RFW printf("update_meta: ufs_bmaparray returned %d\n", error); +#endif vput(vp); return error; } @@ -389,13 +387,13 @@ update_meta(struct lfs *fs, ino_t ino, int version, ufs_daddr_t lbn, case 0: ooff = ip->i_ffs_db[lbn]; if (ooff == UNWRITTEN) - ip->i_ffs_blocks += btodb(size); + ip->i_ffs_blocks += btofsb(fs, size); ip->i_ffs_db[lbn] = ndaddr; break; case 1: ooff = ip->i_ffs_ib[a[0].in_off]; if (ooff == UNWRITTEN) - ip->i_ffs_blocks += btodb(size); + ip->i_ffs_blocks += btofsb(fs, size); ip->i_ffs_ib[a[0].in_off] = ndaddr; break; default: @@ -405,7 +403,7 @@ update_meta(struct lfs *fs, ino_t ino, int version, ufs_daddr_t lbn, ooff = ((ufs_daddr_t *)bp->b_data)[ap->in_off]; if (ooff == UNWRITTEN) - ip->i_ffs_blocks += btodb(size); + ip->i_ffs_blocks += btofsb(fs, size); ((ufs_daddr_t *)bp->b_data)[ap->in_off] = ndaddr; (void) VOP_BWRITE(bp); } @@ -413,31 +411,32 @@ update_meta(struct lfs *fs, ino_t ino, int version, ufs_daddr_t lbn, /* Update segment usage information. */ if (odaddr > 0) { - LFS_SEGENTRY(sup, fs, datosn(fs, odaddr), bp); + LFS_SEGENTRY(sup, fs, dtosn(fs, dbtofsb(fs, odaddr)), bp); #ifdef DIAGNOSTIC if (sup->su_nbytes < size) { panic("update_meta: negative bytes " "(segment %d short by %ld)\n", - datosn(fs, odaddr), (long)size - sup->su_nbytes); + dtosn(fs, dbtofsb(fs, odaddr)), (long)size - sup->su_nbytes); sup->su_nbytes = size; } #endif sup->su_nbytes -= size; VOP_BWRITE(bp); } - LFS_SEGENTRY(sup, fs, datosn(fs, ndaddr), bp); + LFS_SEGENTRY(sup, fs, dtosn(fs, ndaddr), bp); sup->su_nbytes += size; VOP_BWRITE(bp); /* Fix this so it can be released */ /* ip->i_lfs_effnblks = ip->i_ffs_blocks; */ +#ifdef DEBUG_LFS_RFW /* Now look again to make sure it worked */ ufs_bmaparray(vp, lbn, &odaddr, &a[0], &num, NULL ); - if (odaddr != ndaddr) + if (dbtofsb(fs, odaddr) != ndaddr) printf("update_meta: failed setting ino %d lbn %d to %x\n", ino, lbn, ndaddr); - +#endif vput(vp); return 0; } @@ -461,9 +460,11 @@ update_inoblk(struct lfs *fs, daddr_t offset, struct ucred *cred, * Get the inode, update times and perms. * DO NOT update disk blocks, we do that separately. */ - error = bread(devvp, offset, fs->lfs_bsize, cred, &dbp); + error = bread(devvp, fsbtodb(fs, offset), fs->lfs_ibsize, cred, &dbp); if (error) { +#ifdef DEBUG_LFS_RFW printf("update_inoblk: bread returned %d\n", error); +#endif return error; } dip = ((struct dinode *)(dbp->b_data)) + INOPB(fs); @@ -474,7 +475,9 @@ update_inoblk(struct lfs *fs, daddr_t offset, struct ucred *cred, error = lfs_rf_valloc(fs, dip->di_inumber, dip->di_gen, p, &vp); if (error) { +#ifdef DEBUG_LFS_RFW printf("update_inoblk: lfs_rf_valloc returned %d\n", error); +#endif continue; } ip = VTOI(vp); @@ -502,17 +505,17 @@ update_inoblk(struct lfs *fs, daddr_t offset, struct ucred *cred, /* Record change in location */ LFS_IENTRY(ifp, fs, dip->di_inumber, ibp); daddr = ifp->if_daddr; - ifp->if_daddr = dbp->b_blkno; + ifp->if_daddr = dbtofsb(fs, dbp->b_blkno); error = VOP_BWRITE(ibp); /* Ifile */ /* And do segment accounting */ - if (datosn(fs, daddr) != datosn(fs, dbp->b_blkno)) { + if (dtosn(fs, daddr) != dtosn(fs, dbtofsb(fs, dbp->b_blkno))) { if (daddr > 0) { - LFS_SEGENTRY(sup, fs, datosn(fs, daddr), + LFS_SEGENTRY(sup, fs, dtosn(fs, daddr), ibp); sup->su_nbytes -= DINODE_SIZE; VOP_BWRITE(ibp); } - LFS_SEGENTRY(sup, fs, datosn(fs, dbp->b_blkno), + LFS_SEGENTRY(sup, fs, dtosn(fs, dbtofsb(fs, dbp->b_blkno)), ibp); sup->su_nbytes += DINODE_SIZE; VOP_BWRITE(ibp); @@ -541,21 +544,22 @@ check_segsum(struct lfs *fs, daddr_t offset, FINFO *fip; SEGUSE *sup; size_t size; + u_int64_t serial; devvp = VTOI(fs->lfs_ivnode)->i_devvp; /* * If the segment has a superblock and we're at the top * of the segment, skip the superblock. */ - if(sntoda(fs, datosn(fs, offset)) == offset) { - LFS_SEGENTRY(sup, fs, datosn(fs, offset), bp); + if(sntod(fs, dtosn(fs, offset)) == offset) { + LFS_SEGENTRY(sup, fs, dtosn(fs, offset), bp); if(sup->su_flags & SEGUSE_SUPERBLOCK) - offset += btodb(LFS_SBPAD); + offset += btofsb(fs, LFS_SBPAD); brelse(bp); } /* Read in the segment summary */ - error = bread(devvp, offset, LFS_SUMMARY_SIZE, cred, &bp); + error = bread(devvp, offset, fs->lfs_sumsize, cred, &bp); if(error) return -1; @@ -563,7 +567,7 @@ check_segsum(struct lfs *fs, daddr_t offset, ssp = (SEGSUM *)bp->b_data; if(flags & CHECK_CKSUM) { if(ssp->ss_sumsum != cksum(&ssp->ss_datasum, - LFS_SUMMARY_SIZE - + fs->lfs_sumsize - sizeof(ssp->ss_sumsum))) { #ifdef DEBUG_LFS_RFW printf("Sumsum error at 0x%x\n", offset); @@ -586,17 +590,35 @@ check_segsum(struct lfs *fs, daddr_t offset, goto err1; } } + if (fs->lfs_version > 1) { + serial = ssp->ss_serial; + if (serial != fs->lfs_serial + 1) { +#ifdef DEBUG_LFS_RFW + printf("Unexpected serial number at 0x%x\n", offset); +#endif + offset = -1; + goto err1; + } + if (ssp->ss_ident != fs->lfs_ident) { +#ifdef DEBUG_LFS_RFW + printf("Incorrect fsid (0x%x vs 0x%x) at 0x%x\n", + ssp->ss_ident, fs->lfs_ident, offset); +#endif + offset = -1; + goto err1; + } + } if(pseg_flags) *pseg_flags = ssp->ss_flags; oldoffset = offset; - offset += btodb(LFS_SUMMARY_SIZE); + offset += btofsb(fs, fs->lfs_sumsize); ninos = howmany(ssp->ss_ninos, INOPB(fs)); - iaddr = (daddr_t *)(bp->b_data + LFS_SUMMARY_SIZE - sizeof(daddr_t)); + iaddr = (daddr_t *)(bp->b_data + fs->lfs_sumsize - sizeof(daddr_t)); if(flags & CHECK_CKSUM) { /* Count blocks */ nblocks = 0; - fip = (FINFO *)(bp->b_data + sizeof(SEGSUM)); + fip = (FINFO *)(bp->b_data + SEGSUM_SIZE(fs)); for(i = 0; i < ssp->ss_nfinfo; ++i) { nblocks += fip->fi_nblocks; if(fip->fi_nblocks <= 0) @@ -612,13 +634,13 @@ check_segsum(struct lfs *fs, daddr_t offset, } /* Handle individual blocks */ - fip = (FINFO *)(bp->b_data + sizeof(SEGSUM)); + fip = (FINFO *)(bp->b_data + SEGSUM_SIZE(fs)); for(i = 0; i < ssp->ss_nfinfo || ninos; ++i) { /* Inode block? */ if(ninos && *iaddr == offset) { if(flags & CHECK_CKSUM) { /* Read in the head and add to the buffer */ - error = bread(devvp, offset, fs->lfs_bsize, + error = bread(devvp, fsbtodb(fs, offset), fs->lfs_bsize, cred, &dbp); if(error) { offset = -1; @@ -635,7 +657,7 @@ check_segsum(struct lfs *fs, daddr_t offset, goto err2; } } - offset += fsbtodb(fs,1); + offset += btofsb(fs, fs->lfs_ibsize); --iaddr; --ninos; --i; /* compensate */ @@ -648,7 +670,7 @@ check_segsum(struct lfs *fs, daddr_t offset, if (j == fip->fi_nblocks - 1) size = fip->fi_lastlength; if(flags & CHECK_CKSUM) { - error = bread(devvp, offset, size, cred, &dbp); + error = bread(devvp, fsbtodb(fs, offset), size, cred, &dbp); if(error) { offset = -1; goto err2; @@ -664,7 +686,7 @@ check_segsum(struct lfs *fs, daddr_t offset, update_meta(fs, fip->fi_ino, fip->fi_version, fip->fi_blocks[j], offset, size, p); } - offset += btodb(size); + offset += btofsb(fs, size); } fip = (FINFO *)(((char *)fip) + sizeof(FINFO) + (fip->fi_nblocks - 1) * sizeof(ufs_daddr_t)); @@ -673,24 +695,26 @@ check_segsum(struct lfs *fs, daddr_t offset, if((flags & CHECK_CKSUM) && ssp->ss_datasum != cksum(datap, nblocks * sizeof(u_long))) { +#ifdef DEBUG_LFS_RFW printf("Datasum error at 0x%x (wanted %x got %x)\n", offset, ssp->ss_datasum, cksum(datap, nblocks * sizeof(u_long))); +#endif offset = -1; goto err2; } /* If we're at the end of the segment, move to the next */ - if(datosn(fs, offset + btodb(LFS_SUMMARY_SIZE + fs->lfs_bsize)) != - datosn(fs, offset)) { - if (datosn(fs, offset) == datosn(fs, ssp->ss_next)) { + if(dtosn(fs, offset + btofsb(fs, fs->lfs_sumsize + fs->lfs_bsize)) != + dtosn(fs, offset)) { + if (dtosn(fs, offset) == dtosn(fs, ssp->ss_next)) { offset = -1; goto err2; } offset = ssp->ss_next; #ifdef DEBUG_LFS_RFW printf("LFS roll forward: moving on to offset 0x%x " - " -> segment %d\n", offset, datosn(fs,offset)); + " -> segment %d\n", offset, dtosn(fs,offset)); #endif } @@ -713,19 +737,18 @@ check_segsum(struct lfs *fs, daddr_t offset, bp->b_flags |= B_AGE; brelse(bp); + /* XXX should we update the serial number even for bad psegs? */ + if ((flags & CHECK_UPDATE) && offset > 0 && fs->lfs_version > 1) + fs->lfs_serial = serial; return offset; } -#endif /* LFS_DO_ROLLFORWARD */ /* * Common code for mount and mountroot * LFS specific */ int -lfs_mountfs(devvp, mp, p) - struct vnode *devvp; - struct mount *mp; - struct proc *p; +lfs_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p) { extern struct vnode *rootvp; struct dlfs *tdfs, *dfs, *adfs; @@ -735,15 +758,13 @@ lfs_mountfs(devvp, mp, p) struct buf *bp, *abp; struct partinfo dpart; dev_t dev; - int error, i, ronly, size; + int error, i, ronly, secsize, fsbsize; struct ucred *cred; CLEANERINFO *cip; SEGUSE *sup; -#ifdef LFS_DO_ROLLFORWARD - int flags, dirty; - daddr_t offset, oldoffset, lastgoodpseg; + int flags, dirty, do_rollforward; + daddr_t offset, oldoffset, lastgoodpseg, sb_addr; int sn, curseg; -#endif cred = p ? p->p_ucred : NOCRED; /* @@ -764,27 +785,61 @@ lfs_mountfs(devvp, mp, p) if (error) return (error); if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0) - size = DEV_BSIZE; + secsize = DEV_BSIZE; else - size = dpart.disklab->d_secsize; + secsize = dpart.disklab->d_secsize; /* Don't free random space on error. */ bp = NULL; abp = NULL; ump = NULL; - /* Read in the superblock. */ - error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, cred, &bp); - if (error) - goto out; - dfs = (struct dlfs *)bp->b_data; + sb_addr = LFS_LABELPAD / secsize; + while(1) { + /* Read in the superblock. */ + error = bread(devvp, sb_addr, LFS_SBPAD, cred, &bp); + if (error) + goto out; + dfs = (struct dlfs *)bp->b_data; - /* Check the basics. */ - if (dfs->dlfs_magic != LFS_MAGIC || dfs->dlfs_bsize > MAXBSIZE || - dfs->dlfs_version > LFS_VERSION || - dfs->dlfs_bsize < sizeof(struct dlfs)) { - error = EINVAL; /* XXX needs translation */ - goto out; + /* Check the basics. */ + if (dfs->dlfs_magic != LFS_MAGIC || dfs->dlfs_bsize >= MAXBSIZE || + dfs->dlfs_version > LFS_VERSION || + dfs->dlfs_bsize < sizeof(struct dlfs)) { +#ifdef DEBUG_LFS + printf("lfs_mountfs: primary superblock sanity failed\n"); +#endif + error = EINVAL; /* XXX needs translation */ + goto out; + } + if (dfs->dlfs_inodefmt > LFS_MAXINODEFMT) + printf("lfs_mountfs: warning: unknown inode format %d\n", + dfs->dlfs_inodefmt); + + if (dfs->dlfs_version == 1) + fsbsize = secsize; + else { + fsbsize = 1 << (dfs->dlfs_bshift - dfs->dlfs_blktodb + + dfs->dlfs_fsbtodb); + /* + * Could be, if the frag size is large enough, that we + * don't have the "real" primary superblock. If that's + * the case, get the real one, and try again. + */ + if (sb_addr != dfs->dlfs_sboffs[0] << + dfs->dlfs_fsbtodb) { +/* #ifdef DEBUG_LFS */ + printf("lfs_mountfs: sb daddr 0x%x is not right, trying 0x%x\n", + sb_addr, dfs->dlfs_sboffs[0] << + dfs->dlfs_fsbtodb); +/* #endif */ + sb_addr = dfs->dlfs_sboffs[0] << + dfs->dlfs_fsbtodb; + brelse(bp); + continue; + } + } + break; } /* @@ -794,29 +849,44 @@ lfs_mountfs(devvp, mp, p) */ if (dfs->dlfs_sboffs[1] && - dfs->dlfs_sboffs[1]-(LFS_LABELPAD/size) > LFS_SBPAD/size) + dfs->dlfs_sboffs[1] - LFS_LABELPAD / fsbsize > LFS_SBPAD / fsbsize) { - error = bread(devvp, dfs->dlfs_sboffs[1], LFS_SBPAD, cred, &abp); + error = bread(devvp, dfs->dlfs_sboffs[1] * (fsbsize / secsize), + LFS_SBPAD, cred, &abp); if (error) goto out; adfs = (struct dlfs *)abp->b_data; - if (adfs->dlfs_tstamp < dfs->dlfs_tstamp) /* XXX 1s? */ - tdfs = adfs; - else - tdfs = dfs; + if (dfs->dlfs_version == 1) { + /* 1s resolution comparison */ + if (adfs->dlfs_tstamp < dfs->dlfs_tstamp) + tdfs = adfs; + else + tdfs = dfs; + } else { + /* monotonic infinite-resolution comparison */ + if (adfs->dlfs_serial < dfs->dlfs_serial) + tdfs = adfs; + else + tdfs = dfs; + } /* Check the basics. */ if (tdfs->dlfs_magic != LFS_MAGIC || tdfs->dlfs_bsize > MAXBSIZE || tdfs->dlfs_version > LFS_VERSION || tdfs->dlfs_bsize < sizeof(struct dlfs)) { +#ifdef DEBUG_LFS + printf("lfs_mountfs: alt superblock sanity failed\n"); +#endif error = EINVAL; /* XXX needs translation */ goto out; } } else { +#ifdef DEBUG_LFS printf("lfs_mountfs: invalid alt superblock daddr=0x%x\n", dfs->dlfs_sboffs[1]); +#endif error = EINVAL; goto out; } @@ -825,13 +895,18 @@ lfs_mountfs(devvp, mp, p) fs = malloc(sizeof(struct lfs), M_UFSMNT, M_WAITOK); memcpy(&fs->lfs_dlfs, tdfs, sizeof(struct dlfs)); -#ifdef LFS_DO_ROLLFORWARD + /* Compatibility */ + if (fs->lfs_version < 2) { + fs->lfs_sumsize = LFS_V1_SUMMARY_SIZE; + fs->lfs_ibsize = fs->lfs_bsize; + fs->lfs_start = fs->lfs_sboffs[0]; + fs->lfs_tstamp = fs->lfs_otstamp; + fs->lfs_fsbtodb = 0; + } + /* Before rolling forward, lock so vget will sleep for other procs */ fs->lfs_flags = LFS_NOTYET; fs->lfs_rfpid = p->p_pid; -#else - fs->lfs_flags = 0; -#endif ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK); memset((caddr_t)ump, 0, sizeof *ump); @@ -846,14 +921,13 @@ lfs_mountfs(devvp, mp, p) abp = NULL; /* Set up the I/O information */ + fs->lfs_devbsize = secsize; fs->lfs_iocount = 0; fs->lfs_diropwait = 0; fs->lfs_activesb = 0; fs->lfs_uinodes = 0; fs->lfs_ravail = 0; -#ifdef LFS_CANNOT_ROLLFW fs->lfs_sbactive = 0; -#endif #ifdef LFS_TRACK_IOS for (i=0;i<LFS_THROTTLE;i++) fs->lfs_pending[i] = LFS_UNUSED_DADDR; @@ -884,8 +958,8 @@ lfs_mountfs(devvp, mp, p) ump->um_mountp = mp; ump->um_dev = dev; ump->um_devvp = devvp; - ump->um_bptrtodb = 0; - ump->um_seqinc = 1 << fs->lfs_fsbtodb; + ump->um_bptrtodb = fs->lfs_fsbtodb; + ump->um_seqinc = fragstofsb(fs, fs->lfs_frag); ump->um_nindir = fs->lfs_nindir; ump->um_lognindir = ffs(fs->lfs_nindir) - 1; for (i = 0; i < MAXQUOTAS; i++) @@ -898,102 +972,135 @@ lfs_mountfs(devvp, mp, p) * artificially increment the reference count and keep a pointer * to it in the incore copy of the superblock. */ - if ((error = VFS_VGET(mp, LFS_IFILE_INUM, &vp)) != 0) + if ((error = VFS_VGET(mp, LFS_IFILE_INUM, &vp)) != 0) { +#ifdef DEBUG + printf("lfs_mountfs: ifile vget failed, error=%d\n", error); +#endif goto out; + } fs->lfs_ivnode = vp; VREF(vp); vput(vp); -#ifdef LFS_DO_ROLLFORWARD /* * Roll forward. + * + * We don't automatically roll forward for v1 filesystems, because + * of the danger that the clock was turned back between the last + * checkpoint and crash. This would roll forward garbage. + * + * v2 filesystems don't have this problem because they use a + * monotonically increasing serial number instead of a timestamp. */ - /* - * Phase I: - * Find the address of the last good partial segment that was written - * after the checkpoint. Mark the segments in question dirty, so - * they won't be reallocated. - */ - lastgoodpseg = oldoffset = offset = fs->lfs_offset; - flags = 0x0; +#ifdef LFS_DO_ROLLFORWARD + do_rollforward = !fs->lfs_ronly; +#else + do_rollforward = (fs->lfs_version > 1 && !fs->lfs_ronly && + !(fs->lfs_pflags & LFS_PF_CLEAN)); +#endif + if (do_rollforward) { + /* + * Phase I: Find the address of the last good partial + * segment that was written after the checkpoint. Mark + * the segments in question dirty, so they won't be + * reallocated. + */ + lastgoodpseg = oldoffset = offset = fs->lfs_offset; + flags = 0x0; #ifdef DEBUG_LFS_RFW - printf("LFS roll forward phase 1: starting at offset 0x%x\n", offset); + printf("LFS roll forward phase 1: starting at offset 0x%x\n", + offset); #endif - LFS_SEGENTRY(sup, fs, datosn(fs, offset), bp); - if (!(sup->su_flags & SEGUSE_DIRTY)) - --fs->lfs_nclean; - sup->su_flags |= SEGUSE_DIRTY; - (void) VOP_BWRITE(bp); - while ((offset = check_segsum(fs, offset, cred, CHECK_CKSUM, &flags, - p)) > 0) { - if(sntoda(fs, oldoffset) != sntoda(fs, offset)) { - LFS_SEGENTRY(sup, fs, datosn(fs, oldoffset), bp); - if (!(sup->su_flags & SEGUSE_DIRTY)) - --fs->lfs_nclean; - sup->su_flags |= SEGUSE_DIRTY; - (void) VOP_BWRITE(bp); - } + LFS_SEGENTRY(sup, fs, dtosn(fs, offset), bp); + if (!(sup->su_flags & SEGUSE_DIRTY)) + --fs->lfs_nclean; + sup->su_flags |= SEGUSE_DIRTY; + (void) VOP_BWRITE(bp); + while ((offset = check_segsum(fs, offset, cred, CHECK_CKSUM, + &flags, p)) > 0) + { + if(sntod(fs, oldoffset) != sntod(fs, offset)) { + LFS_SEGENTRY(sup, fs, dtosn(fs, oldoffset), + bp); + if (!(sup->su_flags & SEGUSE_DIRTY)) + --fs->lfs_nclean; + sup->su_flags |= SEGUSE_DIRTY; + (void) VOP_BWRITE(bp); + } #ifdef DEBUG_LFS_RFW - printf("LFS roll forward phase 1: offset=0x%x\n", offset); - if(flags & SS_DIROP) { - printf("lfs_mountfs: dirops at 0x%x\n", oldoffset); - if(!(flags & SS_CONT)) - printf("lfs_mountfs: dirops end at 0x%x\n", + printf("LFS roll forward phase 1: offset=0x%x\n", + offset); + if(flags & SS_DIROP) { + printf("lfs_mountfs: dirops at 0x%x\n", oldoffset); - } + if(!(flags & SS_CONT)) + printf("lfs_mountfs: dirops end " + "at 0x%x\n", oldoffset); + } #endif - if(!(flags & SS_CONT)) - lastgoodpseg = offset; - oldoffset = offset; - } + if(!(flags & SS_CONT)) + lastgoodpseg = offset; + oldoffset = offset; + } #ifdef DEBUG_LFS_RFW - if (flags & SS_CONT) { - printf("LFS roll forward: warning: incomplete dirops discarded\n"); - } - printf("LFS roll forward phase 1: completed: lastgoodpseg=0x%x\n", - lastgoodpseg); + if (flags & SS_CONT) { + printf("LFS roll forward: warning: incomplete " + "dirops discarded\n"); + } + printf("LFS roll forward phase 1: completed: " + "lastgoodpseg=0x%x\n", lastgoodpseg); #endif + oldoffset = fs->lfs_offset; + if (fs->lfs_offset != lastgoodpseg) { + /* Don't overwrite what we're trying to preserve */ + offset = fs->lfs_offset; + fs->lfs_offset = lastgoodpseg; + fs->lfs_curseg = sntod(fs, dtosn(fs, fs->lfs_offset)); + for (sn = curseg = dtosn(fs, fs->lfs_curseg);;) { + sn = (sn + 1) % fs->lfs_nseg; + if (sn == curseg) + panic("lfs_mountfs: no clean segments"); + LFS_SEGENTRY(sup, fs, sn, bp); + dirty = (sup->su_flags & SEGUSE_DIRTY); + brelse(bp); + if (!dirty) + break; + } + fs->lfs_nextseg = sntod(fs, sn); - /* Don't accidentally overwrite what we're trying to preserve */ - offset = fs->lfs_offset; - fs->lfs_offset = lastgoodpseg; - fs->lfs_curseg = sntoda(fs, datosn(fs, fs->lfs_offset)); - for (sn = curseg = datosn(fs, fs->lfs_curseg);;) { - sn = (sn + 1) % fs->lfs_nseg; - if (sn == curseg) - panic("lfs_mountfs: no clean segments"); - LFS_SEGENTRY(sup, fs, sn, bp); - dirty = (sup->su_flags & SEGUSE_DIRTY); - brelse(bp); - if (!dirty) - break; - } - fs->lfs_nextseg = sntoda(fs, sn); - - /* - * Phase II: Roll forward from the first superblock. - */ - while (offset != lastgoodpseg) { + /* + * Phase II: Roll forward from the first superblock. + */ + while (offset != lastgoodpseg) { #ifdef DEBUG_LFS_RFW - printf("LFS roll forward phase 2: 0x%x\n", offset); + printf("LFS roll forward phase 2: 0x%x\n", + offset); #endif - oldoffset = offset; - offset = check_segsum(fs, offset, cred, CHECK_UPDATE, NULL, p); - } - - /* - * Finish: flush our changes to disk. - */ - lfs_segwrite(fs->lfs_ivnode->v_mount, SEGM_CKP | SEGM_SYNC); + offset = check_segsum(fs, offset, cred, + CHECK_UPDATE, NULL, p); + } + /* + * Finish: flush our changes to disk. + */ + lfs_segwrite(mp, SEGM_CKP | SEGM_SYNC); + printf("lfs_mountfs: roll forward recovered %d blocks\n", + lastgoodpseg - oldoffset); + } #ifdef DEBUG_LFS_RFW - printf("LFS roll forward complete\n"); + printf("LFS roll forward complete\n"); #endif + } + /* If writing, sb is not clean; record in case of immediate crash */ + if (!fs->lfs_ronly) { + fs->lfs_pflags &= ~LFS_PF_CLEAN; + lfs_writesuper(fs, fs->lfs_sboffs[0]); + } + /* Allow vget now that roll-forward is complete */ fs->lfs_flags &= ~(LFS_NOTYET); wakeup(&fs->lfs_flags); -#endif /* LFS_DO_ROLLFORWARD */ /* * Initialize the ifile cleaner info with information from @@ -1010,7 +1117,7 @@ lfs_mountfs(devvp, mp, p) * Mark the current segment as ACTIVE, since we're going to * be writing to it. */ - LFS_SEGENTRY(sup, fs, datosn(fs, fs->lfs_offset), bp); + LFS_SEGENTRY(sup, fs, dtosn(fs, fs->lfs_offset), bp); sup->su_flags |= SEGUSE_DIRTY | SEGUSE_ACTIVE; (void) VOP_BWRITE(bp); /* Ifile */ @@ -1035,14 +1142,11 @@ out: * unmount system call */ int -lfs_unmount(mp, mntflags, p) - struct mount *mp; - int mntflags; - struct proc *p; +lfs_unmount(struct mount *mp, int mntflags, struct proc *p) { struct ufsmount *ump; struct lfs *fs; - int error, flags, ronly; + int error, flags, ronly, s; extern int lfs_allclean_wakeup; flags = 0; @@ -1070,14 +1174,26 @@ lfs_unmount(mp, mntflags, p) #endif if ((error = vflush(mp, fs->lfs_ivnode, flags)) != 0) return (error); - fs->lfs_clean = 1; if ((error = VFS_SYNC(mp, 1, p->p_ucred, p)) != 0) return (error); if (fs->lfs_ivnode->v_dirtyblkhd.lh_first) panic("lfs_unmount: still dirty blocks on ifile vnode\n"); + + /* Explicitly write the superblock, to update serial and pflags */ + fs->lfs_pflags |= LFS_PF_CLEAN; + lfs_writesuper(fs, fs->lfs_sboffs[0]); + lfs_writesuper(fs, fs->lfs_sboffs[1]); + + /* Finish with the Ifile, now that we're done with it */ vrele(fs->lfs_ivnode); vgone(fs->lfs_ivnode); + /* Wait for superblock writes to complete */ + s = splbio(); + while (fs->lfs_iocount) + tsleep(&fs->lfs_iocount, PRIBIO + 1, "lfs_umount", 0); + splx(s); + ronly = !fs->lfs_ronly; if (ump->um_devvp->v_type != VBAD) ump->um_devvp->v_specmountpoint = NULL; @@ -1101,10 +1217,7 @@ lfs_unmount(mp, mntflags, p) * Get file system statistics. */ int -lfs_statfs(mp, sbp, p) - struct mount *mp; - struct statfs *sbp; - struct proc *p; +lfs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p) { struct lfs *fs; struct ufsmount *ump; @@ -1117,11 +1230,12 @@ lfs_statfs(mp, sbp, p) sbp->f_type = 0; sbp->f_bsize = fs->lfs_fsize; sbp->f_iosize = fs->lfs_bsize; - sbp->f_blocks = dbtofrags(fs, LFS_EST_NONMETA(fs)); - sbp->f_bfree = dbtofrags(fs, LFS_EST_BFREE(fs)); - sbp->f_bavail = dbtofrags(fs, (long)LFS_EST_BFREE(fs) - + sbp->f_blocks = fsbtofrags(fs, LFS_EST_NONMETA(fs)); + sbp->f_bfree = fsbtofrags(fs, LFS_EST_BFREE(fs)); + sbp->f_bavail = fsbtofrags(fs, (long)LFS_EST_BFREE(fs) - (long)LFS_EST_RSVD(fs)); - sbp->f_files = dbtofsb(fs,fs->lfs_bfree) * INOPB(fs); + + sbp->f_files = fs->lfs_bfree / btofsb(fs, fs->lfs_ibsize) * INOPB(fs); sbp->f_ffree = sbp->f_files - fs->lfs_nfiles; if (sbp != &mp->mnt_stat) { bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); @@ -1139,11 +1253,7 @@ lfs_statfs(mp, sbp, p) * Note: we are always called with the filesystem marked `MPBUSY'. */ int -lfs_sync(mp, waitfor, cred, p) - struct mount *mp; - int waitfor; - struct ucred *cred; - struct proc *p; +lfs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p) { int error; struct lfs *fs; @@ -1173,10 +1283,7 @@ extern struct lock ufs_hashlock; * Detection and handling of mount points must be done by the calling routine. */ int -lfs_vget(mp, ino, vpp) - struct mount *mp; - ino_t ino; - struct vnode **vpp; +lfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) { struct lfs *fs; struct inode *ip; @@ -1187,9 +1294,7 @@ lfs_vget(mp, ino, vpp) ufs_daddr_t daddr; dev_t dev; int error; -#ifdef LFS_ATIME_IFILE struct timespec ts; -#endif ump = VFSTOUFS(mp); dev = ump->um_dev; @@ -1224,9 +1329,11 @@ lfs_vget(mp, ino, vpp) /* XXX bounds-check this too */ LFS_IENTRY(ifp, fs, ino, bp); daddr = ifp->if_daddr; -#ifdef LFS_ATIME_IFILE - ts = ifp->if_atime; /* structure copy */ -#endif + if (fs->lfs_version > 1) { + ts.tv_sec = ifp->if_atime_sec; + ts.tv_nsec = ifp->if_atime_nsec; + } + brelse(bp); if (daddr == LFS_UNUSED_DADDR) { *vpp = NULLVP; @@ -1258,7 +1365,9 @@ lfs_vget(mp, ino, vpp) ip->i_lfs = ump->um_lfs; /* Read in the disk contents for the inode, copy into the inode. */ - error = bread(ump->um_devvp, daddr, (int)fs->lfs_bsize, NOCRED, &bp); + error = bread(ump->um_devvp, fsbtodb(fs, daddr), + (fs->lfs_version == 1 ? fs->lfs_bsize : fs->lfs_fsize), + NOCRED, &bp); if (error) { /* * The inode does not contain anything useful, so it would @@ -1274,10 +1383,10 @@ 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; -#endif + if (fs->lfs_version > 1) { + ip->i_ffs_atime = ts.tv_sec; + ip->i_ffs_atimensec = ts.tv_nsec; + } brelse(bp); /* @@ -1322,10 +1431,7 @@ lfs_vget(mp, ino, vpp) * generational number. */ int -lfs_fhtovp(mp, fhp, vpp) - struct mount *mp; - struct fid *fhp; - struct vnode **vpp; +lfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) { struct ufid *ufhp; @@ -1340,9 +1446,7 @@ lfs_fhtovp(mp, fhp, vpp) */ /* ARGSUSED */ int -lfs_vptofh(vp, fhp) - struct vnode *vp; - struct fid *fhp; +lfs_vptofh(struct vnode *vp, struct fid *fhp) { struct inode *ip; struct ufid *ufhp; @@ -1356,14 +1460,7 @@ lfs_vptofh(vp, fhp) } int -lfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) - int *name; - u_int namelen; - void *oldp; - size_t *oldlenp; - void *newp; - size_t newlen; - struct proc *p; +lfs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { extern int lfs_writeindir, lfs_dostats, lfs_clean_vnhead; extern struct lfs_stats lfs_stats; diff --git a/sys/ufs/lfs/lfs_vnops.c b/sys/ufs/lfs/lfs_vnops.c index 1f48bd913b4..bd24cd0fa5f 100644 --- a/sys/ufs/lfs/lfs_vnops.c +++ b/sys/ufs/lfs/lfs_vnops.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_vnops.c,v 1.50 2001/01/22 12:17:43 jdolecek Exp $ */ +/* $NetBSD: lfs_vnops.c,v 1.51 2001/07/13 20:30:25 perseant Exp $ */ /*- * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. @@ -100,7 +100,7 @@ #include <ufs/lfs/lfs_extern.h> /* Global vfs data structures for lfs. */ -int (**lfs_vnodeop_p) __P((void *)); +int (**lfs_vnodeop_p)(void *); const struct vnodeopv_entry_desc lfs_vnodeop_entries[] = { { &vop_default_desc, vn_default_error }, { &vop_lookup_desc, ufs_lookup }, /* lookup */ @@ -148,12 +148,12 @@ const struct vnodeopv_entry_desc lfs_vnodeop_entries[] = { { &vop_truncate_desc, lfs_truncate }, /* truncate */ { &vop_update_desc, lfs_update }, /* update */ { &vop_bwrite_desc, lfs_bwrite }, /* bwrite */ - { (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL } + { (struct vnodeop_desc*)NULL, (int(*)(void *))NULL } }; const struct vnodeopv_desc lfs_vnodeop_opv_desc = { &lfs_vnodeop_p, lfs_vnodeop_entries }; -int (**lfs_specop_p) __P((void *)); +int (**lfs_specop_p)(void *); const struct vnodeopv_entry_desc lfs_specop_entries[] = { { &vop_default_desc, vn_default_error }, { &vop_lookup_desc, spec_lookup }, /* lookup */ @@ -199,12 +199,12 @@ const struct vnodeopv_entry_desc lfs_specop_entries[] = { { &vop_truncate_desc, spec_truncate }, /* truncate */ { &vop_update_desc, lfs_update }, /* update */ { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ - { (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL } + { (struct vnodeop_desc*)NULL, (int(*)(void *))NULL } }; const struct vnodeopv_desc lfs_specop_opv_desc = { &lfs_specop_p, lfs_specop_entries }; -int (**lfs_fifoop_p) __P((void *)); +int (**lfs_fifoop_p)(void *); const struct vnodeopv_entry_desc lfs_fifoop_entries[] = { { &vop_default_desc, vn_default_error }, { &vop_lookup_desc, fifo_lookup }, /* lookup */ @@ -250,7 +250,7 @@ const struct vnodeopv_entry_desc lfs_fifoop_entries[] = { { &vop_truncate_desc, fifo_truncate }, /* truncate */ { &vop_update_desc, lfs_update }, /* update */ { &vop_bwrite_desc, lfs_bwrite }, /* bwrite */ - { (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL } + { (struct vnodeop_desc*)NULL, (int(*)(void *))NULL } }; const struct vnodeopv_desc lfs_fifoop_opv_desc = { &lfs_fifoop_p, lfs_fifoop_entries }; @@ -259,9 +259,7 @@ const struct vnodeopv_desc lfs_fifoop_opv_desc = * A function version of LFS_ITIMES, for the UFS functions which call ITIMES */ void -lfs_itimes(ip, acc, mod, cre) - struct inode *ip; - struct timespec *acc, *mod, *cre; +lfs_itimes(struct inode *ip, struct timespec *acc, struct timespec *mod, struct timespec *cre) { LFS_ITIMES(ip, acc, mod, cre); } @@ -275,8 +273,7 @@ lfs_itimes(ip, acc, mod, cre) */ /* ARGSUSED */ int -lfs_fsync(v) - void *v; +lfs_fsync(void *v) { struct vop_fsync_args /* { struct vnode *a_vp; @@ -299,8 +296,7 @@ lfs_fsync(v) * Take IN_ADIROP off, then call ufs_inactive. */ int -lfs_inactive(v) - void *v; +lfs_inactive(void *v) { struct vop_inactive_args /* { struct vnode *a_vp; @@ -327,12 +323,11 @@ lfs_inactive(v) * is decremented during segment write, when VDIROP is taken off. */ #define SET_DIROP(vp) lfs_set_dirop(vp) -static int lfs_set_dirop __P((struct vnode *)); +static int lfs_set_dirop(struct vnode *); extern int lfs_dirvcount; static int -lfs_set_dirop(vp) - struct vnode *vp; +lfs_set_dirop(struct vnode *vp) { struct lfs *fs; int error; @@ -342,7 +337,7 @@ lfs_set_dirop(vp) * We might need one directory block plus supporting indirect blocks, * plus an inode block and ifile page for the new vnode. */ - if ((error = lfs_reserve(fs, vp, fsbtodb(fs, NIADDR + 3))) != 0) + if ((error = lfs_reserve(fs, vp, btofsb(fs, (NIADDR + 3) << fs->lfs_bshift))) != 0) return (error); if (fs->lfs_dirops == 0) lfs_check(vp, LFS_UNUSED_LBN, 0); @@ -364,7 +359,7 @@ lfs_set_dirop(vp) #endif if((error = tsleep(&lfs_dirvcount, PCATCH|PUSER, "lfs_maxdirop", 0)) !=0) { - lfs_reserve(fs, vp, -fsbtodb(fs, NIADDR + 3)); + lfs_reserve(fs, vp, -btofsb(fs, (NIADDR + 3) << fs->lfs_bshift)); return error; } } @@ -388,7 +383,7 @@ lfs_set_dirop(vp) wakeup(&(fs)->lfs_writer); \ lfs_check((vp),LFS_UNUSED_LBN,0); \ } \ - lfs_reserve(fs, vp, -fsbtodb(fs, NIADDR + 3)); /* XXX */ \ + lfs_reserve((fs), vp, -btofsb((fs), (NIADDR + 3) << (fs)->lfs_bshift)); /* XXX */ \ lfs_vunref(vp); \ } @@ -406,8 +401,7 @@ lfs_set_dirop(vp) #define UNMARK_VNODE(vp) lfs_unmark_vnode(vp) -void lfs_unmark_vnode(vp) - struct vnode *vp; +void lfs_unmark_vnode(struct vnode *vp) { struct inode *ip; @@ -419,8 +413,7 @@ void lfs_unmark_vnode(vp) } int -lfs_symlink(v) - void *v; +lfs_symlink(void *v) { struct vop_symlink_args /* { struct vnode *a_dvp; @@ -445,8 +438,7 @@ lfs_symlink(v) } int -lfs_mknod(v) - void *v; +lfs_mknod(void *v) { struct vop_mknod_args /* { struct vnode *a_dvp; @@ -518,8 +510,7 @@ lfs_mknod(v) } int -lfs_create(v) - void *v; +lfs_create(void *v) { struct vop_create_args /* { struct vnode *a_dvp; @@ -543,8 +534,7 @@ lfs_create(v) } int -lfs_whiteout(v) - void *v; +lfs_whiteout(void *v) { struct vop_whiteout_args /* { struct vnode *a_dvp; @@ -564,8 +554,7 @@ lfs_whiteout(v) } int -lfs_mkdir(v) - void *v; +lfs_mkdir(void *v) { struct vop_mkdir_args /* { struct vnode *a_dvp; @@ -589,8 +578,7 @@ lfs_mkdir(v) } int -lfs_remove(v) - void *v; +lfs_remove(void *v) { struct vop_remove_args /* { struct vnode *a_dvp; @@ -632,8 +620,7 @@ lfs_remove(v) } int -lfs_rmdir(v) - void *v; +lfs_rmdir(void *v) { struct vop_rmdir_args /* { struct vnodeop_desc *a_desc; @@ -672,8 +659,7 @@ lfs_rmdir(v) } int -lfs_link(v) - void *v; +lfs_link(void *v) { struct vop_link_args /* { struct vnode *a_dvp; @@ -694,8 +680,7 @@ lfs_link(v) } int -lfs_rename(v) - void *v; +lfs_rename(void *v) { struct vop_rename_args /* { struct vnode *a_fdvp; @@ -754,8 +739,7 @@ lfs_rename(v) /* XXX hack to avoid calling ITIMES in getattr */ int -lfs_getattr(v) - void *v; +lfs_getattr(void *v) { struct vop_getattr_args /* { struct vnode *a_vp; @@ -766,6 +750,7 @@ lfs_getattr(v) struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); struct vattr *vap = ap->a_vap; + struct lfs *fs = ip->i_lfs; /* * Copy from inode table */ @@ -792,7 +777,7 @@ lfs_getattr(v) vap->va_blocksize = MAXBSIZE; else vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize; - vap->va_bytes = dbtob((u_quad_t)ip->i_ffs_blocks); + vap->va_bytes = fsbtob(fs, (u_quad_t)ip->i_ffs_blocks); vap->va_type = vp->v_type; vap->va_filerev = ip->i_modrev; return (0); @@ -807,8 +792,7 @@ lfs_getattr(v) */ /* ARGSUSED */ int -lfs_close(v) - void *v; +lfs_close(void *v) { struct vop_close_args /* { struct vnode *a_vp; @@ -835,8 +819,7 @@ lfs_close(v) int lfs_no_inactive = 0; int -lfs_reclaim(v) - void *v; +lfs_reclaim(void *v) { struct vop_reclaim_args /* { struct vnode *a_vp; diff --git a/sys/ufs/ufs/ufs_readwrite.c b/sys/ufs/ufs/ufs_readwrite.c index 9222905f4b3..b26971c935e 100644 --- a/sys/ufs/ufs/ufs_readwrite.c +++ b/sys/ufs/ufs/ufs_readwrite.c @@ -1,4 +1,4 @@ -/* $NetBSD: ufs_readwrite.c,v 1.31 2001/03/26 06:47:34 chs Exp $ */ +/* $NetBSD: ufs_readwrite.c,v 1.32 2001/07/13 20:30:26 perseant Exp $ */ /*- * Copyright (c) 1993 @@ -374,10 +374,10 @@ WRITE(void *v) } #ifdef LFS_READWRITE if (!error) - error = lfs_reserve(fs, vp, fsbtodb(fs, NIADDR + 1)); + error = lfs_reserve(fs, vp, btofsb(fs, (NIADDR + 1) << fs->lfs_bshift)); (void)VOP_BWRITE(bp); if (!error) - lfs_reserve(fs, vp, fsbtodb(fs, -(NIADDR + 1))); + lfs_reserve(fs, vp, -btofsb(fs, (NIADDR + 1) << fs->lfs_bshift)); #else if (ioflag & IO_SYNC) (void)bwrite(bp); diff --git a/usr.sbin/dumplfs/dumplfs.c b/usr.sbin/dumplfs/dumplfs.c index 74673dbfd90..39b8f063566 100644 --- a/usr.sbin/dumplfs/dumplfs.c +++ b/usr.sbin/dumplfs/dumplfs.c @@ -1,4 +1,4 @@ -/* $NetBSD: dumplfs.c,v 1.18 2001/01/05 03:27:26 lukem Exp $ */ +/* $NetBSD: dumplfs.c,v 1.19 2001/07/13 20:30:21 perseant Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -45,7 +45,7 @@ __COPYRIGHT( #if 0 static char sccsid[] = "@(#)dumplfs.c 8.5 (Berkeley) 5/24/95"; #else -__RCSID("$NetBSD: dumplfs.c,v 1.18 2001/01/05 03:27:26 lukem Exp $"); +__RCSID("$NetBSD: dumplfs.c,v 1.19 2001/07/13 20:30:21 perseant Exp $"); #endif #endif /* not lint */ @@ -67,20 +67,18 @@ __RCSID("$NetBSD: dumplfs.c,v 1.18 2001/01/05 03:27:26 lukem Exp $"); #include <unistd.h> #include "extern.h" -static void addseg __P((char *)); -static void dump_cleaner_info __P((struct lfs *, void *)); -static void dump_dinode __P((struct dinode *)); -static void dump_ifile __P((int, struct lfs *, int, int)); -static int dump_ipage_ifile __P((int, IFILE *, int)); -static int dump_ipage_segusage __P((struct lfs *, int, IFILE *, int)); -static void dump_segment __P((int, int, daddr_t, struct lfs *, int)); -static int dump_sum __P((int, struct lfs *, SEGSUM *, int, daddr_t)); -static void dump_super __P((struct lfs *)); -static void usage __P((void)); +static void addseg(char *); +static void dump_cleaner_info(struct lfs *, void *); +static void dump_dinode(struct dinode *); +static void dump_ifile(int, struct lfs *, int, int, int); +static int dump_ipage_ifile(struct lfs *, int, char *, int); +static int dump_ipage_segusage(struct lfs *, int, char *, int); +static void dump_segment(int, int, daddr_t, struct lfs *, int); +static int dump_sum(int, struct lfs *, SEGSUM *, int, daddr_t); +static void dump_super(struct lfs *); +static void usage(void); -int main __P((int, char *[])); - -extern u_long cksum __P((void *, size_t)); +extern u_long cksum(void *, size_t); typedef struct seglist SEGLIST; struct seglist { @@ -95,42 +93,40 @@ char *special; #define print_suheader \ (void)printf("segnum\tflags\tnbytes\tninos\tnsums\tlastmod\n") -#define print_suentry(i, sp) \ - (void)printf("%d\t%c%c%c\t%d\t%d\t%d\t%s", i, \ - (((sp)->su_flags & SEGUSE_ACTIVE) ? 'A' : ' '), \ - (((sp)->su_flags & SEGUSE_DIRTY) ? 'D' : 'C'), \ - (((sp)->su_flags & SEGUSE_SUPERBLOCK) ? 'S' : ' '), \ - (sp)->su_nbytes, (sp)->su_ninos, (sp)->su_nsums, \ - ctime((time_t *)&(sp)->su_lastmod)) +#define print_suentry(i, sp, fs) \ + (void)printf("%d\t%c%c%c\t%d\t%d\t%d\t%s", i, \ + (((sp)->su_flags & SEGUSE_ACTIVE) ? 'A' : ' '), \ + (((sp)->su_flags & SEGUSE_DIRTY) ? 'D' : 'C'), \ + (((sp)->su_flags & SEGUSE_SUPERBLOCK) ? 'S' : ' '), \ + (sp)->su_nbytes, (sp)->su_ninos, (sp)->su_nsums, \ + ((fs)->lfs_version == 1 ? ctime((time_t *)&(sp)->su_olastmod) : \ + ctime((time_t *)&(sp)->su_lastmod))) /* Ifile formats */ #define print_iheader \ (void)printf("inum\tstatus\tversion\tdaddr\t\tfreeptr\n") #define print_ientry(i, ip) \ - if (ip->if_daddr == LFS_UNUSED_DADDR) \ + if ((ip)->if_daddr == LFS_UNUSED_DADDR) \ (void)printf("%d\tFREE\t%d\t \t\t%d\n", \ - i, ip->if_version, ip->if_nextfree); \ + i, (ip)->if_version, (ip)->if_nextfree); \ else \ (void)printf("%d\tINUSE\t%d\t%8X \n", \ - i, ip->if_version, ip->if_daddr) - -#define datobyte(fs, da) /* disk address to bytes */ \ - (((off_t)(da)) << ((fs)->lfs_bshift - (fs)->lfs_fsbtodb)) + i, (ip)->if_version, (ip)->if_daddr) +#define fsbtobyte(fs, b) fsbtob((fs), (off_t)((b))) int -main(argc, argv) - int argc; - char *argv[]; +main(int argc, char **argv) { struct lfs lfs_sb1, lfs_sb2, *lfs_master; daddr_t seg_addr, idaddr, sbdaddr; - int ch, do_allsb, do_ientries, fd, segnum; + int ch, do_allsb, do_ientries, do_segentries, fd, segnum; do_allsb = 0; do_ientries = 0; + do_segentries = 0; idaddr = 0x0; sbdaddr = 0x0; - while ((ch = getopt(argc, argv, "ab:iI:s:")) != -1) + while ((ch = getopt(argc, argv, "ab:iI:Ss:")) != -1) switch(ch) { case 'a': /* Dump all superblocks */ do_allsb = 1; @@ -139,11 +135,14 @@ main(argc, argv) sbdaddr = strtol(optarg, NULL, 0); break; case 'i': /* Dump ifile entries */ - do_ientries = 1; + do_ientries = !do_ientries; break; case 'I': /* Use this ifile inode */ idaddr = strtol(optarg, NULL, 0); break; + case 'S': + do_segentries = !do_segentries; + break; case 's': /* Dump out these segments */ addseg(optarg); break; @@ -161,24 +160,37 @@ main(argc, argv) err(1, "%s", special); if (sbdaddr == 0x0) { - /* Read the first superblock */ + /* Read the proto-superblock */ get(fd, LFS_LABELPAD, &(lfs_sb1.lfs_dlfs), sizeof(struct dlfs)); + + /* If that wasn't the real first sb, get the real first sb */ + if (lfs_sb1.lfs_version > 1 && + lfs_sb1.lfs_sboffs[0] > btofsb(&lfs_sb1, LFS_LABELPAD)) + get(fd, fsbtob(&lfs_sb1, lfs_sb1.lfs_sboffs[0]), + &(lfs_sb1.lfs_dlfs), sizeof(struct dlfs)); /* * Read the second superblock and figure out which check point is * most up to date. */ get(fd, - datobyte(&lfs_sb1, lfs_sb1.lfs_sboffs[1]), + fsbtobyte(&lfs_sb1, lfs_sb1.lfs_sboffs[1]), &(lfs_sb2.lfs_dlfs), sizeof(struct dlfs)); lfs_master = &lfs_sb1; - if (lfs_sb1.lfs_tstamp > lfs_sb2.lfs_tstamp) { - lfs_master = &lfs_sb2; - sbdaddr = - btodb(datobyte(&lfs_sb1, lfs_sb1.lfs_sboffs[1])); - } else - sbdaddr = btodb(LFS_LABELPAD); + if (lfs_sb1.lfs_version > 1) { + if (lfs_sb1.lfs_serial > lfs_sb2.lfs_serial) { + lfs_master = &lfs_sb2; + sbdaddr = lfs_sb1.lfs_sboffs[1]; + } else + sbdaddr = lfs_sb1.lfs_sboffs[0]; + } else { + if (lfs_sb1.lfs_otstamp > lfs_sb2.lfs_otstamp) { + lfs_master = &lfs_sb2; + sbdaddr = lfs_sb1.lfs_sboffs[1]; + } else + sbdaddr = lfs_sb1.lfs_sboffs[0]; + } } else { /* Read the first superblock */ get(fd, dbtob((off_t)sbdaddr), &(lfs_sb1.lfs_dlfs), @@ -186,24 +198,32 @@ main(argc, argv) lfs_master = &lfs_sb1; } + /* Compatibility */ + if (lfs_master->lfs_version == 1) { + lfs_master->lfs_sumsize = LFS_V1_SUMMARY_SIZE; + lfs_master->lfs_ibsize = lfs_master->lfs_bsize; + lfs_master->lfs_start = lfs_master->lfs_sboffs[0]; + lfs_master->lfs_tstamp = lfs_master->lfs_otstamp; + lfs_master->lfs_fsbtodb = 0; + } + (void)printf("Master Superblock at 0x%x:\n", sbdaddr); dump_super(lfs_master); - dump_ifile(fd, lfs_master, do_ientries, idaddr); + dump_ifile(fd, lfs_master, do_ientries, do_segentries, idaddr); if (seglist != NULL) for (; seglist != NULL; seglist = seglist->next) { - seg_addr = lfs_master->lfs_sboffs[0] + seglist->num * - (lfs_master->lfs_ssize << lfs_master->lfs_fsbtodb); - dump_segment(fd, - seglist->num, seg_addr, lfs_master, do_allsb); + seg_addr = sntod(lfs_master, seglist->num); + dump_segment(fd, seglist->num, seg_addr, lfs_master, + do_allsb); } else - for (segnum = 0, seg_addr = lfs_master->lfs_sboffs[0]; - segnum < lfs_master->lfs_nseg; segnum++, seg_addr += - lfs_master->lfs_ssize << lfs_master->lfs_fsbtodb) - dump_segment(fd, - segnum, seg_addr, lfs_master, do_allsb); + for (segnum = 0, seg_addr = sntod(lfs_master, 0); + segnum < lfs_master->lfs_nseg; + segnum++, seg_addr = sntod(lfs_master, segnum)) + dump_segment(fd, segnum, seg_addr, lfs_master, + do_allsb); (void)close(fd); exit(0); @@ -215,13 +235,9 @@ main(argc, argv) * printed out rather than making this code incredibly efficient. */ static void -dump_ifile(fd, lfsp, do_ientries, addr) - int fd; - struct lfs *lfsp; - int do_ientries; - daddr_t addr; +dump_ifile(int fd, struct lfs *lfsp, int do_ientries, int do_segentries, daddr_t addr) { - IFILE *ipage; + char *ipage; struct dinode *dip, *dpage; daddr_t *addrp, *dindir, *iaddrp, *indir; int block_limit, i, inum, j, nblocks, psize; @@ -232,7 +248,7 @@ dump_ifile(fd, lfsp, do_ientries, addr) if (!(dpage = malloc(psize))) err(1, "malloc"); - get(fd, datobyte(lfsp, addr), dpage, psize); + get(fd, fsbtobyte(lfsp, addr), dpage, psize); for (dip = dpage + INOPB(lfsp) - 1; dip >= dpage; --dip) if (dip->di_inumber == LFS_IFILE_INUM) @@ -254,16 +270,20 @@ dump_ifile(fd, lfsp, do_ientries, addr) err(1, "malloc"); for (inum = 0, addrp = dip->di_db, i = 0; i < block_limit; i++, addrp++) { - get(fd, datobyte(lfsp, *addrp), ipage, psize); + get(fd, fsbtobyte(lfsp, *addrp), ipage, psize); if (i < lfsp->lfs_cleansz) { dump_cleaner_info(lfsp, ipage); - print_suheader; + if (do_segentries) + print_suheader; continue; } if (i < (lfsp->lfs_segtabsz + lfsp->lfs_cleansz)) { - inum = dump_ipage_segusage(lfsp, inum, ipage, - lfsp->lfs_sepb); + if (do_segentries) + inum = dump_ipage_segusage(lfsp, inum, ipage, + lfsp->lfs_sepb); + else + inum = (i < lfsp->lfs_segtabsz + lfsp->lfs_cleansz - 1); if (!inum) { if(!do_ientries) goto e0; @@ -271,8 +291,7 @@ dump_ifile(fd, lfsp, do_ientries, addr) print_iheader; } } else - inum = dump_ipage_ifile(inum, ipage, lfsp->lfs_ifpb); - + inum = dump_ipage_ifile(lfsp, inum, ipage, lfsp->lfs_ifpb); } if (nblocks <= NDADDR) @@ -281,21 +300,23 @@ dump_ifile(fd, lfsp, do_ientries, addr) /* Dump out blocks off of single indirect block */ if (!(indir = malloc(psize))) err(1, "malloc"); - get(fd, datobyte(lfsp, dip->di_ib[0]), indir, psize); + get(fd, fsbtobyte(lfsp, dip->di_ib[0]), indir, psize); block_limit = MIN(i + lfsp->lfs_nindir, nblocks); for (addrp = indir; i < block_limit; i++, addrp++) { if (*addrp == LFS_UNUSED_DADDR) break; - get(fd, datobyte(lfsp, *addrp), ipage, psize); + get(fd, fsbtobyte(lfsp, *addrp), ipage, psize); if (i < lfsp->lfs_cleansz) { dump_cleaner_info(lfsp, ipage); continue; - } else - i -= lfsp->lfs_cleansz; + } - if (i < lfsp->lfs_segtabsz) { - inum = dump_ipage_segusage(lfsp, inum, ipage, - lfsp->lfs_sepb); + if (i < lfsp->lfs_segtabsz + lfsp->lfs_cleansz) { + if (do_segentries) + inum = dump_ipage_segusage(lfsp, inum, ipage, + lfsp->lfs_sepb); + else + inum = (i < lfsp->lfs_segtabsz + lfsp->lfs_cleansz - 1); if (!inum) { if(!do_ientries) goto e1; @@ -303,7 +324,7 @@ dump_ifile(fd, lfsp, do_ientries, addr) print_iheader; } } else - inum = dump_ipage_ifile(inum, ipage, lfsp->lfs_ifpb); + inum = dump_ipage_ifile(lfsp, inum, ipage, lfsp->lfs_ifpb); } if (nblocks <= lfsp->lfs_nindir * lfsp->lfs_ifpb) @@ -312,25 +333,28 @@ dump_ifile(fd, lfsp, do_ientries, addr) /* Get the double indirect block */ if (!(dindir = malloc(psize))) err(1, "malloc"); - get(fd, datobyte(lfsp, dip->di_ib[1]), dindir, psize); + get(fd, fsbtobyte(lfsp, dip->di_ib[1]), dindir, psize); for (iaddrp = dindir, j = 0; j < lfsp->lfs_nindir; j++, iaddrp++) { if (*iaddrp == LFS_UNUSED_DADDR) break; - get(fd, datobyte(lfsp, *iaddrp), indir, psize); + get(fd, fsbtobyte(lfsp, *iaddrp), indir, psize); block_limit = MIN(i + lfsp->lfs_nindir, nblocks); for (addrp = indir; i < block_limit; i++, addrp++) { if (*addrp == LFS_UNUSED_DADDR) break; - get(fd, datobyte(lfsp, *addrp), ipage, psize); + get(fd, fsbtobyte(lfsp, *addrp), ipage, psize); if (i < lfsp->lfs_cleansz) { dump_cleaner_info(lfsp, ipage); continue; - } else - i -= lfsp->lfs_cleansz; + } - if (i < lfsp->lfs_segtabsz) { - inum = dump_ipage_segusage(lfsp, - inum, ipage, lfsp->lfs_sepb); + if (i < lfsp->lfs_segtabsz + lfsp->lfs_cleansz) { + if (do_segentries) + inum = dump_ipage_segusage(lfsp, + inum, ipage, lfsp->lfs_sepb); + else + inum = (i < lfsp->lfs_segtabsz + + lfsp->lfs_cleansz - 1); if (!inum) { if(!do_ientries) goto e2; @@ -338,7 +362,7 @@ dump_ifile(fd, lfsp, do_ientries, addr) print_iheader; } } else - inum = dump_ipage_ifile(inum, + inum = dump_ipage_ifile(lfsp, inum, ipage, lfsp->lfs_ifpb); } } @@ -349,27 +373,24 @@ e0: free(dpage); } static int -dump_ipage_ifile(i, pp, tot) - int i; - IFILE *pp; - int tot; +dump_ipage_ifile(struct lfs *lfsp, int i, char *pp, int tot) { - IFILE *ip; - int cnt, max; + char *ip; + int cnt, max, entsize; + if (lfsp->lfs_version == 1) + entsize = sizeof(IFILE_V1); + else + entsize = sizeof(IFILE); max = i + tot; - for (ip = pp, cnt = i; cnt < max; cnt++, ip++) - print_ientry(cnt, ip); + for (ip = pp, cnt = i; cnt < max; cnt++, ip += entsize) + print_ientry(cnt, (IFILE *)ip); return (max); } static int -dump_ipage_segusage(lfsp, i, pp, tot) - struct lfs *lfsp; - int i; - IFILE *pp; - int tot; +dump_ipage_segusage(struct lfs *lfsp, int i, char *pp, int tot) { SEGUSE *sp; int cnt, max; @@ -377,16 +398,20 @@ dump_ipage_segusage(lfsp, i, pp, tot) max = i + tot; for (sp = (SEGUSE *)pp, cnt = i; - cnt < lfsp->lfs_nseg && cnt < max; cnt++, sp++) { + cnt < lfsp->lfs_nseg && cnt < max; cnt++) { if (seglist == NULL) - print_suentry(cnt, sp); + print_suentry(cnt, sp, lfsp); else { for (slp = seglist; slp != NULL; slp = slp->next) if (cnt == slp->num) { - print_suentry(cnt, sp); + print_suentry(cnt, sp, lfsp); break; } } + if (lfsp->lfs_version > 1) + ++sp; + else + sp = (SEGUSE *)((SEGUSE_V1 *)sp + 1); } if (max >= lfsp->lfs_nseg) return (0); @@ -395,8 +420,7 @@ dump_ipage_segusage(lfsp, i, pp, tot) } static void -dump_dinode(dip) - struct dinode *dip; +dump_dinode(struct dinode *dip) { int i; time_t at, mt, ct; @@ -405,18 +429,18 @@ dump_dinode(dip) mt = dip->di_mtime; ct = dip->di_ctime; - (void)printf("%s%d\t%s%d\t%s%d\t%s%d\t%s%llu\n", + (void)printf(" %so%o\t%s%d\t%s%d\t%s%d\t%s%llu\n", "mode ", dip->di_mode, "nlink ", dip->di_nlink, "uid ", dip->di_uid, "gid ", dip->di_gid, "size ", (long long)dip->di_size); - (void)printf("%s%s%s%s%s%s", + (void)printf(" %s%s %s%s %s%s", "atime ", ctime(&at), "mtime ", ctime(&mt), "ctime ", ctime(&ct)); - (void)printf("inum %d\n", dip->di_inumber); - (void)printf("Direct Addresses\n"); + (void)printf(" inum %d\n", dip->di_inumber); + (void)printf(" Direct Addresses\n"); for (i = 0; i < NDADDR; i++) { (void)printf("\t0x%x", dip->di_db[i]); if ((i % 6) == 5) @@ -428,11 +452,7 @@ dump_dinode(dip) } static int -dump_sum(fd, lfsp, sp, segnum, addr) - struct lfs *lfsp; - SEGSUM *sp; - int fd, segnum; - daddr_t addr; +dump_sum(int fd, struct lfs *lfsp, SEGSUM *sp, int segnum, daddr_t addr) { FINFO *fp; daddr_t *dp; @@ -443,14 +463,20 @@ dump_sum(fd, lfsp, sp, segnum, addr) if (sp->ss_magic != SS_MAGIC || sp->ss_sumsum != (ck = cksum(&sp->ss_datasum, - LFS_SUMMARY_SIZE - sizeof(sp->ss_sumsum)))) { + lfsp->lfs_sumsize - sizeof(sp->ss_sumsum)))) { /* Don't print "corrupt" if we're just too close to the edge */ - if (datosn(lfsp, addr + fsbtodb(lfsp, lfsp->lfs_bsize)) == - datosn(lfsp, addr)) + if (dtosn(lfsp, addr + fsbtodb(lfsp, 1)) == + dtosn(lfsp, addr)) (void)printf("dumplfs: %s %d address 0x%x\n", "corrupt summary block; segment", segnum, addr); - return(0); + return (0); + } + if (lfsp->lfs_version > 1 && sp->ss_ident != lfsp->lfs_ident) { + (void)printf("dumplfs: %s %d address 0x%x\n", + "summary from a former life; segment", segnum, + addr); + return (0); } (void)printf("Segment Summary Info at 0x%x\n", addr); @@ -462,22 +488,28 @@ dump_sum(fd, lfsp, sp, segnum, addr) (sp->ss_flags & SS_CONT) ? 'C' : '-', "sumsum ", sp->ss_sumsum, "datasum ", sp->ss_datasum ); - (void)printf("\tcreate %s", ctime((time_t *)&sp->ss_create)); + if (lfsp->lfs_version == 1) + (void)printf("\tcreate %s\n", ctime((time_t *)&sp->ss_ident)); + else { + (void)printf("\tcreate %s", ctime((time_t *)&sp->ss_create)); + (void)printf(" roll_id %-8x", sp->ss_ident); + (void)printf(" serial %lld\n", (long long)sp->ss_serial); + } /* Dump out inode disk addresses */ dp = (daddr_t *)sp; - dp += LFS_SUMMARY_SIZE / sizeof(daddr_t); - inop = malloc(1 << lfsp->lfs_bshift); + dp += lfsp->lfs_sumsize / sizeof(daddr_t); + inop = malloc(lfsp->lfs_bsize); printf(" Inode addresses:"); numbytes = 0; for (dp--, i = 0; i < sp->ss_ninos; dp--) { - numbytes += lfsp->lfs_bsize; /* add bytes for inode block */ + numbytes += lfsp->lfs_ibsize; /* add bytes for inode block */ printf("\t0x%x {", *dp); - get(fd, datobyte(lfsp, *dp), inop, (1 << lfsp->lfs_bshift)); + get(fd, fsbtobyte(lfsp, *dp), inop, lfsp->lfs_ibsize); for (j = 0; i < sp->ss_ninos && j < INOPB(lfsp); j++, i++) { if (j > 0) (void)printf(", "); - (void)printf("%d", inop[j].di_inumber); + (void)printf("%dv%d", inop[j].di_inumber, inop[j].di_gen); } (void)printf("}"); if (((i/INOPB(lfsp)) % 4) == 3) @@ -486,7 +518,11 @@ dump_sum(fd, lfsp, sp, segnum, addr) free(inop); printf("\n"); - for (fp = (FINFO *)(sp + 1), i = 0; i < sp->ss_nfinfo; i++) { + if (lfsp->lfs_version == 1) + fp = (FINFO *)((SEGSUM_V1 *)sp + 1); + else + fp = (FINFO *)(sp + 1); + for (i = 0; i < sp->ss_nfinfo; i++) { (void)printf(" FINFO for inode: %d version %d nblocks %d lastlength %d\n", fp->fi_ino, fp->fi_version, fp->fi_nblocks, fp->fi_lastlength); @@ -508,61 +544,69 @@ dump_sum(fd, lfsp, sp, segnum, addr) } static void -dump_segment(fd, segnum, addr, lfsp, dump_sb) - int fd, segnum; - daddr_t addr; - struct lfs *lfsp; - int dump_sb; +dump_segment(int fd, int segnum, daddr_t addr, struct lfs *lfsp, int dump_sb) { struct lfs lfs_sb, *sbp; SEGSUM *sump; - char sumblock[LFS_SUMMARY_SIZE]; + char *sumblock; int did_one, nbytes, sb; off_t sum_offset; daddr_t new_addr; - (void)printf("\nSEGMENT %d (Disk Address 0x%x)\n", - /* addr >> (lfsp->lfs_segshift - daddr_shift), */ - datosn(lfsp, addr), - addr); - sum_offset = datobyte(lfsp, addr); + (void)printf("\nSEGMENT %d (Disk Address 0x%x)\n", dtosn(lfsp, addr), + addr); + sum_offset = fsbtobyte(lfsp, addr); + sumblock = malloc(lfsp->lfs_sumsize); + + if (lfsp->lfs_version > 1 && segnum == 0) { + /* First segment eats the label as well as the superblock */ + sum_offset += fragroundup(lfsp, LFS_LABELPAD); + addr += btofsb(lfsp, fragroundup(lfsp, LFS_LABELPAD)); + printf("Disklabel at 0x0\n"); + } sb = 0; did_one = 0; do { - get(fd, sum_offset, sumblock, LFS_SUMMARY_SIZE); + get(fd, sum_offset, sumblock, lfsp->lfs_sumsize); sump = (SEGSUM *)sumblock; - if (sump->ss_sumsum != cksum (&sump->ss_datasum, - LFS_SUMMARY_SIZE - sizeof(sump->ss_sumsum))) { + if ((lfsp->lfs_version > 1 && + sump->ss_ident != lfsp->lfs_ident) || + sump->ss_sumsum != cksum (&sump->ss_datasum, + lfsp->lfs_sumsize - sizeof(sump->ss_sumsum))) { sbp = (struct lfs *)sump; if ((sb = (sbp->lfs_magic == LFS_MAGIC))) { + printf("Superblock at 0x%x\n", + (unsigned)btofsb(lfsp, sum_offset)); if (dump_sb) { get(fd, sum_offset, &(lfs_sb.lfs_dlfs), sizeof(struct dlfs)); - (void)printf("\nSuperblock at 0x%x:\n", - (unsigned)btodb(sum_offset)); dump_super(&lfs_sb); - (void)printf("%s","\n"); } - sum_offset += LFS_SBPAD; + if (lfsp->lfs_version > 1) + sum_offset += fragroundup(lfsp, LFS_SBPAD); + else + sum_offset += LFS_SBPAD; } else if (did_one) break; else { - printf("Segment at 0x%x corrupt\n", addr); + printf("Segment at 0x%x empty or corrupt\n", + addr); break; } } else { - nbytes = dump_sum(fd, lfsp, sump, segnum, sum_offset >> - (lfsp->lfs_bshift - lfsp->lfs_fsbtodb)); + nbytes = dump_sum(fd, lfsp, sump, segnum, + btofsb(lfsp, sum_offset)); if (nbytes) - sum_offset += LFS_SUMMARY_SIZE + nbytes; + sum_offset += lfsp->lfs_sumsize + nbytes; else sum_offset = 0; did_one = 1; } /* If the segment ends right on a boundary, it still ends */ - new_addr = sum_offset >> (lfsp->lfs_bshift - lfsp->lfs_fsbtodb); - if (datosn(lfsp, new_addr) != datosn(lfsp, addr)) + new_addr = btofsb(lfsp, sum_offset); + /* printf("end daddr = 0x%lx\n", (long)new_addr); */ + if (dtosn(lfsp, new_addr) != dtosn(lfsp, addr)) break; } while (sum_offset); @@ -570,86 +614,89 @@ dump_segment(fd, segnum, addr, lfsp, dump_sb) } static void -dump_super(lfsp) - struct lfs *lfsp; +dump_super(struct lfs *lfsp) { int i; - (void)printf("%s0x%x\t%s0x%x\t%s%d\t%s%d\n", - "magic ", lfsp->lfs_magic, - "version ", lfsp->lfs_version, - "size ", lfsp->lfs_size, - "ssize ", lfsp->lfs_ssize); - (void)printf("%s%d\t\t%s%d\t%s%d\t%s%d\n", - "dsize ", lfsp->lfs_dsize, - "bsize ", lfsp->lfs_bsize, - "fsize ", lfsp->lfs_fsize, - "frag ", lfsp->lfs_frag); - - (void)printf("%s%d\t\t%s%d\t%s%d\t%s%d\n", - "minfree ", lfsp->lfs_minfree, - "inopb ", lfsp->lfs_inopb, - "ifpb ", lfsp->lfs_ifpb, - "nindir ", lfsp->lfs_nindir); - - (void)printf("%s%d\t\t%s%d\t%s%d\t%s%d\n", - "nseg ", lfsp->lfs_nseg, - "nspf ", lfsp->lfs_nspf, - "cleansz ", lfsp->lfs_cleansz, - "segtabsz ", lfsp->lfs_segtabsz); - - (void)printf("%s0x%x\t%s%d\t%s0x%llX\t%s%d\n", - "segmask ", lfsp->lfs_segmask, - "segshift ", lfsp->lfs_segshift, - "bmask ", (long long)lfsp->lfs_bmask, - "bshift ", lfsp->lfs_bshift); - - (void)printf("%s0x%llX\t\t%s%d\t%s0x%llX\t%s%u\n", - "ffmask ", (long long)lfsp->lfs_ffmask, - "ffshift ", lfsp->lfs_ffshift, - "fbmask ", (long long)lfsp->lfs_fbmask, - "fbshift ", lfsp->lfs_fbshift); - - (void)printf("%s%d\t%s%d\t%s0x%x\t%s0x%llx\n", - "sushift ", lfsp->lfs_sushift, - "fsbtodb ", lfsp->lfs_fsbtodb, - "cksum ", lfsp->lfs_cksum, - "maxfilesize ", (long long)lfsp->lfs_maxfilesize); - - (void)printf("%s%d\t%s%d\t%s%d\n", - "nclean ", lfsp->lfs_nclean, - "dmeta ", lfsp->lfs_dmeta, - "minfreeseg ", lfsp->lfs_minfreeseg); - - (void)printf("Superblock disk addresses:\t"); - for (i = 0; i < LFS_MAXNUMSB; i++) { - (void)printf(" 0x%x", lfsp->lfs_sboffs[i]); - if ( i == (LFS_MAXNUMSB >> 1)) - (void)printf("\n\t\t\t\t"); - } - (void)printf("\n"); - - (void)printf("Checkpoint Info\n"); - (void)printf("%s%d\t%s0x%x\t%s%d\n", - "free ", lfsp->lfs_free, - "idaddr ", lfsp->lfs_idaddr, - "ifile ", lfsp->lfs_ifile); - (void)printf("%s%d\t%s%d\t%s%d\n", - "uinodes ", lfsp->lfs_uinodes, - "bfree ", lfsp->lfs_bfree, - "avail ", lfsp->lfs_avail); - (void)printf("%s%d\t%s0x%x\t%s0x%x\n%s0x%x\t%s0x%x\t", - "nfiles ", lfsp->lfs_nfiles, - "lastseg ", lfsp->lfs_lastseg, - "nextseg ", lfsp->lfs_nextseg, - "curseg ", lfsp->lfs_curseg, - "offset ", lfsp->lfs_offset); - (void)printf("tstamp %s", ctime((time_t *)&lfsp->lfs_tstamp)); + (void)printf(" %s0x%-8x %s0x%-8x %s%-10d\n", + "magic ", lfsp->lfs_magic, + "version ", lfsp->lfs_version, + "size ", lfsp->lfs_size); + (void)printf(" %s%-10d %s%-10d %s%-10d\n", + "ssize ", lfsp->lfs_ssize, + "dsize ", lfsp->lfs_dsize, + "bsize ", lfsp->lfs_bsize); + (void)printf(" %s%-10d %s%-10d %s%-10d\n", + "fsize ", lfsp->lfs_fsize, + "frag ", lfsp->lfs_frag, + "minfree ", lfsp->lfs_minfree); + (void)printf(" %s%-10d %s%-10d %s%-10d\n", + "inopb ", lfsp->lfs_inopb, + "ifpb ", lfsp->lfs_ifpb, + "nindir ", lfsp->lfs_nindir); + (void)printf(" %s%-10d %s%-10d %s%-10d\n", + "nseg ", lfsp->lfs_nseg, + "sepb ", lfsp->lfs_sepb, + "cleansz ", lfsp->lfs_cleansz); + (void)printf(" %s%-10d %s0x%-8x %s%-10d\n", + "segtabsz ", lfsp->lfs_segtabsz, + "segmask ", lfsp->lfs_segmask, + "segshift ", lfsp->lfs_segshift); + (void)printf(" %s0x%-8qx %s%-10d %s0x%-8qX\n", + "bmask ", (long long)lfsp->lfs_bmask, + "bshift ", lfsp->lfs_bshift, + "ffmask ", (long long)lfsp->lfs_ffmask); + (void)printf(" %s%-10d %s0x%-8qx %s%u\n", + "ffshift ", lfsp->lfs_ffshift, + "fbmask ", (long long)lfsp->lfs_fbmask, + "fbshift ", lfsp->lfs_fbshift); + + (void)printf(" %s%-10d %s%-10d %s0x%-8x\n", + "sushift ", lfsp->lfs_sushift, + "fsbtodb ", lfsp->lfs_fsbtodb, + "cksum ", lfsp->lfs_cksum); + (void)printf(" %s%-10d %s%-10d %s%-10d\n", + "nclean ", lfsp->lfs_nclean, + "dmeta ", lfsp->lfs_dmeta, + "minfreeseg ", lfsp->lfs_minfreeseg); + (void)printf(" %s0x%-8x %s%-9d %s%-10d\n", + "roll_id ", lfsp->lfs_ident, + "interleave ", lfsp->lfs_interleave, + "sumsize ", lfsp->lfs_sumsize); + (void)printf(" %s0x%-8qx\n", + "maxfilesize ", (long long)lfsp->lfs_maxfilesize); + + + (void)printf(" Superblock disk addresses:\n "); + for (i = 0; i < LFS_MAXNUMSB; i++) { + (void)printf(" 0x%-8x", lfsp->lfs_sboffs[i]); + if (i == (LFS_MAXNUMSB >> 1)) + (void)printf("\n "); + } + (void)printf("\n"); + + (void)printf(" Checkpoint Info\n"); + (void)printf(" %s%-10d %s0x%-8x %s%-10d\n", + "free ", lfsp->lfs_free, + "idaddr ", lfsp->lfs_idaddr, + "ifile ", lfsp->lfs_ifile); + (void)printf(" %s%-10d %s%-10d %s%-10d\n", + "uinodes ", lfsp->lfs_uinodes, + "bfree ", lfsp->lfs_bfree, + "avail ", lfsp->lfs_avail); + (void)printf(" %s%-10d %s0x%-8x %s0x%-8x\n", + "nfiles ", lfsp->lfs_nfiles, + "lastseg ", lfsp->lfs_lastseg, + "nextseg ", lfsp->lfs_nextseg); + (void)printf(" %s0x%-8x %s0x%-8x %s%-10lld\n", + "curseg ", lfsp->lfs_curseg, + "offset ", lfsp->lfs_offset, + "serial ", (long long)lfsp->lfs_serial); + (void)printf(" tstamp %s", ctime((time_t *)&lfsp->lfs_tstamp)); } static void -addseg(arg) - char *arg; +addseg(char *arg) { SEGLIST *p; @@ -661,13 +708,15 @@ addseg(arg) } static void -dump_cleaner_info(lfsp, ipage) - struct lfs *lfsp; - void *ipage; +dump_cleaner_info(struct lfs *lfsp, void *ipage) { CLEANERINFO *cip; cip = (CLEANERINFO *)ipage; + if (lfsp->lfs_version > 1) { + (void)printf("free_head %d\n", cip->free_head); + (void)printf("free_tail %d\n", cip->free_tail); + } (void)printf("clean\t%d\tdirty\t%d\n", cip->clean, cip->dirty); (void)printf("bfree\t%d\tavail\t%d\n\n", @@ -675,8 +724,8 @@ dump_cleaner_info(lfsp, ipage) } static void -usage() +usage(void) { - (void)fprintf(stderr, "usage: dumplfs [-ai] [-s segnum] file\n"); + (void)fprintf(stderr, "usage: dumplfs [-aiS] [-b daddr] [-I daddr] [-s segnum] file\n"); exit(1); } diff --git a/usr.sbin/dumplfs/extern.h b/usr.sbin/dumplfs/extern.h index b6ea7a9b0b3..64fe5038b1b 100644 --- a/usr.sbin/dumplfs/extern.h +++ b/usr.sbin/dumplfs/extern.h @@ -1,4 +1,4 @@ -/* $NetBSD: extern.h,v 1.4 1998/03/01 02:26:12 fvdl Exp $ */ +/* $NetBSD: extern.h,v 1.5 2001/07/13 20:30:21 perseant Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -35,6 +35,6 @@ * @(#)extern.h 8.2 (Berkeley) 4/28/95 */ -void get __P((int, off_t, void *, size_t)); +void get(int, off_t, void *, size_t); extern char *special; diff --git a/usr.sbin/dumplfs/misc.c b/usr.sbin/dumplfs/misc.c index 325ffeb0da3..aa52b595dd2 100644 --- a/usr.sbin/dumplfs/misc.c +++ b/usr.sbin/dumplfs/misc.c @@ -1,4 +1,4 @@ -/* $NetBSD: misc.c,v 1.5 1998/03/03 07:35:50 thorpej Exp $ */ +/* $NetBSD: misc.c,v 1.6 2001/07/13 20:30:21 perseant Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -39,7 +39,7 @@ #if 0 static char sccsid[] = "@(#)misc.c 8.2 (Berkeley) 4/28/95"; #else -__RCSID("$NetBSD: misc.c,v 1.5 1998/03/03 07:35:50 thorpej Exp $"); +__RCSID("$NetBSD: misc.c,v 1.6 2001/07/13 20:30:21 perseant Exp $"); #endif #endif /* not lint */ @@ -54,11 +54,7 @@ __RCSID("$NetBSD: misc.c,v 1.5 1998/03/03 07:35:50 thorpej Exp $"); #include "extern.h" void -get(fd, off, p, len) - int fd; - off_t off; - void *p; - size_t len; +get(int fd, off_t off, void *p, size_t len) { int rbytes; |
