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*61416Scgd static char sccsid[] = "@(#)library.c 5.11 (Berkeley) 06/04/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> 2660095Sbostic #include <unistd.h> 2760095Sbostic 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 /* 4161373Scgd * This function will get information on a a filesystem which matches 4261373Scgd * the name and type given. If a "name" is in a filesystem of the given 4361373Scgd * type, then buf is filled with that filesystem's info, and the 4461373Scgd * a non-zero value is returned. 4555491Sbostic */ 4655491Sbostic int 4761373Scgd fs_getmntinfo(buf, name, type) 4855491Sbostic struct statfs **buf; 4961373Scgd char *name; 5055491Sbostic int type; 5155491Sbostic { 5261373Scgd /* allocate space for the filesystem info */ 5361373Scgd *buf = (struct statfs *)malloc(sizeof(struct statfs)); 5461373Scgd if (*buf == NULL) 5561373Scgd return 0; 5655491Sbostic 5761373Scgd /* grab the filesystem info */ 5861373Scgd if (statfs(name, *buf) < 0) { 5961373Scgd free(*buf); 6061373Scgd return 0; 6161373Scgd } 6255491Sbostic 6361373Scgd /* check to see if it's the one we want */ 6461373Scgd if (((*buf)->f_type != type) || 6561373Scgd strncmp(name, (*buf)->f_mntonname, MNAMELEN)) { 6661373Scgd /* "this is not the filesystem you're looking for */ 6761373Scgd free(*buf); 6861373Scgd return 0; 6955491Sbostic } 7055491Sbostic 7161373Scgd return 1; 7255491Sbostic } 7355491Sbostic 7455491Sbostic /* 7555856Sbostic * Get all the information available on an LFS file system. 7661373Scgd * Returns an pointer to an FS_INFO structure, NULL on error. 7755491Sbostic */ 7855856Sbostic FS_INFO * 7961373Scgd get_fs_info (lstatfsp, use_mmap) 8061373Scgd struct statfs *lstatfsp; /* IN: pointer to statfs struct */ 8157201Smargo int use_mmap; /* IN: mmap or read */ 8255491Sbostic { 8361373Scgd FS_INFO *fsp; 8455491Sbostic int i; 8555491Sbostic 8661373Scgd fsp = (FS_INFO *)malloc(sizeof(FS_INFO)); 8761373Scgd if (fsp == NULL) 8861373Scgd return NULL; 8961373Scgd bzero(fsp, sizeof(FS_INFO)); 9055491Sbostic 9161373Scgd fsp->fi_statfsp = lstatfsp; 9261373Scgd if (get_superblock (fsp, &fsp->fi_lfs)) 9361373Scgd err(1, "get_fs_info: get_superblock failed"); 9461373Scgd fsp->fi_daddr_shift = 9561373Scgd fsp->fi_lfs.lfs_bshift - fsp->fi_lfs.lfs_fsbtodb; 9661373Scgd get_ifile (fsp, use_mmap); 9755856Sbostic return (fsp); 9855491Sbostic } 9955491Sbostic 10055856Sbostic /* 10155856Sbostic * If we are reading the ifile then we need to refresh it. Even if 10255856Sbostic * we are mmapping it, it might have grown. Finally, we need to 10355856Sbostic * refresh the file system information (statfs) info. 10455856Sbostic */ 10555491Sbostic void 10661373Scgd reread_fs_info(fsp, use_mmap) 10761373Scgd FS_INFO *fsp; /* IN: prointer fs_infos to reread */ 10860095Sbostic int use_mmap; 10955491Sbostic { 11055856Sbostic int i; 11155491Sbostic 11261373Scgd if (statfs(fsp->fi_statfsp->f_mntonname, fsp->fi_statfsp)) 113*61416Scgd err(1, "reread_fs_info: statfs failed"); 11461373Scgd get_ifile (fsp, use_mmap); 11555491Sbostic } 11655491Sbostic 11755491Sbostic /* 11855856Sbostic * Gets the superblock from disk (possibly in face of errors) 11955491Sbostic */ 12055491Sbostic int 12155491Sbostic get_superblock (fsp, sbp) 12255856Sbostic FS_INFO *fsp; /* local file system info structure */ 12355856Sbostic struct lfs *sbp; 12455491Sbostic { 12555856Sbostic char mntfromname[MNAMELEN+1]; 12655856Sbostic int fid; 12755491Sbostic 12855491Sbostic strcpy(mntfromname, "/dev/r"); 12955856Sbostic strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5); 13055491Sbostic 13155491Sbostic if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) { 13255856Sbostic err(0, "get_superblock: bad open"); 13355856Sbostic return (-1); 13455491Sbostic } 13555491Sbostic 13655856Sbostic get(fid, LFS_LABELPAD, sbp, sizeof(struct lfs)); 13755491Sbostic close (fid); 13855491Sbostic 13955856Sbostic return (0); 14055491Sbostic } 14155491Sbostic 14255491Sbostic /* 14355856Sbostic * This function will map the ifile into memory. It causes a 14455856Sbostic * fatal error on failure. 14555491Sbostic */ 14655856Sbostic void 14757201Smargo get_ifile (fsp, use_mmap) 14855491Sbostic FS_INFO *fsp; 14957201Smargo int use_mmap; 15057201Smargo 15155491Sbostic { 15255856Sbostic struct stat file_stat; 15355856Sbostic caddr_t ifp; 15455856Sbostic char *ifile_name; 15555856Sbostic int count, fid; 15655491Sbostic 15755856Sbostic ifp = NULL; 15855856Sbostic ifile_name = malloc(strlen(fsp->fi_statfsp->f_mntonname) + 15955856Sbostic strlen(IFILE_NAME)+2); 16055856Sbostic strcat(strcat(strcpy(ifile_name, fsp->fi_statfsp->f_mntonname), "/"), 16155856Sbostic IFILE_NAME); 16255491Sbostic 16355856Sbostic if ((fid = open(ifile_name, O_RDWR, (mode_t)0)) < 0) 16455856Sbostic err(1, "get_ifile: bad open"); 16555491Sbostic 16655856Sbostic if (fstat (fid, &file_stat)) 16755856Sbostic err(1, "get_ifile: fstat failed"); 16855491Sbostic 16957201Smargo if (use_mmap && file_stat.st_size == fsp->fi_ifile_length) { 17057201Smargo (void) close(fid); 17157201Smargo return; 17257201Smargo } 17355856Sbostic 17455491Sbostic /* get the ifile */ 17557201Smargo if (use_mmap) { 17657201Smargo if (fsp->fi_cip) 17757201Smargo munmap((caddr_t)fsp->fi_cip, fsp->fi_ifile_length); 17857201Smargo ifp = mmap ((caddr_t)0, file_stat.st_size, 17957201Smargo PROT_READ|PROT_WRITE, 0, fid, (off_t)0); 18057201Smargo if (ifp == (caddr_t)(-1)) 18157201Smargo err(1, "get_ifile: mmap failed"); 18257201Smargo } else { 18357201Smargo if (fsp->fi_cip) 18457201Smargo free(fsp->fi_cip); 18557201Smargo if (!(ifp = malloc (file_stat.st_size))) 18657201Smargo err (1, "get_ifile: malloc failed"); 18755856Sbostic redo_read: 18857201Smargo count = read (fid, ifp, (size_t) file_stat.st_size); 18955491Sbostic 19057201Smargo if (count < 0) 19157201Smargo err(1, "get_ifile: bad ifile read"); 19257201Smargo else if (count < file_stat.st_size) { 19357201Smargo err(0, "get_ifile"); 19457201Smargo if (lseek(fid, 0, SEEK_SET) < 0) 19557201Smargo err(1, "get_ifile: bad ifile lseek"); 19657201Smargo goto redo_read; 19757201Smargo } 19855491Sbostic } 19957201Smargo fsp->fi_ifile_length = file_stat.st_size; 20055491Sbostic close (fid); 20155491Sbostic 20255856Sbostic fsp->fi_cip = (CLEANERINFO *)ifp; 20355856Sbostic fsp->fi_segusep = (SEGUSE *)(ifp + CLEANSIZE(fsp)); 20455856Sbostic fsp->fi_ifilep = (IFILE *)((caddr_t)fsp->fi_segusep + SEGTABSIZE(fsp)); 20555856Sbostic 20655856Sbostic /* 20755856Sbostic * The number of ifile entries is equal to the number of blocks 20855856Sbostic * blocks in the ifile minus the ones allocated to cleaner info 20955856Sbostic * and segment usage table multiplied by the number of ifile 21055856Sbostic * entries per page. 21155856Sbostic */ 21255856Sbostic fsp->fi_ifile_count = (fsp->fi_ifile_length >> fsp->fi_lfs.lfs_bshift - 21355856Sbostic fsp->fi_lfs.lfs_cleansz - fsp->fi_lfs.lfs_segtabsz) * 21455856Sbostic fsp->fi_lfs.lfs_ifpb; 21555856Sbostic 21655491Sbostic free (ifile_name); 21755491Sbostic } 21855491Sbostic 21955491Sbostic /* 22055856Sbostic * This function will scan a segment and return a list of 22155491Sbostic * <inode, blocknum> pairs which indicate which blocks were 22255856Sbostic * contained as live data within the segment when the segment 22355856Sbostic * summary was read (it may have "died" since then). Any given 22455856Sbostic * pair will be listed at most once. 22555491Sbostic */ 22655491Sbostic int 22755930Sbostic lfs_segmapv(fsp, seg, seg_buf, blocks, bcount) 22855856Sbostic FS_INFO *fsp; /* pointer to local file system information */ 22955856Sbostic int seg; /* the segment number */ 23055856Sbostic caddr_t seg_buf; /* the buffer containing the segment's data */ 23155856Sbostic BLOCK_INFO **blocks; /* OUT: array of block_info for live blocks */ 23255856Sbostic int *bcount; /* OUT: number of active blocks in segment */ 23355491Sbostic { 23455856Sbostic BLOCK_INFO *bip; 23555856Sbostic SEGSUM *sp; 23655856Sbostic SEGUSE *sup; 23756623Smargo FINFO *fip; 23855856Sbostic struct lfs *lfsp; 23955856Sbostic caddr_t s, segend; 24055856Sbostic daddr_t pseg_addr, seg_addr; 24156623Smargo int i, nelem, nblocks, sumsize; 24255856Sbostic time_t timestamp; 24355491Sbostic 24455856Sbostic lfsp = &fsp->fi_lfs; 24555930Sbostic nelem = 2 * lfsp->lfs_ssize; 24655930Sbostic if (!(bip = malloc(nelem * sizeof(BLOCK_INFO)))) 24755856Sbostic goto err0; 24855491Sbostic 24955856Sbostic sup = SEGUSE_ENTRY(lfsp, fsp->fi_segusep, seg); 25055856Sbostic s = seg_buf + (sup->su_flags & SEGUSE_SUPERBLOCK ? LFS_SBPAD : 0); 25155856Sbostic seg_addr = sntoda(lfsp, seg); 25255856Sbostic pseg_addr = seg_addr + (sup->su_flags & SEGUSE_SUPERBLOCK ? btodb(LFS_SBPAD) : 0); 25355856Sbostic #ifdef VERBOSE 25455856Sbostic printf("\tsegment buffer at: 0x%x\tseg_addr 0x%x\n", s, seg_addr); 25555856Sbostic #endif /* VERBOSE */ 25655491Sbostic 25755856Sbostic *bcount = 0; 25855856Sbostic for (segend = seg_buf + seg_size(lfsp), timestamp = 0; s < segend; ) { 25955856Sbostic sp = (SEGSUM *)s; 26056623Smargo 26155491Sbostic #ifdef VERBOSE 26255856Sbostic printf("\tpartial at: 0x%x\n", pseg_addr); 26355856Sbostic print_SEGSUM(lfsp, sp); 26455491Sbostic fflush(stdout); 26555491Sbostic #endif /* VERBOSE */ 26655491Sbostic 26755856Sbostic nblocks = pseg_valid(fsp, sp); 26855856Sbostic if (nblocks <= 0) 26955856Sbostic break; 27055491Sbostic 27155856Sbostic /* Check if we have hit old data */ 27255856Sbostic if (timestamp > ((SEGSUM*)s)->ss_create) 27355856Sbostic break; 27455491Sbostic timestamp = ((SEGSUM*)s)->ss_create; 27555491Sbostic 27656623Smargo #ifdef DIAGNOSTIC 27756623Smargo /* Verfiy size of summary block */ 27856623Smargo sumsize = sizeof(SEGSUM) + 27956623Smargo (sp->ss_ninos + INOPB(lfsp) - 1) / INOPB(lfsp); 28056623Smargo for (fip = (FINFO *)(sp + 1); i < sp->ss_nfinfo; ++i) { 28156623Smargo sumsize += sizeof(FINFO) + 28256623Smargo (fip->fi_nblocks - 1) * sizeof(daddr_t); 28356623Smargo fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks]); 28456623Smargo } 28556623Smargo if (sumsize > LFS_SUMMARY_SIZE) { 28656623Smargo fprintf(stderr, 28756623Smargo "Segment %d summary block too big: %d\n", 28856623Smargo seg, sumsize); 28956623Smargo exit(1); 29056623Smargo } 29156623Smargo #endif 29256623Smargo 29355930Sbostic if (*bcount + nblocks + sp->ss_ninos > nelem) { 29455930Sbostic nelem = *bcount + nblocks + sp->ss_ninos; 29555930Sbostic bip = realloc (bip, nelem * sizeof(BLOCK_INFO)); 29655930Sbostic if (!bip) 29755930Sbostic goto err0; 29855856Sbostic } 29955856Sbostic add_blocks(fsp, bip, bcount, sp, seg_buf, seg_addr, pseg_addr); 30055930Sbostic add_inodes(fsp, bip, bcount, sp, seg_buf, seg_addr); 30155856Sbostic pseg_addr += fsbtodb(lfsp, nblocks) + 30255856Sbostic bytetoda(fsp, LFS_SUMMARY_SIZE); 30355856Sbostic s += (nblocks << lfsp->lfs_bshift) + LFS_SUMMARY_SIZE; 30455856Sbostic } 30555856Sbostic qsort(bip, *bcount, sizeof(BLOCK_INFO), bi_compare); 30655856Sbostic toss(bip, bcount, sizeof(BLOCK_INFO), bi_toss, NULL); 30755856Sbostic #ifdef VERBOSE 30855856Sbostic { 30955856Sbostic BLOCK_INFO *_bip; 31055856Sbostic int i; 31155491Sbostic 31255856Sbostic printf("BLOCK INFOS\n"); 31355856Sbostic for (_bip = bip, i=0; i < *bcount; ++_bip, ++i) 31455856Sbostic PRINT_BINFO(_bip); 31555491Sbostic } 31655856Sbostic #endif 31755856Sbostic *blocks = bip; 31855856Sbostic return (0); 31955856Sbostic 32055856Sbostic err0: *bcount = 0; 32155856Sbostic return (-1); 32255491Sbostic 32355491Sbostic } 32455491Sbostic 32555491Sbostic /* 32655856Sbostic * This will parse a partial segment and fill in BLOCK_INFO structures 32755856Sbostic * for each block described in the segment summary. It will not include 32855856Sbostic * blocks or inodes from files with new version numbers. 32955491Sbostic */ 33055491Sbostic void 33155856Sbostic add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr) 33255491Sbostic FS_INFO *fsp; /* pointer to super block */ 33355856Sbostic BLOCK_INFO *bip; /* Block info array */ 33455856Sbostic int *countp; /* IN/OUT: number of blocks in array */ 33555856Sbostic SEGSUM *sp; /* segment summmary pointer */ 33655856Sbostic caddr_t seg_buf; /* buffer containing segment */ 33755856Sbostic daddr_t segaddr; /* address of this segment */ 33855856Sbostic daddr_t psegaddr; /* address of this partial segment */ 33955491Sbostic { 34055856Sbostic IFILE *ifp; 34155856Sbostic FINFO *fip; 34255856Sbostic caddr_t bp; 34355930Sbostic daddr_t *dp, *iaddrp; 34455856Sbostic int db_per_block, i, j; 34555856Sbostic u_long page_size; 34655491Sbostic 34755491Sbostic #ifdef VERBOSE 34855856Sbostic printf("FILE INFOS\n"); 34955491Sbostic #endif 35055856Sbostic db_per_block = fsbtodb(&fsp->fi_lfs, 1); 35155856Sbostic page_size = fsp->fi_lfs.lfs_bsize; 35255856Sbostic bp = seg_buf + datobyte(fsp, psegaddr - segaddr) + LFS_SUMMARY_SIZE; 35355856Sbostic bip += *countp; 35455856Sbostic psegaddr += bytetoda(fsp, LFS_SUMMARY_SIZE); 35555856Sbostic iaddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE); 35655856Sbostic --iaddrp; 35755856Sbostic for (fip = (FINFO *)(sp + 1), i = 0; i < sp->ss_nfinfo; 35855856Sbostic ++i, fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks])) { 35955491Sbostic 36055856Sbostic ifp = IFILE_ENTRY(&fsp->fi_lfs, fsp->fi_ifilep, fip->fi_ino); 36155856Sbostic PRINT_FINFO(fip, ifp); 36255856Sbostic if (ifp->if_version > fip->fi_version) 36355491Sbostic continue; 36455856Sbostic dp = &(fip->fi_blocks[0]); 36555856Sbostic for (j = 0; j < fip->fi_nblocks; j++, dp++) { 36655856Sbostic while (psegaddr == *iaddrp) { 36755856Sbostic psegaddr += db_per_block; 36855856Sbostic bp += page_size; 36955856Sbostic --iaddrp; 37055491Sbostic } 37155856Sbostic bip->bi_inode = fip->fi_ino; 37255856Sbostic bip->bi_lbn = *dp; 37355856Sbostic bip->bi_daddr = psegaddr; 37455856Sbostic bip->bi_segcreate = (time_t)(sp->ss_create); 37555856Sbostic bip->bi_bp = bp; 37656193Smargo bip->bi_version = ifp->if_version; 37755856Sbostic psegaddr += db_per_block; 37855856Sbostic bp += page_size; 37955856Sbostic ++bip; 38055856Sbostic ++(*countp); 38155491Sbostic } 38255491Sbostic } 38355491Sbostic } 38455491Sbostic 38555856Sbostic /* 38655856Sbostic * For a particular segment summary, reads the inode blocks and adds 38755856Sbostic * INODE_INFO structures to the array. Returns the number of inodes 38855856Sbostic * actually added. 38955856Sbostic */ 39055491Sbostic void 39155930Sbostic add_inodes (fsp, bip, countp, sp, seg_buf, seg_addr) 39255491Sbostic FS_INFO *fsp; /* pointer to super block */ 39355930Sbostic BLOCK_INFO *bip; /* block info array */ 39455856Sbostic int *countp; /* pointer to current number of inodes */ 39555856Sbostic SEGSUM *sp; /* segsum pointer */ 39655491Sbostic caddr_t seg_buf; /* the buffer containing the segment's data */ 39755856Sbostic daddr_t seg_addr; /* disk address of seg_buf */ 39855491Sbostic { 39955856Sbostic struct dinode *di; 40055856Sbostic struct lfs *lfsp; 40155856Sbostic IFILE *ifp; 40255930Sbostic BLOCK_INFO *bp; 40355856Sbostic daddr_t *daddrp; 40455856Sbostic ino_t inum; 40555856Sbostic int i; 40655491Sbostic 40755856Sbostic if (sp->ss_ninos <= 0) 40855856Sbostic return; 40955491Sbostic 41055930Sbostic bp = bip + *countp; 41155856Sbostic lfsp = &fsp->fi_lfs; 41255491Sbostic #ifdef VERBOSE 41355930Sbostic (void) printf("INODES:\n"); 41455491Sbostic #endif 41555856Sbostic daddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE); 41655856Sbostic for (i = 0; i < sp->ss_ninos; ++i) { 41755491Sbostic if (i % INOPB(lfsp) == 0) { 41855856Sbostic --daddrp; 41955856Sbostic di = (struct dinode *)(seg_buf + 42055856Sbostic ((*daddrp - seg_addr) << fsp->fi_daddr_shift)); 42155491Sbostic } else 42255491Sbostic ++di; 42355491Sbostic 42457201Smargo inum = di->di_inumber; 42555930Sbostic bp->bi_lbn = LFS_UNUSED_LBN; 42655930Sbostic bp->bi_inode = inum; 42755930Sbostic bp->bi_daddr = *daddrp; 42855930Sbostic bp->bi_bp = di; 42955930Sbostic bp->bi_segcreate = sp->ss_create; 43055491Sbostic 43156036Sbostic if (inum == LFS_IFILE_INUM) { 43256193Smargo bp->bi_version = 1; /* Ifile version should be 1 */ 43355930Sbostic bp++; 43455856Sbostic ++(*countp); 43556036Sbostic PRINT_INODE(1, bp); 43656036Sbostic } else { 43756036Sbostic ifp = IFILE_ENTRY(lfsp, fsp->fi_ifilep, inum); 43856036Sbostic PRINT_INODE(ifp->if_daddr == *daddrp, bp); 43956193Smargo bp->bi_version = ifp->if_version; 44056036Sbostic if (ifp->if_daddr == *daddrp) { 44156036Sbostic bp++; 44256036Sbostic ++(*countp); 44356036Sbostic } 44456036Sbostic } 44555491Sbostic } 44655491Sbostic } 44755491Sbostic 44855491Sbostic /* 44955856Sbostic * Checks the summary checksum and the data checksum to determine if the 45055856Sbostic * segment is valid or not. Returns the size of the partial segment if it 45155856Sbostic * is valid, * and 0 otherwise. Use dump_summary to figure out size of the 45255856Sbostic * the partial as well as whether or not the checksum is valid. 45355491Sbostic */ 45455491Sbostic int 45555491Sbostic pseg_valid (fsp, ssp) 45655491Sbostic FS_INFO *fsp; /* pointer to file system info */ 45755856Sbostic SEGSUM *ssp; /* pointer to segment summary block */ 45855491Sbostic { 45955491Sbostic caddr_t p; 46055856Sbostic int i, nblocks; 46155856Sbostic u_long *datap; 46255491Sbostic 46356655Sbostic if ((nblocks = dump_summary(&fsp->fi_lfs, ssp, 0, NULL)) <= 0 || 46456655Sbostic nblocks > fsp->fi_lfs.lfs_ssize - 1) 46555856Sbostic return(0); 46655491Sbostic 46755856Sbostic /* check data/inode block(s) checksum too */ 46855856Sbostic datap = (u_long *)malloc(nblocks * sizeof(u_long)); 46955491Sbostic p = (caddr_t)ssp + LFS_SUMMARY_SIZE; 47055856Sbostic for (i = 0; i < nblocks; ++i) { 47155491Sbostic datap[i] = *((u_long *)p); 47255856Sbostic p += fsp->fi_lfs.lfs_bsize; 47355491Sbostic } 47455856Sbostic if (cksum ((void *)datap, nblocks * sizeof(u_long)) != ssp->ss_datasum) 47555856Sbostic return (0); 47655491Sbostic 47755856Sbostic return (nblocks); 47855491Sbostic } 47955491Sbostic 48055491Sbostic 48155491Sbostic /* #define MMAP_SEGMENT */ 48255491Sbostic /* 48355491Sbostic * read a segment into a memory buffer 48455491Sbostic */ 48555491Sbostic int 48657201Smargo mmap_segment (fsp, segment, segbuf, use_mmap) 48755856Sbostic FS_INFO *fsp; /* file system information */ 48855856Sbostic int segment; /* segment number */ 48955856Sbostic caddr_t *segbuf; /* pointer to buffer area */ 49057201Smargo int use_mmap; /* mmap instead of read */ 49155491Sbostic { 49255856Sbostic struct lfs *lfsp; 49355856Sbostic int fid; /* fildes for file system device */ 49455856Sbostic daddr_t seg_daddr; /* base disk address of segment */ 49555856Sbostic off_t seg_byte; 49655856Sbostic size_t ssize; 49755856Sbostic char mntfromname[MNAMELEN+2]; 49855491Sbostic 49955856Sbostic lfsp = &fsp->fi_lfs; 50055856Sbostic 50155491Sbostic /* get the disk address of the beginning of the segment */ 50255491Sbostic seg_daddr = sntoda(lfsp, segment); 50355856Sbostic seg_byte = datobyte(fsp, seg_daddr); 50455856Sbostic ssize = seg_size(lfsp); 50555491Sbostic 50655491Sbostic strcpy(mntfromname, "/dev/r"); 50755856Sbostic strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5); 50855491Sbostic 50955491Sbostic if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) { 51055856Sbostic err(0, "mmap_segment: bad open"); 51155856Sbostic return (-1); 51255491Sbostic } 51355491Sbostic 51457201Smargo if (use_mmap) { 51557201Smargo *segbuf = mmap ((caddr_t)0, seg_size(lfsp), PROT_READ, 51657201Smargo 0, fid, seg_byte); 51757201Smargo if (*(long *)segbuf < 0) { 51857201Smargo err(0, "mmap_segment: mmap failed"); 51957201Smargo return (NULL); 52057201Smargo } 52157201Smargo } else { 52255856Sbostic #ifdef VERBOSE 52357201Smargo printf("mmap_segment\tseg_daddr: %lu\tseg_size: %lu\tseg_offset: %qu\n", 52457201Smargo seg_daddr, ssize, seg_byte); 52555856Sbostic #endif 52657201Smargo /* malloc the space for the buffer */ 52757201Smargo *segbuf = malloc(ssize); 52857201Smargo if (!*segbuf) { 52957201Smargo err(0, "mmap_segment: malloc failed"); 53057201Smargo return(NULL); 53157201Smargo } 53255491Sbostic 53357201Smargo /* read the segment data into the buffer */ 53457201Smargo if (lseek (fid, seg_byte, SEEK_SET) != seg_byte) { 53557201Smargo err (0, "mmap_segment: bad lseek"); 53657201Smargo free(*segbuf); 53757201Smargo return (-1); 53857201Smargo } 53957201Smargo 54057201Smargo if (read (fid, *segbuf, ssize) != ssize) { 54157201Smargo err (0, "mmap_segment: bad read"); 54257201Smargo free(*segbuf); 54357201Smargo return (-1); 54457201Smargo } 54555491Sbostic } 54655491Sbostic close (fid); 54755491Sbostic 54855856Sbostic return (0); 54955491Sbostic } 55055491Sbostic 55155491Sbostic void 55257201Smargo munmap_segment (fsp, seg_buf, use_mmap) 55355856Sbostic FS_INFO *fsp; /* file system information */ 55455856Sbostic caddr_t seg_buf; /* pointer to buffer area */ 55557201Smargo int use_mmap; /* mmap instead of read/write */ 55655491Sbostic { 55757201Smargo if (use_mmap) 55857201Smargo munmap (seg_buf, seg_size(&fsp->fi_lfs)); 55957201Smargo else 56057201Smargo free (seg_buf); 56155491Sbostic } 56255491Sbostic 56355491Sbostic 56455491Sbostic /* 56555491Sbostic * USEFUL DEBUGGING TOOLS: 56655491Sbostic */ 56755491Sbostic void 56855856Sbostic print_SEGSUM (lfsp, p) 56955856Sbostic struct lfs *lfsp; 57055856Sbostic SEGSUM *p; 57155491Sbostic { 57255856Sbostic if (p) 57355856Sbostic (void) dump_summary(lfsp, p, DUMP_ALL, NULL); 57455491Sbostic else printf("0x0"); 57555491Sbostic fflush(stdout); 57655491Sbostic } 57755491Sbostic 57855856Sbostic int 57955856Sbostic bi_compare(a, b) 58055856Sbostic const void *a; 58155856Sbostic const void *b; 58255491Sbostic { 58355856Sbostic const BLOCK_INFO *ba, *bb; 58455856Sbostic int diff; 58555491Sbostic 58655856Sbostic ba = a; 58755856Sbostic bb = b; 58855491Sbostic 58955856Sbostic if (diff = (int)(ba->bi_inode - bb->bi_inode)) 59055856Sbostic return (diff); 59155930Sbostic if (diff = (int)(ba->bi_lbn - bb->bi_lbn)) { 59255930Sbostic if (ba->bi_lbn == LFS_UNUSED_LBN) 59355930Sbostic return(-1); 59455930Sbostic else if (bb->bi_lbn == LFS_UNUSED_LBN) 59555930Sbostic return(1); 59656623Smargo else if (ba->bi_lbn < 0 && bb->bi_lbn >= 0) 59755930Sbostic return(1); 59856623Smargo else if (bb->bi_lbn < 0 && ba->bi_lbn >= 0) 59956623Smargo return(-1); 60055930Sbostic else 60155930Sbostic return (diff); 60255930Sbostic } 60355856Sbostic if (diff = (int)(ba->bi_segcreate - bb->bi_segcreate)) 60455856Sbostic return (diff); 60555856Sbostic diff = (int)(ba->bi_daddr - bb->bi_daddr); 60655856Sbostic return (diff); 60755856Sbostic } 60855491Sbostic 60955856Sbostic int 61055856Sbostic bi_toss(dummy, a, b) 61155856Sbostic const void *dummy; 61255856Sbostic const void *a; 61355856Sbostic const void *b; 61455491Sbostic { 61555856Sbostic const BLOCK_INFO *ba, *bb; 61655491Sbostic 61755856Sbostic ba = a; 61855856Sbostic bb = b; 61955856Sbostic 62055856Sbostic return(ba->bi_inode == bb->bi_inode && ba->bi_lbn == bb->bi_lbn); 62155491Sbostic } 62255491Sbostic 62355491Sbostic void 62455856Sbostic toss(p, nump, size, dotoss, client) 62555856Sbostic void *p; 62655856Sbostic int *nump; 62755856Sbostic size_t size; 62855856Sbostic int (*dotoss) __P((const void *, const void *, const void *)); 62955856Sbostic void *client; 63055491Sbostic { 63155856Sbostic int i; 63255856Sbostic void *p1; 63355491Sbostic 63455856Sbostic if (*nump == 0) 63555856Sbostic return; 63655491Sbostic 63755856Sbostic for (i = *nump; --i > 0;) { 63855856Sbostic p1 = p + size; 63955856Sbostic if (dotoss(client, p, p1)) { 64060095Sbostic memmove(p, p1, i * size); 64155856Sbostic --(*nump); 64255856Sbostic } else 64355856Sbostic p += size; 64455491Sbostic } 64555491Sbostic } 646