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*57201Smargo static char sccsid[] = "@(#)library.c 5.8 (Berkeley) 12/18/92"; 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> 16*57201Smargo #include <sys/types.h> 17*57201Smargo #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> 2455491Sbostic #include <unistd.h> 2555856Sbostic #include <stdlib.h> 2655856Sbostic #include <string.h> 2755491Sbostic #include "clean.h" 2855491Sbostic 2955856Sbostic void add_blocks __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t, 3055856Sbostic daddr_t, daddr_t)); 3155930Sbostic void add_inodes __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t, 3255856Sbostic daddr_t)); 3355856Sbostic int bi_compare __P((const void *, const void *)); 3455856Sbostic int bi_toss __P((const void *, const void *, const void *)); 35*57201Smargo void get_ifile __P((FS_INFO *, int)); 3655856Sbostic int get_superblock __P((FS_INFO *, struct lfs *)); 3755856Sbostic int pseg_valid __P((FS_INFO *, SEGSUM *)); 3855856Sbostic 3955491Sbostic /* 4055856Sbostic * This function will get information on all mounted file systems 4155491Sbostic * of a given type. 4255491Sbostic */ 4355491Sbostic int 4455491Sbostic fs_getmntinfo(buf, type) 4555491Sbostic struct statfs **buf; 4655491Sbostic int type; 4755491Sbostic { 4855856Sbostic struct statfs *tstatfsp; 4955856Sbostic struct statfs *sbp; 5055856Sbostic int count, i, tcount; 5155491Sbostic 5255863Sbostic tcount = getmntinfo(&tstatfsp, MNT_NOWAIT); 5355491Sbostic 5455491Sbostic if (tcount < 0) { 5555856Sbostic err(0, "getmntinfo failed"); 5655856Sbostic return (-1); 5755491Sbostic } 5855491Sbostic 5955856Sbostic for (count = 0, i = 0; i < tcount ; ++i) 6055856Sbostic if (tstatfsp[i].f_type == type) 6155856Sbostic ++count; 6255491Sbostic 6355856Sbostic if (count) { 6455856Sbostic if (!(*buf = (struct statfs *) 6555856Sbostic malloc(count * sizeof(struct statfs)))) 6655856Sbostic err(1, "fs_getmntinfo: out of space"); 6755856Sbostic for (i = 0, sbp = *buf; i < tcount ; ++i) { 6855856Sbostic if (tstatfsp[i].f_type == type) { 6955856Sbostic *sbp = tstatfsp[i]; 7055856Sbostic ++sbp; 7155491Sbostic } 7255491Sbostic } 7355491Sbostic } 7455856Sbostic return (count); 7555491Sbostic } 7655491Sbostic 7755491Sbostic /* 7855856Sbostic * Get all the information available on an LFS file system. 7955856Sbostic * Returns an array of FS_INFO structures, NULL on error. 8055491Sbostic */ 8155856Sbostic FS_INFO * 82*57201Smargo get_fs_info (lstatfsp, count, use_mmap) 8355856Sbostic struct statfs *lstatfsp; /* IN: array of statfs structs */ 8455856Sbostic int count; /* IN: number of file systems */ 85*57201Smargo int use_mmap; /* IN: mmap or read */ 8655491Sbostic { 8755856Sbostic FS_INFO *fp, *fsp; 8855491Sbostic int i; 8955491Sbostic 90*57201Smargo fsp = (FS_INFO *)calloc(count, sizeof(FS_INFO)); 9155491Sbostic 9255856Sbostic for (fp = fsp, i = 0; i < count; ++i, ++fp) { 9355856Sbostic fp->fi_statfsp = lstatfsp++; 9455856Sbostic if (get_superblock (fp, &fp->fi_lfs)) 9555856Sbostic err(1, "get_fs_info: get_superblock failed"); 9655856Sbostic fp->fi_daddr_shift = 9755856Sbostic fp->fi_lfs.lfs_bshift - fp->fi_lfs.lfs_fsbtodb; 98*57201Smargo get_ifile (fp, use_mmap); 9955491Sbostic } 10055856Sbostic return (fsp); 10155491Sbostic } 10255491Sbostic 10355856Sbostic /* 10455856Sbostic * If we are reading the ifile then we need to refresh it. Even if 10555856Sbostic * we are mmapping it, it might have grown. Finally, we need to 10655856Sbostic * refresh the file system information (statfs) info. 10755856Sbostic */ 10855491Sbostic void 109*57201Smargo reread_fs_info(fsp, count, use_mmap) 11055856Sbostic FS_INFO *fsp; /* IN: array of fs_infos to free */ 11155856Sbostic int count; /* IN: number of file systems */ 11255491Sbostic { 11355856Sbostic int i; 11455491Sbostic 11555856Sbostic for (i = 0; i < count; ++i, ++fsp) { 11655856Sbostic if (statfs(fsp->fi_statfsp->f_mntonname, fsp->fi_statfsp)) 11755856Sbostic err(0, "reread_fs_info: statfs failed"); 118*57201Smargo get_ifile (fsp, use_mmap); 11955491Sbostic } 12055491Sbostic } 12155491Sbostic 12255491Sbostic /* 12355856Sbostic * Gets the superblock from disk (possibly in face of errors) 12455491Sbostic */ 12555491Sbostic int 12655491Sbostic get_superblock (fsp, sbp) 12755856Sbostic FS_INFO *fsp; /* local file system info structure */ 12855856Sbostic struct lfs *sbp; 12955491Sbostic { 13055856Sbostic char mntfromname[MNAMELEN+1]; 13155856Sbostic int fid; 13255491Sbostic 13355491Sbostic strcpy(mntfromname, "/dev/r"); 13455856Sbostic strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5); 13555491Sbostic 13655491Sbostic if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) { 13755856Sbostic err(0, "get_superblock: bad open"); 13855856Sbostic return (-1); 13955491Sbostic } 14055491Sbostic 14155856Sbostic get(fid, LFS_LABELPAD, sbp, sizeof(struct lfs)); 14255491Sbostic close (fid); 14355491Sbostic 14455856Sbostic return (0); 14555491Sbostic } 14655491Sbostic 14755491Sbostic /* 14855856Sbostic * This function will map the ifile into memory. It causes a 14955856Sbostic * fatal error on failure. 15055491Sbostic */ 15155856Sbostic void 152*57201Smargo get_ifile (fsp, use_mmap) 15355491Sbostic FS_INFO *fsp; 154*57201Smargo int use_mmap; 155*57201Smargo 15655491Sbostic { 15755856Sbostic struct stat file_stat; 15855856Sbostic caddr_t ifp; 15955856Sbostic char *ifile_name; 16055856Sbostic int count, fid; 16155491Sbostic 16255856Sbostic ifp = NULL; 16355856Sbostic ifile_name = malloc(strlen(fsp->fi_statfsp->f_mntonname) + 16455856Sbostic strlen(IFILE_NAME)+2); 16555856Sbostic strcat(strcat(strcpy(ifile_name, fsp->fi_statfsp->f_mntonname), "/"), 16655856Sbostic IFILE_NAME); 16755491Sbostic 16855856Sbostic if ((fid = open(ifile_name, O_RDWR, (mode_t)0)) < 0) 16955856Sbostic err(1, "get_ifile: bad open"); 17055491Sbostic 17155856Sbostic if (fstat (fid, &file_stat)) 17255856Sbostic err(1, "get_ifile: fstat failed"); 17355491Sbostic 174*57201Smargo if (use_mmap && file_stat.st_size == fsp->fi_ifile_length) { 175*57201Smargo (void) close(fid); 176*57201Smargo return; 177*57201Smargo } 17855856Sbostic 17955491Sbostic /* get the ifile */ 180*57201Smargo if (use_mmap) { 181*57201Smargo if (fsp->fi_cip) 182*57201Smargo munmap((caddr_t)fsp->fi_cip, fsp->fi_ifile_length); 183*57201Smargo ifp = mmap ((caddr_t)0, file_stat.st_size, 184*57201Smargo PROT_READ|PROT_WRITE, 0, fid, (off_t)0); 185*57201Smargo if (ifp == (caddr_t)(-1)) 186*57201Smargo err(1, "get_ifile: mmap failed"); 187*57201Smargo } else { 188*57201Smargo if (fsp->fi_cip) 189*57201Smargo free(fsp->fi_cip); 190*57201Smargo if (!(ifp = malloc (file_stat.st_size))) 191*57201Smargo err (1, "get_ifile: malloc failed"); 19255856Sbostic redo_read: 193*57201Smargo count = read (fid, ifp, (size_t) file_stat.st_size); 19455491Sbostic 195*57201Smargo if (count < 0) 196*57201Smargo err(1, "get_ifile: bad ifile read"); 197*57201Smargo else if (count < file_stat.st_size) { 198*57201Smargo err(0, "get_ifile"); 199*57201Smargo if (lseek(fid, 0, SEEK_SET) < 0) 200*57201Smargo err(1, "get_ifile: bad ifile lseek"); 201*57201Smargo goto redo_read; 202*57201Smargo } 20355491Sbostic } 204*57201Smargo fsp->fi_ifile_length = file_stat.st_size; 20555491Sbostic close (fid); 20655491Sbostic 20755856Sbostic fsp->fi_cip = (CLEANERINFO *)ifp; 20855856Sbostic fsp->fi_segusep = (SEGUSE *)(ifp + CLEANSIZE(fsp)); 20955856Sbostic fsp->fi_ifilep = (IFILE *)((caddr_t)fsp->fi_segusep + SEGTABSIZE(fsp)); 21055856Sbostic 21155856Sbostic /* 21255856Sbostic * The number of ifile entries is equal to the number of blocks 21355856Sbostic * blocks in the ifile minus the ones allocated to cleaner info 21455856Sbostic * and segment usage table multiplied by the number of ifile 21555856Sbostic * entries per page. 21655856Sbostic */ 21755856Sbostic fsp->fi_ifile_count = (fsp->fi_ifile_length >> fsp->fi_lfs.lfs_bshift - 21855856Sbostic fsp->fi_lfs.lfs_cleansz - fsp->fi_lfs.lfs_segtabsz) * 21955856Sbostic fsp->fi_lfs.lfs_ifpb; 22055856Sbostic 22155491Sbostic free (ifile_name); 22255491Sbostic } 22355491Sbostic 22455491Sbostic /* 22555856Sbostic * This function will scan a segment and return a list of 22655491Sbostic * <inode, blocknum> pairs which indicate which blocks were 22755856Sbostic * contained as live data within the segment when the segment 22855856Sbostic * summary was read (it may have "died" since then). Any given 22955856Sbostic * pair will be listed at most once. 23055491Sbostic */ 23155491Sbostic int 23255930Sbostic lfs_segmapv(fsp, seg, seg_buf, blocks, bcount) 23355856Sbostic FS_INFO *fsp; /* pointer to local file system information */ 23455856Sbostic int seg; /* the segment number */ 23555856Sbostic caddr_t seg_buf; /* the buffer containing the segment's data */ 23655856Sbostic BLOCK_INFO **blocks; /* OUT: array of block_info for live blocks */ 23755856Sbostic int *bcount; /* OUT: number of active blocks in segment */ 23855491Sbostic { 23955856Sbostic BLOCK_INFO *bip; 24055856Sbostic SEGSUM *sp; 24155856Sbostic SEGUSE *sup; 24256623Smargo FINFO *fip; 24355856Sbostic struct lfs *lfsp; 24455856Sbostic caddr_t s, segend; 24555856Sbostic daddr_t pseg_addr, seg_addr; 24656623Smargo int i, nelem, nblocks, sumsize; 24755856Sbostic time_t timestamp; 24855491Sbostic 24955856Sbostic lfsp = &fsp->fi_lfs; 25055930Sbostic nelem = 2 * lfsp->lfs_ssize; 25155930Sbostic if (!(bip = malloc(nelem * sizeof(BLOCK_INFO)))) 25255856Sbostic goto err0; 25355491Sbostic 25455856Sbostic sup = SEGUSE_ENTRY(lfsp, fsp->fi_segusep, seg); 25555856Sbostic s = seg_buf + (sup->su_flags & SEGUSE_SUPERBLOCK ? LFS_SBPAD : 0); 25655856Sbostic seg_addr = sntoda(lfsp, seg); 25755856Sbostic pseg_addr = seg_addr + (sup->su_flags & SEGUSE_SUPERBLOCK ? btodb(LFS_SBPAD) : 0); 25855856Sbostic #ifdef VERBOSE 25955856Sbostic printf("\tsegment buffer at: 0x%x\tseg_addr 0x%x\n", s, seg_addr); 26055856Sbostic #endif /* VERBOSE */ 26155491Sbostic 26255856Sbostic *bcount = 0; 26355856Sbostic for (segend = seg_buf + seg_size(lfsp), timestamp = 0; s < segend; ) { 26455856Sbostic sp = (SEGSUM *)s; 26556623Smargo 26655491Sbostic #ifdef VERBOSE 26755856Sbostic printf("\tpartial at: 0x%x\n", pseg_addr); 26855856Sbostic print_SEGSUM(lfsp, sp); 26955491Sbostic fflush(stdout); 27055491Sbostic #endif /* VERBOSE */ 27155491Sbostic 27255856Sbostic nblocks = pseg_valid(fsp, sp); 27355856Sbostic if (nblocks <= 0) 27455856Sbostic break; 27555491Sbostic 27655856Sbostic /* Check if we have hit old data */ 27755856Sbostic if (timestamp > ((SEGSUM*)s)->ss_create) 27855856Sbostic break; 27955491Sbostic timestamp = ((SEGSUM*)s)->ss_create; 28055491Sbostic 28156623Smargo #ifdef DIAGNOSTIC 28256623Smargo /* Verfiy size of summary block */ 28356623Smargo sumsize = sizeof(SEGSUM) + 28456623Smargo (sp->ss_ninos + INOPB(lfsp) - 1) / INOPB(lfsp); 28556623Smargo for (fip = (FINFO *)(sp + 1); i < sp->ss_nfinfo; ++i) { 28656623Smargo sumsize += sizeof(FINFO) + 28756623Smargo (fip->fi_nblocks - 1) * sizeof(daddr_t); 28856623Smargo fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks]); 28956623Smargo } 29056623Smargo if (sumsize > LFS_SUMMARY_SIZE) { 29156623Smargo fprintf(stderr, 29256623Smargo "Segment %d summary block too big: %d\n", 29356623Smargo seg, sumsize); 29456623Smargo exit(1); 29556623Smargo } 29656623Smargo #endif 29756623Smargo 29855930Sbostic if (*bcount + nblocks + sp->ss_ninos > nelem) { 29955930Sbostic nelem = *bcount + nblocks + sp->ss_ninos; 30055930Sbostic bip = realloc (bip, nelem * sizeof(BLOCK_INFO)); 30155930Sbostic if (!bip) 30255930Sbostic goto err0; 30355856Sbostic } 30455856Sbostic add_blocks(fsp, bip, bcount, sp, seg_buf, seg_addr, pseg_addr); 30555930Sbostic add_inodes(fsp, bip, bcount, sp, seg_buf, seg_addr); 30655856Sbostic pseg_addr += fsbtodb(lfsp, nblocks) + 30755856Sbostic bytetoda(fsp, LFS_SUMMARY_SIZE); 30855856Sbostic s += (nblocks << lfsp->lfs_bshift) + LFS_SUMMARY_SIZE; 30955856Sbostic } 31055856Sbostic qsort(bip, *bcount, sizeof(BLOCK_INFO), bi_compare); 31155856Sbostic toss(bip, bcount, sizeof(BLOCK_INFO), bi_toss, NULL); 31255856Sbostic #ifdef VERBOSE 31355856Sbostic { 31455856Sbostic BLOCK_INFO *_bip; 31555856Sbostic int i; 31655491Sbostic 31755856Sbostic printf("BLOCK INFOS\n"); 31855856Sbostic for (_bip = bip, i=0; i < *bcount; ++_bip, ++i) 31955856Sbostic PRINT_BINFO(_bip); 32055491Sbostic } 32155856Sbostic #endif 32255856Sbostic *blocks = bip; 32355856Sbostic return (0); 32455856Sbostic 32555856Sbostic err0: *bcount = 0; 32655856Sbostic return (-1); 32755491Sbostic 32855491Sbostic } 32955491Sbostic 33055491Sbostic /* 33155856Sbostic * This will parse a partial segment and fill in BLOCK_INFO structures 33255856Sbostic * for each block described in the segment summary. It will not include 33355856Sbostic * blocks or inodes from files with new version numbers. 33455491Sbostic */ 33555491Sbostic void 33655856Sbostic add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr) 33755491Sbostic FS_INFO *fsp; /* pointer to super block */ 33855856Sbostic BLOCK_INFO *bip; /* Block info array */ 33955856Sbostic int *countp; /* IN/OUT: number of blocks in array */ 34055856Sbostic SEGSUM *sp; /* segment summmary pointer */ 34155856Sbostic caddr_t seg_buf; /* buffer containing segment */ 34255856Sbostic daddr_t segaddr; /* address of this segment */ 34355856Sbostic daddr_t psegaddr; /* address of this partial segment */ 34455491Sbostic { 34555856Sbostic IFILE *ifp; 34655856Sbostic FINFO *fip; 34755856Sbostic caddr_t bp; 34855930Sbostic daddr_t *dp, *iaddrp; 34955856Sbostic int db_per_block, i, j; 35055856Sbostic u_long page_size; 35155491Sbostic 35255491Sbostic #ifdef VERBOSE 35355856Sbostic printf("FILE INFOS\n"); 35455491Sbostic #endif 35555856Sbostic db_per_block = fsbtodb(&fsp->fi_lfs, 1); 35655856Sbostic page_size = fsp->fi_lfs.lfs_bsize; 35755856Sbostic bp = seg_buf + datobyte(fsp, psegaddr - segaddr) + LFS_SUMMARY_SIZE; 35855856Sbostic bip += *countp; 35955856Sbostic psegaddr += bytetoda(fsp, LFS_SUMMARY_SIZE); 36055856Sbostic iaddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE); 36155856Sbostic --iaddrp; 36255856Sbostic for (fip = (FINFO *)(sp + 1), i = 0; i < sp->ss_nfinfo; 36355856Sbostic ++i, fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks])) { 36455491Sbostic 36555856Sbostic ifp = IFILE_ENTRY(&fsp->fi_lfs, fsp->fi_ifilep, fip->fi_ino); 36655856Sbostic PRINT_FINFO(fip, ifp); 36755856Sbostic if (ifp->if_version > fip->fi_version) 36855491Sbostic continue; 36955856Sbostic dp = &(fip->fi_blocks[0]); 37055856Sbostic for (j = 0; j < fip->fi_nblocks; j++, dp++) { 37155856Sbostic while (psegaddr == *iaddrp) { 37255856Sbostic psegaddr += db_per_block; 37355856Sbostic bp += page_size; 37455856Sbostic --iaddrp; 37555491Sbostic } 37655856Sbostic bip->bi_inode = fip->fi_ino; 37755856Sbostic bip->bi_lbn = *dp; 37855856Sbostic bip->bi_daddr = psegaddr; 37955856Sbostic bip->bi_segcreate = (time_t)(sp->ss_create); 38055856Sbostic bip->bi_bp = bp; 38156193Smargo bip->bi_version = ifp->if_version; 38255856Sbostic psegaddr += db_per_block; 38355856Sbostic bp += page_size; 38455856Sbostic ++bip; 38555856Sbostic ++(*countp); 38655491Sbostic } 38755491Sbostic } 38855491Sbostic } 38955491Sbostic 39055856Sbostic /* 39155856Sbostic * For a particular segment summary, reads the inode blocks and adds 39255856Sbostic * INODE_INFO structures to the array. Returns the number of inodes 39355856Sbostic * actually added. 39455856Sbostic */ 39555491Sbostic void 39655930Sbostic add_inodes (fsp, bip, countp, sp, seg_buf, seg_addr) 39755491Sbostic FS_INFO *fsp; /* pointer to super block */ 39855930Sbostic BLOCK_INFO *bip; /* block info array */ 39955856Sbostic int *countp; /* pointer to current number of inodes */ 40055856Sbostic SEGSUM *sp; /* segsum pointer */ 40155491Sbostic caddr_t seg_buf; /* the buffer containing the segment's data */ 40255856Sbostic daddr_t seg_addr; /* disk address of seg_buf */ 40355491Sbostic { 40455856Sbostic struct dinode *di; 40555856Sbostic struct lfs *lfsp; 40655856Sbostic IFILE *ifp; 40755930Sbostic BLOCK_INFO *bp; 40855856Sbostic daddr_t *daddrp; 40955856Sbostic ino_t inum; 41055856Sbostic int i; 41155491Sbostic 41255856Sbostic if (sp->ss_ninos <= 0) 41355856Sbostic return; 41455491Sbostic 41555930Sbostic bp = bip + *countp; 41655856Sbostic lfsp = &fsp->fi_lfs; 41755491Sbostic #ifdef VERBOSE 41855930Sbostic (void) printf("INODES:\n"); 41955491Sbostic #endif 42055856Sbostic daddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE); 42155856Sbostic for (i = 0; i < sp->ss_ninos; ++i) { 42255491Sbostic if (i % INOPB(lfsp) == 0) { 42355856Sbostic --daddrp; 42455856Sbostic di = (struct dinode *)(seg_buf + 42555856Sbostic ((*daddrp - seg_addr) << fsp->fi_daddr_shift)); 42655491Sbostic } else 42755491Sbostic ++di; 42855491Sbostic 429*57201Smargo inum = di->di_inumber; 43055930Sbostic bp->bi_lbn = LFS_UNUSED_LBN; 43155930Sbostic bp->bi_inode = inum; 43255930Sbostic bp->bi_daddr = *daddrp; 43355930Sbostic bp->bi_bp = di; 43455930Sbostic bp->bi_segcreate = sp->ss_create; 43555491Sbostic 43656036Sbostic if (inum == LFS_IFILE_INUM) { 43756193Smargo bp->bi_version = 1; /* Ifile version should be 1 */ 43855930Sbostic bp++; 43955856Sbostic ++(*countp); 44056036Sbostic PRINT_INODE(1, bp); 44156036Sbostic } else { 44256036Sbostic ifp = IFILE_ENTRY(lfsp, fsp->fi_ifilep, inum); 44356036Sbostic PRINT_INODE(ifp->if_daddr == *daddrp, bp); 44456193Smargo bp->bi_version = ifp->if_version; 44556036Sbostic if (ifp->if_daddr == *daddrp) { 44656036Sbostic bp++; 44756036Sbostic ++(*countp); 44856036Sbostic } 44956036Sbostic } 45055491Sbostic } 45155491Sbostic } 45255491Sbostic 45355491Sbostic /* 45455856Sbostic * Checks the summary checksum and the data checksum to determine if the 45555856Sbostic * segment is valid or not. Returns the size of the partial segment if it 45655856Sbostic * is valid, * and 0 otherwise. Use dump_summary to figure out size of the 45755856Sbostic * the partial as well as whether or not the checksum is valid. 45855491Sbostic */ 45955491Sbostic int 46055491Sbostic pseg_valid (fsp, ssp) 46155491Sbostic FS_INFO *fsp; /* pointer to file system info */ 46255856Sbostic SEGSUM *ssp; /* pointer to segment summary block */ 46355491Sbostic { 46455491Sbostic caddr_t p; 46555856Sbostic int i, nblocks; 46655856Sbostic u_long *datap; 46756623Smargo SEGUSE *sup; 46855491Sbostic 46956655Sbostic if ((nblocks = dump_summary(&fsp->fi_lfs, ssp, 0, NULL)) <= 0 || 47056655Sbostic nblocks > fsp->fi_lfs.lfs_ssize - 1) 47155856Sbostic return(0); 47255491Sbostic 47355856Sbostic /* check data/inode block(s) checksum too */ 47455856Sbostic datap = (u_long *)malloc(nblocks * sizeof(u_long)); 47555491Sbostic p = (caddr_t)ssp + LFS_SUMMARY_SIZE; 47655856Sbostic for (i = 0; i < nblocks; ++i) { 47755491Sbostic datap[i] = *((u_long *)p); 47855856Sbostic p += fsp->fi_lfs.lfs_bsize; 47955491Sbostic } 48055856Sbostic if (cksum ((void *)datap, nblocks * sizeof(u_long)) != ssp->ss_datasum) 48155856Sbostic return (0); 48255491Sbostic 48355856Sbostic return (nblocks); 48455491Sbostic } 48555491Sbostic 48655491Sbostic 48755491Sbostic /* #define MMAP_SEGMENT */ 48855491Sbostic /* 48955491Sbostic * read a segment into a memory buffer 49055491Sbostic */ 49155491Sbostic int 492*57201Smargo mmap_segment (fsp, segment, segbuf, use_mmap) 49355856Sbostic FS_INFO *fsp; /* file system information */ 49455856Sbostic int segment; /* segment number */ 49555856Sbostic caddr_t *segbuf; /* pointer to buffer area */ 496*57201Smargo int use_mmap; /* mmap instead of read */ 49755491Sbostic { 49855856Sbostic struct lfs *lfsp; 49955856Sbostic int fid; /* fildes for file system device */ 50055856Sbostic daddr_t seg_daddr; /* base disk address of segment */ 50155856Sbostic off_t seg_byte; 50255856Sbostic size_t ssize; 50355856Sbostic char mntfromname[MNAMELEN+2]; 50455491Sbostic 50555856Sbostic lfsp = &fsp->fi_lfs; 50655856Sbostic 50755491Sbostic /* get the disk address of the beginning of the segment */ 50855491Sbostic seg_daddr = sntoda(lfsp, segment); 50955856Sbostic seg_byte = datobyte(fsp, seg_daddr); 51055856Sbostic ssize = seg_size(lfsp); 51155491Sbostic 51255491Sbostic strcpy(mntfromname, "/dev/r"); 51355856Sbostic strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5); 51455491Sbostic 51555491Sbostic if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) { 51655856Sbostic err(0, "mmap_segment: bad open"); 51755856Sbostic return (-1); 51855491Sbostic } 51955491Sbostic 520*57201Smargo if (use_mmap) { 521*57201Smargo *segbuf = mmap ((caddr_t)0, seg_size(lfsp), PROT_READ, 522*57201Smargo 0, fid, seg_byte); 523*57201Smargo if (*(long *)segbuf < 0) { 524*57201Smargo err(0, "mmap_segment: mmap failed"); 525*57201Smargo return (NULL); 526*57201Smargo } 527*57201Smargo } else { 52855856Sbostic #ifdef VERBOSE 529*57201Smargo printf("mmap_segment\tseg_daddr: %lu\tseg_size: %lu\tseg_offset: %qu\n", 530*57201Smargo seg_daddr, ssize, seg_byte); 53155856Sbostic #endif 532*57201Smargo /* malloc the space for the buffer */ 533*57201Smargo *segbuf = malloc(ssize); 534*57201Smargo if (!*segbuf) { 535*57201Smargo err(0, "mmap_segment: malloc failed"); 536*57201Smargo return(NULL); 537*57201Smargo } 53855491Sbostic 539*57201Smargo /* read the segment data into the buffer */ 540*57201Smargo if (lseek (fid, seg_byte, SEEK_SET) != seg_byte) { 541*57201Smargo err (0, "mmap_segment: bad lseek"); 542*57201Smargo free(*segbuf); 543*57201Smargo return (-1); 544*57201Smargo } 545*57201Smargo 546*57201Smargo if (read (fid, *segbuf, ssize) != ssize) { 547*57201Smargo err (0, "mmap_segment: bad read"); 548*57201Smargo free(*segbuf); 549*57201Smargo return (-1); 550*57201Smargo } 55155491Sbostic } 55255491Sbostic close (fid); 55355491Sbostic 55455856Sbostic return (0); 55555491Sbostic } 55655491Sbostic 55755491Sbostic void 558*57201Smargo munmap_segment (fsp, seg_buf, use_mmap) 55955856Sbostic FS_INFO *fsp; /* file system information */ 56055856Sbostic caddr_t seg_buf; /* pointer to buffer area */ 561*57201Smargo int use_mmap; /* mmap instead of read/write */ 56255491Sbostic { 563*57201Smargo if (use_mmap) 564*57201Smargo munmap (seg_buf, seg_size(&fsp->fi_lfs)); 565*57201Smargo else 566*57201Smargo free (seg_buf); 56755491Sbostic } 56855491Sbostic 56955491Sbostic 57055491Sbostic /* 57155491Sbostic * USEFUL DEBUGGING TOOLS: 57255491Sbostic */ 57355491Sbostic void 57455856Sbostic print_SEGSUM (lfsp, p) 57555856Sbostic struct lfs *lfsp; 57655856Sbostic SEGSUM *p; 57755491Sbostic { 57855856Sbostic if (p) 57955856Sbostic (void) dump_summary(lfsp, p, DUMP_ALL, NULL); 58055491Sbostic else printf("0x0"); 58155491Sbostic fflush(stdout); 58255491Sbostic } 58355491Sbostic 58455856Sbostic int 58555856Sbostic bi_compare(a, b) 58655856Sbostic const void *a; 58755856Sbostic const void *b; 58855491Sbostic { 58955856Sbostic const BLOCK_INFO *ba, *bb; 59055856Sbostic int diff; 59155491Sbostic 59255856Sbostic ba = a; 59355856Sbostic bb = b; 59455491Sbostic 59555856Sbostic if (diff = (int)(ba->bi_inode - bb->bi_inode)) 59655856Sbostic return (diff); 59755930Sbostic if (diff = (int)(ba->bi_lbn - bb->bi_lbn)) { 59855930Sbostic if (ba->bi_lbn == LFS_UNUSED_LBN) 59955930Sbostic return(-1); 60055930Sbostic else if (bb->bi_lbn == LFS_UNUSED_LBN) 60155930Sbostic return(1); 60256623Smargo else if (ba->bi_lbn < 0 && bb->bi_lbn >= 0) 60355930Sbostic return(1); 60456623Smargo else if (bb->bi_lbn < 0 && ba->bi_lbn >= 0) 60556623Smargo return(-1); 60655930Sbostic else 60755930Sbostic return (diff); 60855930Sbostic } 60955856Sbostic if (diff = (int)(ba->bi_segcreate - bb->bi_segcreate)) 61055856Sbostic return (diff); 61155856Sbostic diff = (int)(ba->bi_daddr - bb->bi_daddr); 61255856Sbostic return (diff); 61355856Sbostic } 61455491Sbostic 61555856Sbostic int 61655856Sbostic bi_toss(dummy, a, b) 61755856Sbostic const void *dummy; 61855856Sbostic const void *a; 61955856Sbostic const void *b; 62055491Sbostic { 62155856Sbostic const BLOCK_INFO *ba, *bb; 62255491Sbostic 62355856Sbostic ba = a; 62455856Sbostic bb = b; 62555856Sbostic 62655856Sbostic return(ba->bi_inode == bb->bi_inode && ba->bi_lbn == bb->bi_lbn); 62755491Sbostic } 62855491Sbostic 62955491Sbostic void 63055856Sbostic toss(p, nump, size, dotoss, client) 63155856Sbostic void *p; 63255856Sbostic int *nump; 63355856Sbostic size_t size; 63455856Sbostic int (*dotoss) __P((const void *, const void *, const void *)); 63555856Sbostic void *client; 63655491Sbostic { 63755856Sbostic int i; 63855856Sbostic void *p1; 63955491Sbostic 64055856Sbostic if (*nump == 0) 64155856Sbostic return; 64255491Sbostic 64355856Sbostic for (i = *nump; --i > 0;) { 64455856Sbostic p1 = p + size; 64555856Sbostic if (dotoss(client, p, p1)) { 64655856Sbostic bcopy(p1, p, i * size); 64755856Sbostic --(*nump); 64855856Sbostic } else 64955856Sbostic p += size; 65055491Sbostic } 65155491Sbostic } 652