155860Sbostic /*- 255860Sbostic * Copyright (c) 1992 The Regents of the University of California. 355860Sbostic * All rights reserved. 455860Sbostic * 555860Sbostic * %sccs.include.redist.c% 655860Sbostic */ 755860Sbostic 855860Sbostic #ifndef lint 9*60095Sbostic static char sccsid[] = "@(#)library.c 5.9 (Berkeley) 05/17/93"; 1055860Sbostic #endif /* not lint */ 1155860Sbostic 1255491Sbostic #include <sys/param.h> 1355491Sbostic #include <sys/time.h> 1455491Sbostic #include <sys/stat.h> 1555491Sbostic #include <sys/mount.h> 1657201Smargo #include <sys/types.h> 1757201Smargo #include <sys/mman.h> 1855491Sbostic 1955491Sbostic #include <ufs/ufs/dinode.h> 2055491Sbostic #include <ufs/lfs/lfs.h> 2155491Sbostic 2255491Sbostic #include <fcntl.h> 2355491Sbostic #include <stdio.h> 2455856Sbostic #include <stdlib.h> 2555856Sbostic #include <string.h> 26*60095Sbostic #include <unistd.h> 27*60095Sbostic 2855491Sbostic #include "clean.h" 2955491Sbostic 3055856Sbostic void add_blocks __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t, 3155856Sbostic daddr_t, daddr_t)); 3255930Sbostic void add_inodes __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t, 3355856Sbostic daddr_t)); 3455856Sbostic int bi_compare __P((const void *, const void *)); 3555856Sbostic int bi_toss __P((const void *, const void *, const void *)); 3657201Smargo void get_ifile __P((FS_INFO *, int)); 3755856Sbostic int get_superblock __P((FS_INFO *, struct lfs *)); 3855856Sbostic int pseg_valid __P((FS_INFO *, SEGSUM *)); 3955856Sbostic 4055491Sbostic /* 4155856Sbostic * This function will get information on all mounted file systems 4255491Sbostic * of a given type. 4355491Sbostic */ 4455491Sbostic int 4555491Sbostic fs_getmntinfo(buf, type) 4655491Sbostic struct statfs **buf; 4755491Sbostic int type; 4855491Sbostic { 4955856Sbostic struct statfs *tstatfsp; 5055856Sbostic struct statfs *sbp; 5155856Sbostic int count, i, tcount; 5255491Sbostic 5355863Sbostic tcount = getmntinfo(&tstatfsp, MNT_NOWAIT); 5455491Sbostic 5555491Sbostic if (tcount < 0) { 5655856Sbostic err(0, "getmntinfo failed"); 5755856Sbostic return (-1); 5855491Sbostic } 5955491Sbostic 6055856Sbostic for (count = 0, i = 0; i < tcount ; ++i) 6155856Sbostic if (tstatfsp[i].f_type == type) 6255856Sbostic ++count; 6355491Sbostic 6455856Sbostic if (count) { 6555856Sbostic if (!(*buf = (struct statfs *) 6655856Sbostic malloc(count * sizeof(struct statfs)))) 6755856Sbostic err(1, "fs_getmntinfo: out of space"); 6855856Sbostic for (i = 0, sbp = *buf; i < tcount ; ++i) { 6955856Sbostic if (tstatfsp[i].f_type == type) { 7055856Sbostic *sbp = tstatfsp[i]; 7155856Sbostic ++sbp; 7255491Sbostic } 7355491Sbostic } 7455491Sbostic } 7555856Sbostic return (count); 7655491Sbostic } 7755491Sbostic 7855491Sbostic /* 7955856Sbostic * Get all the information available on an LFS file system. 8055856Sbostic * Returns an array of FS_INFO structures, NULL on error. 8155491Sbostic */ 8255856Sbostic FS_INFO * 8357201Smargo get_fs_info (lstatfsp, count, use_mmap) 8455856Sbostic struct statfs *lstatfsp; /* IN: array of statfs structs */ 8555856Sbostic int count; /* IN: number of file systems */ 8657201Smargo int use_mmap; /* IN: mmap or read */ 8755491Sbostic { 8855856Sbostic FS_INFO *fp, *fsp; 8955491Sbostic int i; 9055491Sbostic 9157201Smargo fsp = (FS_INFO *)calloc(count, sizeof(FS_INFO)); 9255491Sbostic 9355856Sbostic for (fp = fsp, i = 0; i < count; ++i, ++fp) { 9455856Sbostic fp->fi_statfsp = lstatfsp++; 9555856Sbostic if (get_superblock (fp, &fp->fi_lfs)) 9655856Sbostic err(1, "get_fs_info: get_superblock failed"); 9755856Sbostic fp->fi_daddr_shift = 9855856Sbostic fp->fi_lfs.lfs_bshift - fp->fi_lfs.lfs_fsbtodb; 9957201Smargo get_ifile (fp, use_mmap); 10055491Sbostic } 10155856Sbostic return (fsp); 10255491Sbostic } 10355491Sbostic 10455856Sbostic /* 10555856Sbostic * If we are reading the ifile then we need to refresh it. Even if 10655856Sbostic * we are mmapping it, it might have grown. Finally, we need to 10755856Sbostic * refresh the file system information (statfs) info. 10855856Sbostic */ 10955491Sbostic void 11057201Smargo reread_fs_info(fsp, count, use_mmap) 11155856Sbostic FS_INFO *fsp; /* IN: array of fs_infos to free */ 11255856Sbostic int count; /* IN: number of file systems */ 113*60095Sbostic int use_mmap; 11455491Sbostic { 11555856Sbostic int i; 11655491Sbostic 11755856Sbostic for (i = 0; i < count; ++i, ++fsp) { 11855856Sbostic if (statfs(fsp->fi_statfsp->f_mntonname, fsp->fi_statfsp)) 11955856Sbostic err(0, "reread_fs_info: statfs failed"); 12057201Smargo get_ifile (fsp, use_mmap); 12155491Sbostic } 12255491Sbostic } 12355491Sbostic 12455491Sbostic /* 12555856Sbostic * Gets the superblock from disk (possibly in face of errors) 12655491Sbostic */ 12755491Sbostic int 12855491Sbostic get_superblock (fsp, sbp) 12955856Sbostic FS_INFO *fsp; /* local file system info structure */ 13055856Sbostic struct lfs *sbp; 13155491Sbostic { 13255856Sbostic char mntfromname[MNAMELEN+1]; 13355856Sbostic int fid; 13455491Sbostic 13555491Sbostic strcpy(mntfromname, "/dev/r"); 13655856Sbostic strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5); 13755491Sbostic 13855491Sbostic if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) { 13955856Sbostic err(0, "get_superblock: bad open"); 14055856Sbostic return (-1); 14155491Sbostic } 14255491Sbostic 14355856Sbostic get(fid, LFS_LABELPAD, sbp, sizeof(struct lfs)); 14455491Sbostic close (fid); 14555491Sbostic 14655856Sbostic return (0); 14755491Sbostic } 14855491Sbostic 14955491Sbostic /* 15055856Sbostic * This function will map the ifile into memory. It causes a 15155856Sbostic * fatal error on failure. 15255491Sbostic */ 15355856Sbostic void 15457201Smargo get_ifile (fsp, use_mmap) 15555491Sbostic FS_INFO *fsp; 15657201Smargo int use_mmap; 15757201Smargo 15855491Sbostic { 15955856Sbostic struct stat file_stat; 16055856Sbostic caddr_t ifp; 16155856Sbostic char *ifile_name; 16255856Sbostic int count, fid; 16355491Sbostic 16455856Sbostic ifp = NULL; 16555856Sbostic ifile_name = malloc(strlen(fsp->fi_statfsp->f_mntonname) + 16655856Sbostic strlen(IFILE_NAME)+2); 16755856Sbostic strcat(strcat(strcpy(ifile_name, fsp->fi_statfsp->f_mntonname), "/"), 16855856Sbostic IFILE_NAME); 16955491Sbostic 17055856Sbostic if ((fid = open(ifile_name, O_RDWR, (mode_t)0)) < 0) 17155856Sbostic err(1, "get_ifile: bad open"); 17255491Sbostic 17355856Sbostic if (fstat (fid, &file_stat)) 17455856Sbostic err(1, "get_ifile: fstat failed"); 17555491Sbostic 17657201Smargo if (use_mmap && file_stat.st_size == fsp->fi_ifile_length) { 17757201Smargo (void) close(fid); 17857201Smargo return; 17957201Smargo } 18055856Sbostic 18155491Sbostic /* get the ifile */ 18257201Smargo if (use_mmap) { 18357201Smargo if (fsp->fi_cip) 18457201Smargo munmap((caddr_t)fsp->fi_cip, fsp->fi_ifile_length); 18557201Smargo ifp = mmap ((caddr_t)0, file_stat.st_size, 18657201Smargo PROT_READ|PROT_WRITE, 0, fid, (off_t)0); 18757201Smargo if (ifp == (caddr_t)(-1)) 18857201Smargo err(1, "get_ifile: mmap failed"); 18957201Smargo } else { 19057201Smargo if (fsp->fi_cip) 19157201Smargo free(fsp->fi_cip); 19257201Smargo if (!(ifp = malloc (file_stat.st_size))) 19357201Smargo err (1, "get_ifile: malloc failed"); 19455856Sbostic redo_read: 19557201Smargo count = read (fid, ifp, (size_t) file_stat.st_size); 19655491Sbostic 19757201Smargo if (count < 0) 19857201Smargo err(1, "get_ifile: bad ifile read"); 19957201Smargo else if (count < file_stat.st_size) { 20057201Smargo err(0, "get_ifile"); 20157201Smargo if (lseek(fid, 0, SEEK_SET) < 0) 20257201Smargo err(1, "get_ifile: bad ifile lseek"); 20357201Smargo goto redo_read; 20457201Smargo } 20555491Sbostic } 20657201Smargo fsp->fi_ifile_length = file_stat.st_size; 20755491Sbostic close (fid); 20855491Sbostic 20955856Sbostic fsp->fi_cip = (CLEANERINFO *)ifp; 21055856Sbostic fsp->fi_segusep = (SEGUSE *)(ifp + CLEANSIZE(fsp)); 21155856Sbostic fsp->fi_ifilep = (IFILE *)((caddr_t)fsp->fi_segusep + SEGTABSIZE(fsp)); 21255856Sbostic 21355856Sbostic /* 21455856Sbostic * The number of ifile entries is equal to the number of blocks 21555856Sbostic * blocks in the ifile minus the ones allocated to cleaner info 21655856Sbostic * and segment usage table multiplied by the number of ifile 21755856Sbostic * entries per page. 21855856Sbostic */ 21955856Sbostic fsp->fi_ifile_count = (fsp->fi_ifile_length >> fsp->fi_lfs.lfs_bshift - 22055856Sbostic fsp->fi_lfs.lfs_cleansz - fsp->fi_lfs.lfs_segtabsz) * 22155856Sbostic fsp->fi_lfs.lfs_ifpb; 22255856Sbostic 22355491Sbostic free (ifile_name); 22455491Sbostic } 22555491Sbostic 22655491Sbostic /* 22755856Sbostic * This function will scan a segment and return a list of 22855491Sbostic * <inode, blocknum> pairs which indicate which blocks were 22955856Sbostic * contained as live data within the segment when the segment 23055856Sbostic * summary was read (it may have "died" since then). Any given 23155856Sbostic * pair will be listed at most once. 23255491Sbostic */ 23355491Sbostic int 23455930Sbostic lfs_segmapv(fsp, seg, seg_buf, blocks, bcount) 23555856Sbostic FS_INFO *fsp; /* pointer to local file system information */ 23655856Sbostic int seg; /* the segment number */ 23755856Sbostic caddr_t seg_buf; /* the buffer containing the segment's data */ 23855856Sbostic BLOCK_INFO **blocks; /* OUT: array of block_info for live blocks */ 23955856Sbostic int *bcount; /* OUT: number of active blocks in segment */ 24055491Sbostic { 24155856Sbostic BLOCK_INFO *bip; 24255856Sbostic SEGSUM *sp; 24355856Sbostic SEGUSE *sup; 24456623Smargo FINFO *fip; 24555856Sbostic struct lfs *lfsp; 24655856Sbostic caddr_t s, segend; 24755856Sbostic daddr_t pseg_addr, seg_addr; 24856623Smargo int i, nelem, nblocks, sumsize; 24955856Sbostic time_t timestamp; 25055491Sbostic 25155856Sbostic lfsp = &fsp->fi_lfs; 25255930Sbostic nelem = 2 * lfsp->lfs_ssize; 25355930Sbostic if (!(bip = malloc(nelem * sizeof(BLOCK_INFO)))) 25455856Sbostic goto err0; 25555491Sbostic 25655856Sbostic sup = SEGUSE_ENTRY(lfsp, fsp->fi_segusep, seg); 25755856Sbostic s = seg_buf + (sup->su_flags & SEGUSE_SUPERBLOCK ? LFS_SBPAD : 0); 25855856Sbostic seg_addr = sntoda(lfsp, seg); 25955856Sbostic pseg_addr = seg_addr + (sup->su_flags & SEGUSE_SUPERBLOCK ? btodb(LFS_SBPAD) : 0); 26055856Sbostic #ifdef VERBOSE 26155856Sbostic printf("\tsegment buffer at: 0x%x\tseg_addr 0x%x\n", s, seg_addr); 26255856Sbostic #endif /* VERBOSE */ 26355491Sbostic 26455856Sbostic *bcount = 0; 26555856Sbostic for (segend = seg_buf + seg_size(lfsp), timestamp = 0; s < segend; ) { 26655856Sbostic sp = (SEGSUM *)s; 26756623Smargo 26855491Sbostic #ifdef VERBOSE 26955856Sbostic printf("\tpartial at: 0x%x\n", pseg_addr); 27055856Sbostic print_SEGSUM(lfsp, sp); 27155491Sbostic fflush(stdout); 27255491Sbostic #endif /* VERBOSE */ 27355491Sbostic 27455856Sbostic nblocks = pseg_valid(fsp, sp); 27555856Sbostic if (nblocks <= 0) 27655856Sbostic break; 27755491Sbostic 27855856Sbostic /* Check if we have hit old data */ 27955856Sbostic if (timestamp > ((SEGSUM*)s)->ss_create) 28055856Sbostic break; 28155491Sbostic timestamp = ((SEGSUM*)s)->ss_create; 28255491Sbostic 28356623Smargo #ifdef DIAGNOSTIC 28456623Smargo /* Verfiy size of summary block */ 28556623Smargo sumsize = sizeof(SEGSUM) + 28656623Smargo (sp->ss_ninos + INOPB(lfsp) - 1) / INOPB(lfsp); 28756623Smargo for (fip = (FINFO *)(sp + 1); i < sp->ss_nfinfo; ++i) { 28856623Smargo sumsize += sizeof(FINFO) + 28956623Smargo (fip->fi_nblocks - 1) * sizeof(daddr_t); 29056623Smargo fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks]); 29156623Smargo } 29256623Smargo if (sumsize > LFS_SUMMARY_SIZE) { 29356623Smargo fprintf(stderr, 29456623Smargo "Segment %d summary block too big: %d\n", 29556623Smargo seg, sumsize); 29656623Smargo exit(1); 29756623Smargo } 29856623Smargo #endif 29956623Smargo 30055930Sbostic if (*bcount + nblocks + sp->ss_ninos > nelem) { 30155930Sbostic nelem = *bcount + nblocks + sp->ss_ninos; 30255930Sbostic bip = realloc (bip, nelem * sizeof(BLOCK_INFO)); 30355930Sbostic if (!bip) 30455930Sbostic goto err0; 30555856Sbostic } 30655856Sbostic add_blocks(fsp, bip, bcount, sp, seg_buf, seg_addr, pseg_addr); 30755930Sbostic add_inodes(fsp, bip, bcount, sp, seg_buf, seg_addr); 30855856Sbostic pseg_addr += fsbtodb(lfsp, nblocks) + 30955856Sbostic bytetoda(fsp, LFS_SUMMARY_SIZE); 31055856Sbostic s += (nblocks << lfsp->lfs_bshift) + LFS_SUMMARY_SIZE; 31155856Sbostic } 31255856Sbostic qsort(bip, *bcount, sizeof(BLOCK_INFO), bi_compare); 31355856Sbostic toss(bip, bcount, sizeof(BLOCK_INFO), bi_toss, NULL); 31455856Sbostic #ifdef VERBOSE 31555856Sbostic { 31655856Sbostic BLOCK_INFO *_bip; 31755856Sbostic int i; 31855491Sbostic 31955856Sbostic printf("BLOCK INFOS\n"); 32055856Sbostic for (_bip = bip, i=0; i < *bcount; ++_bip, ++i) 32155856Sbostic PRINT_BINFO(_bip); 32255491Sbostic } 32355856Sbostic #endif 32455856Sbostic *blocks = bip; 32555856Sbostic return (0); 32655856Sbostic 32755856Sbostic err0: *bcount = 0; 32855856Sbostic return (-1); 32955491Sbostic 33055491Sbostic } 33155491Sbostic 33255491Sbostic /* 33355856Sbostic * This will parse a partial segment and fill in BLOCK_INFO structures 33455856Sbostic * for each block described in the segment summary. It will not include 33555856Sbostic * blocks or inodes from files with new version numbers. 33655491Sbostic */ 33755491Sbostic void 33855856Sbostic add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr) 33955491Sbostic FS_INFO *fsp; /* pointer to super block */ 34055856Sbostic BLOCK_INFO *bip; /* Block info array */ 34155856Sbostic int *countp; /* IN/OUT: number of blocks in array */ 34255856Sbostic SEGSUM *sp; /* segment summmary pointer */ 34355856Sbostic caddr_t seg_buf; /* buffer containing segment */ 34455856Sbostic daddr_t segaddr; /* address of this segment */ 34555856Sbostic daddr_t psegaddr; /* address of this partial segment */ 34655491Sbostic { 34755856Sbostic IFILE *ifp; 34855856Sbostic FINFO *fip; 34955856Sbostic caddr_t bp; 35055930Sbostic daddr_t *dp, *iaddrp; 35155856Sbostic int db_per_block, i, j; 35255856Sbostic u_long page_size; 35355491Sbostic 35455491Sbostic #ifdef VERBOSE 35555856Sbostic printf("FILE INFOS\n"); 35655491Sbostic #endif 35755856Sbostic db_per_block = fsbtodb(&fsp->fi_lfs, 1); 35855856Sbostic page_size = fsp->fi_lfs.lfs_bsize; 35955856Sbostic bp = seg_buf + datobyte(fsp, psegaddr - segaddr) + LFS_SUMMARY_SIZE; 36055856Sbostic bip += *countp; 36155856Sbostic psegaddr += bytetoda(fsp, LFS_SUMMARY_SIZE); 36255856Sbostic iaddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE); 36355856Sbostic --iaddrp; 36455856Sbostic for (fip = (FINFO *)(sp + 1), i = 0; i < sp->ss_nfinfo; 36555856Sbostic ++i, fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks])) { 36655491Sbostic 36755856Sbostic ifp = IFILE_ENTRY(&fsp->fi_lfs, fsp->fi_ifilep, fip->fi_ino); 36855856Sbostic PRINT_FINFO(fip, ifp); 36955856Sbostic if (ifp->if_version > fip->fi_version) 37055491Sbostic continue; 37155856Sbostic dp = &(fip->fi_blocks[0]); 37255856Sbostic for (j = 0; j < fip->fi_nblocks; j++, dp++) { 37355856Sbostic while (psegaddr == *iaddrp) { 37455856Sbostic psegaddr += db_per_block; 37555856Sbostic bp += page_size; 37655856Sbostic --iaddrp; 37755491Sbostic } 37855856Sbostic bip->bi_inode = fip->fi_ino; 37955856Sbostic bip->bi_lbn = *dp; 38055856Sbostic bip->bi_daddr = psegaddr; 38155856Sbostic bip->bi_segcreate = (time_t)(sp->ss_create); 38255856Sbostic bip->bi_bp = bp; 38356193Smargo bip->bi_version = ifp->if_version; 38455856Sbostic psegaddr += db_per_block; 38555856Sbostic bp += page_size; 38655856Sbostic ++bip; 38755856Sbostic ++(*countp); 38855491Sbostic } 38955491Sbostic } 39055491Sbostic } 39155491Sbostic 39255856Sbostic /* 39355856Sbostic * For a particular segment summary, reads the inode blocks and adds 39455856Sbostic * INODE_INFO structures to the array. Returns the number of inodes 39555856Sbostic * actually added. 39655856Sbostic */ 39755491Sbostic void 39855930Sbostic add_inodes (fsp, bip, countp, sp, seg_buf, seg_addr) 39955491Sbostic FS_INFO *fsp; /* pointer to super block */ 40055930Sbostic BLOCK_INFO *bip; /* block info array */ 40155856Sbostic int *countp; /* pointer to current number of inodes */ 40255856Sbostic SEGSUM *sp; /* segsum pointer */ 40355491Sbostic caddr_t seg_buf; /* the buffer containing the segment's data */ 40455856Sbostic daddr_t seg_addr; /* disk address of seg_buf */ 40555491Sbostic { 40655856Sbostic struct dinode *di; 40755856Sbostic struct lfs *lfsp; 40855856Sbostic IFILE *ifp; 40955930Sbostic BLOCK_INFO *bp; 41055856Sbostic daddr_t *daddrp; 41155856Sbostic ino_t inum; 41255856Sbostic int i; 41355491Sbostic 41455856Sbostic if (sp->ss_ninos <= 0) 41555856Sbostic return; 41655491Sbostic 41755930Sbostic bp = bip + *countp; 41855856Sbostic lfsp = &fsp->fi_lfs; 41955491Sbostic #ifdef VERBOSE 42055930Sbostic (void) printf("INODES:\n"); 42155491Sbostic #endif 42255856Sbostic daddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE); 42355856Sbostic for (i = 0; i < sp->ss_ninos; ++i) { 42455491Sbostic if (i % INOPB(lfsp) == 0) { 42555856Sbostic --daddrp; 42655856Sbostic di = (struct dinode *)(seg_buf + 42755856Sbostic ((*daddrp - seg_addr) << fsp->fi_daddr_shift)); 42855491Sbostic } else 42955491Sbostic ++di; 43055491Sbostic 43157201Smargo inum = di->di_inumber; 43255930Sbostic bp->bi_lbn = LFS_UNUSED_LBN; 43355930Sbostic bp->bi_inode = inum; 43455930Sbostic bp->bi_daddr = *daddrp; 43555930Sbostic bp->bi_bp = di; 43655930Sbostic bp->bi_segcreate = sp->ss_create; 43755491Sbostic 43856036Sbostic if (inum == LFS_IFILE_INUM) { 43956193Smargo bp->bi_version = 1; /* Ifile version should be 1 */ 44055930Sbostic bp++; 44155856Sbostic ++(*countp); 44256036Sbostic PRINT_INODE(1, bp); 44356036Sbostic } else { 44456036Sbostic ifp = IFILE_ENTRY(lfsp, fsp->fi_ifilep, inum); 44556036Sbostic PRINT_INODE(ifp->if_daddr == *daddrp, bp); 44656193Smargo bp->bi_version = ifp->if_version; 44756036Sbostic if (ifp->if_daddr == *daddrp) { 44856036Sbostic bp++; 44956036Sbostic ++(*countp); 45056036Sbostic } 45156036Sbostic } 45255491Sbostic } 45355491Sbostic } 45455491Sbostic 45555491Sbostic /* 45655856Sbostic * Checks the summary checksum and the data checksum to determine if the 45755856Sbostic * segment is valid or not. Returns the size of the partial segment if it 45855856Sbostic * is valid, * and 0 otherwise. Use dump_summary to figure out size of the 45955856Sbostic * the partial as well as whether or not the checksum is valid. 46055491Sbostic */ 46155491Sbostic int 46255491Sbostic pseg_valid (fsp, ssp) 46355491Sbostic FS_INFO *fsp; /* pointer to file system info */ 46455856Sbostic SEGSUM *ssp; /* pointer to segment summary block */ 46555491Sbostic { 46655491Sbostic caddr_t p; 46755856Sbostic int i, nblocks; 46855856Sbostic u_long *datap; 46955491Sbostic 47056655Sbostic if ((nblocks = dump_summary(&fsp->fi_lfs, ssp, 0, NULL)) <= 0 || 47156655Sbostic nblocks > fsp->fi_lfs.lfs_ssize - 1) 47255856Sbostic return(0); 47355491Sbostic 47455856Sbostic /* check data/inode block(s) checksum too */ 47555856Sbostic datap = (u_long *)malloc(nblocks * sizeof(u_long)); 47655491Sbostic p = (caddr_t)ssp + LFS_SUMMARY_SIZE; 47755856Sbostic for (i = 0; i < nblocks; ++i) { 47855491Sbostic datap[i] = *((u_long *)p); 47955856Sbostic p += fsp->fi_lfs.lfs_bsize; 48055491Sbostic } 48155856Sbostic if (cksum ((void *)datap, nblocks * sizeof(u_long)) != ssp->ss_datasum) 48255856Sbostic return (0); 48355491Sbostic 48455856Sbostic return (nblocks); 48555491Sbostic } 48655491Sbostic 48755491Sbostic 48855491Sbostic /* #define MMAP_SEGMENT */ 48955491Sbostic /* 49055491Sbostic * read a segment into a memory buffer 49155491Sbostic */ 49255491Sbostic int 49357201Smargo mmap_segment (fsp, segment, segbuf, use_mmap) 49455856Sbostic FS_INFO *fsp; /* file system information */ 49555856Sbostic int segment; /* segment number */ 49655856Sbostic caddr_t *segbuf; /* pointer to buffer area */ 49757201Smargo int use_mmap; /* mmap instead of read */ 49855491Sbostic { 49955856Sbostic struct lfs *lfsp; 50055856Sbostic int fid; /* fildes for file system device */ 50155856Sbostic daddr_t seg_daddr; /* base disk address of segment */ 50255856Sbostic off_t seg_byte; 50355856Sbostic size_t ssize; 50455856Sbostic char mntfromname[MNAMELEN+2]; 50555491Sbostic 50655856Sbostic lfsp = &fsp->fi_lfs; 50755856Sbostic 50855491Sbostic /* get the disk address of the beginning of the segment */ 50955491Sbostic seg_daddr = sntoda(lfsp, segment); 51055856Sbostic seg_byte = datobyte(fsp, seg_daddr); 51155856Sbostic ssize = seg_size(lfsp); 51255491Sbostic 51355491Sbostic strcpy(mntfromname, "/dev/r"); 51455856Sbostic strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5); 51555491Sbostic 51655491Sbostic if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) { 51755856Sbostic err(0, "mmap_segment: bad open"); 51855856Sbostic return (-1); 51955491Sbostic } 52055491Sbostic 52157201Smargo if (use_mmap) { 52257201Smargo *segbuf = mmap ((caddr_t)0, seg_size(lfsp), PROT_READ, 52357201Smargo 0, fid, seg_byte); 52457201Smargo if (*(long *)segbuf < 0) { 52557201Smargo err(0, "mmap_segment: mmap failed"); 52657201Smargo return (NULL); 52757201Smargo } 52857201Smargo } else { 52955856Sbostic #ifdef VERBOSE 53057201Smargo printf("mmap_segment\tseg_daddr: %lu\tseg_size: %lu\tseg_offset: %qu\n", 53157201Smargo seg_daddr, ssize, seg_byte); 53255856Sbostic #endif 53357201Smargo /* malloc the space for the buffer */ 53457201Smargo *segbuf = malloc(ssize); 53557201Smargo if (!*segbuf) { 53657201Smargo err(0, "mmap_segment: malloc failed"); 53757201Smargo return(NULL); 53857201Smargo } 53955491Sbostic 54057201Smargo /* read the segment data into the buffer */ 54157201Smargo if (lseek (fid, seg_byte, SEEK_SET) != seg_byte) { 54257201Smargo err (0, "mmap_segment: bad lseek"); 54357201Smargo free(*segbuf); 54457201Smargo return (-1); 54557201Smargo } 54657201Smargo 54757201Smargo if (read (fid, *segbuf, ssize) != ssize) { 54857201Smargo err (0, "mmap_segment: bad read"); 54957201Smargo free(*segbuf); 55057201Smargo return (-1); 55157201Smargo } 55255491Sbostic } 55355491Sbostic close (fid); 55455491Sbostic 55555856Sbostic return (0); 55655491Sbostic } 55755491Sbostic 55855491Sbostic void 55957201Smargo munmap_segment (fsp, seg_buf, use_mmap) 56055856Sbostic FS_INFO *fsp; /* file system information */ 56155856Sbostic caddr_t seg_buf; /* pointer to buffer area */ 56257201Smargo int use_mmap; /* mmap instead of read/write */ 56355491Sbostic { 56457201Smargo if (use_mmap) 56557201Smargo munmap (seg_buf, seg_size(&fsp->fi_lfs)); 56657201Smargo else 56757201Smargo free (seg_buf); 56855491Sbostic } 56955491Sbostic 57055491Sbostic 57155491Sbostic /* 57255491Sbostic * USEFUL DEBUGGING TOOLS: 57355491Sbostic */ 57455491Sbostic void 57555856Sbostic print_SEGSUM (lfsp, p) 57655856Sbostic struct lfs *lfsp; 57755856Sbostic SEGSUM *p; 57855491Sbostic { 57955856Sbostic if (p) 58055856Sbostic (void) dump_summary(lfsp, p, DUMP_ALL, NULL); 58155491Sbostic else printf("0x0"); 58255491Sbostic fflush(stdout); 58355491Sbostic } 58455491Sbostic 58555856Sbostic int 58655856Sbostic bi_compare(a, b) 58755856Sbostic const void *a; 58855856Sbostic const void *b; 58955491Sbostic { 59055856Sbostic const BLOCK_INFO *ba, *bb; 59155856Sbostic int diff; 59255491Sbostic 59355856Sbostic ba = a; 59455856Sbostic bb = b; 59555491Sbostic 59655856Sbostic if (diff = (int)(ba->bi_inode - bb->bi_inode)) 59755856Sbostic return (diff); 59855930Sbostic if (diff = (int)(ba->bi_lbn - bb->bi_lbn)) { 59955930Sbostic if (ba->bi_lbn == LFS_UNUSED_LBN) 60055930Sbostic return(-1); 60155930Sbostic else if (bb->bi_lbn == LFS_UNUSED_LBN) 60255930Sbostic return(1); 60356623Smargo else if (ba->bi_lbn < 0 && bb->bi_lbn >= 0) 60455930Sbostic return(1); 60556623Smargo else if (bb->bi_lbn < 0 && ba->bi_lbn >= 0) 60656623Smargo return(-1); 60755930Sbostic else 60855930Sbostic return (diff); 60955930Sbostic } 61055856Sbostic if (diff = (int)(ba->bi_segcreate - bb->bi_segcreate)) 61155856Sbostic return (diff); 61255856Sbostic diff = (int)(ba->bi_daddr - bb->bi_daddr); 61355856Sbostic return (diff); 61455856Sbostic } 61555491Sbostic 61655856Sbostic int 61755856Sbostic bi_toss(dummy, a, b) 61855856Sbostic const void *dummy; 61955856Sbostic const void *a; 62055856Sbostic const void *b; 62155491Sbostic { 62255856Sbostic const BLOCK_INFO *ba, *bb; 62355491Sbostic 62455856Sbostic ba = a; 62555856Sbostic bb = b; 62655856Sbostic 62755856Sbostic return(ba->bi_inode == bb->bi_inode && ba->bi_lbn == bb->bi_lbn); 62855491Sbostic } 62955491Sbostic 63055491Sbostic void 63155856Sbostic toss(p, nump, size, dotoss, client) 63255856Sbostic void *p; 63355856Sbostic int *nump; 63455856Sbostic size_t size; 63555856Sbostic int (*dotoss) __P((const void *, const void *, const void *)); 63655856Sbostic void *client; 63755491Sbostic { 63855856Sbostic int i; 63955856Sbostic void *p1; 64055491Sbostic 64155856Sbostic if (*nump == 0) 64255856Sbostic return; 64355491Sbostic 64455856Sbostic for (i = *nump; --i > 0;) { 64555856Sbostic p1 = p + size; 64655856Sbostic if (dotoss(client, p, p1)) { 647*60095Sbostic memmove(p, p1, i * size); 64855856Sbostic --(*nump); 64955856Sbostic } else 65055856Sbostic p += size; 65155491Sbostic } 65255491Sbostic } 653