1*55860Sbostic /*- 2*55860Sbostic * Copyright (c) 1992 The Regents of the University of California. 3*55860Sbostic * All rights reserved. 4*55860Sbostic * 5*55860Sbostic * %sccs.include.redist.c% 6*55860Sbostic */ 7*55860Sbostic 8*55860Sbostic #ifndef lint 9*55860Sbostic static char sccsid[] = "@(#)library.c 5.1 (Berkeley) 08/06/92"; 10*55860Sbostic #endif /* not lint */ 11*55860Sbostic 1255491Sbostic #include <sys/param.h> 1355491Sbostic #include <sys/time.h> 1455491Sbostic #include <sys/stat.h> 1555491Sbostic #include <sys/mount.h> 1655491Sbostic 1755491Sbostic #include <ufs/ufs/dinode.h> 1855491Sbostic #include <ufs/lfs/lfs.h> 1955491Sbostic 2055491Sbostic #include <fcntl.h> 2155491Sbostic #include <stdio.h> 2255491Sbostic #include <unistd.h> 2355856Sbostic #include <stdlib.h> 2455856Sbostic #include <string.h> 2555491Sbostic #include "clean.h" 2655491Sbostic 2755856Sbostic void add_blocks __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t, 2855856Sbostic daddr_t, daddr_t)); 2955856Sbostic void add_inodes __P((FS_INFO *, INODE_INFO *, int *, SEGSUM *, caddr_t, 3055856Sbostic daddr_t)); 3155856Sbostic int bi_compare __P((const void *, const void *)); 3255856Sbostic int bi_toss __P((const void *, const void *, const void *)); 3355856Sbostic void get_ifile __P((FS_INFO *)); 3455856Sbostic int get_superblock __P((FS_INFO *, struct lfs *)); 3555856Sbostic int ii_compare __P((const void *, const void *)); 3655856Sbostic int ii_toss __P((const void *, const void *, const void *)); 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 5255491Sbostic tcount = getmntinfo(&tstatfsp, 0); 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 * 8255856Sbostic get_fs_info (lstatfsp, count) 8355856Sbostic struct statfs *lstatfsp; /* IN: array of statfs structs */ 8455856Sbostic int count; /* IN: number of file systems */ 8555491Sbostic { 8655856Sbostic FS_INFO *fp, *fsp; 8755491Sbostic int i; 8855491Sbostic 8955856Sbostic fsp = (FS_INFO *)malloc(count * sizeof(FS_INFO)); 9055491Sbostic 9155856Sbostic for (fp = fsp, i = 0; i < count; ++i, ++fp) { 9255856Sbostic fp->fi_statfsp = lstatfsp++; 9355856Sbostic if (get_superblock (fp, &fp->fi_lfs)) 9455856Sbostic err(1, "get_fs_info: get_superblock failed"); 9555856Sbostic fp->fi_daddr_shift = 9655856Sbostic fp->fi_lfs.lfs_bshift - fp->fi_lfs.lfs_fsbtodb; 9755856Sbostic get_ifile (fp); 9855491Sbostic } 9955856Sbostic return (fsp); 10055491Sbostic } 10155491Sbostic 10255856Sbostic /* 10355856Sbostic * If we are reading the ifile then we need to refresh it. Even if 10455856Sbostic * we are mmapping it, it might have grown. Finally, we need to 10555856Sbostic * refresh the file system information (statfs) info. 10655856Sbostic */ 10755491Sbostic void 10855856Sbostic reread_fs_info(fsp, count) 10955856Sbostic FS_INFO *fsp; /* IN: array of fs_infos to free */ 11055856Sbostic int count; /* IN: number of file systems */ 11155491Sbostic { 11255856Sbostic int i; 11355491Sbostic 11455856Sbostic for (i = 0; i < count; ++i, ++fsp) { 11555856Sbostic if (statfs(fsp->fi_statfsp->f_mntonname, fsp->fi_statfsp)) 11655856Sbostic err(0, "reread_fs_info: statfs failed"); 11755856Sbostic #ifdef MMAP_WORKS 11855856Sbostic if (munmap(fsp->fi_cip, fsp->fi_ifile_length) < 0) 11955856Sbostic err(0, "reread_fs_info: munmap failed"); 12055491Sbostic #else 12155856Sbostic free (fsp->fi_cip); 12255491Sbostic #endif /* MMAP_WORKS */ 12355856Sbostic get_ifile (fsp); 12455491Sbostic } 12555491Sbostic } 12655491Sbostic 12755491Sbostic /* 12855856Sbostic * Gets the superblock from disk (possibly in face of errors) 12955491Sbostic */ 13055491Sbostic int 13155491Sbostic get_superblock (fsp, sbp) 13255856Sbostic FS_INFO *fsp; /* local file system info structure */ 13355856Sbostic struct lfs *sbp; 13455491Sbostic { 13555856Sbostic char mntfromname[MNAMELEN+1]; 13655856Sbostic int fid; 13755491Sbostic 13855491Sbostic strcpy(mntfromname, "/dev/r"); 13955856Sbostic strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5); 14055491Sbostic 14155491Sbostic if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) { 14255856Sbostic err(0, "get_superblock: bad open"); 14355856Sbostic return (-1); 14455491Sbostic } 14555491Sbostic 14655856Sbostic get(fid, LFS_LABELPAD, sbp, sizeof(struct lfs)); 14755491Sbostic close (fid); 14855491Sbostic 14955856Sbostic return (0); 15055491Sbostic } 15155491Sbostic 15255491Sbostic /* 15355856Sbostic * This function will map the ifile into memory. It causes a 15455856Sbostic * fatal error on failure. 15555491Sbostic */ 15655856Sbostic void 15755491Sbostic get_ifile (fsp) 15855491Sbostic FS_INFO *fsp; 15955491Sbostic { 16055856Sbostic struct stat file_stat; 16155856Sbostic caddr_t ifp; 16255856Sbostic char *ifile_name; 16355856Sbostic int count, fid; 16455491Sbostic 16555856Sbostic ifp = NULL; 16655856Sbostic sync(); 16755856Sbostic ifile_name = malloc(strlen(fsp->fi_statfsp->f_mntonname) + 16855856Sbostic strlen(IFILE_NAME)+2); 16955856Sbostic strcat(strcat(strcpy(ifile_name, fsp->fi_statfsp->f_mntonname), "/"), 17055856Sbostic IFILE_NAME); 17155491Sbostic 17255856Sbostic if ((fid = open(ifile_name, O_RDWR, (mode_t)0)) < 0) 17355856Sbostic err(1, "get_ifile: bad open"); 17455491Sbostic 17555856Sbostic if (fstat (fid, &file_stat)) 17655856Sbostic err(1, "get_ifile: fstat failed"); 17755491Sbostic 17855856Sbostic fsp->fi_ifile_length = file_stat.st_size; 17955856Sbostic 18055491Sbostic /* get the ifile */ 18155491Sbostic #ifndef MMAP_WORKS 18255856Sbostic if (!(ifp = malloc ((size_t)fsp->fi_ifile_length))) 18355856Sbostic err (1, "get_ifile: malloc failed"); 18455856Sbostic redo_read: 18555856Sbostic count = read (fid, ifp, (size_t) fsp->fi_ifile_length); 18655491Sbostic 18755856Sbostic if (count < 0) 18855856Sbostic err(1, "get_ifile: bad ifile read"); 18955856Sbostic else if (count < (int)fsp->fi_ifile_length) { 19055856Sbostic err(0, "get_ifile"); 19155856Sbostic if (lseek(fid, 0, SEEK_SET) < 0) 19255856Sbostic err(1, "get_ifile: bad ifile lseek"); 19355856Sbostic goto redo_read; 19455491Sbostic } 19555491Sbostic #else /* MMAP_WORKS */ 19655856Sbostic ifp = mmap ((caddr_t)0, (size_t) fsp->fi_ifile_length, PROT_READ|PROT_WRITE, 19755491Sbostic MAP_FILE|MAP_SHARED, fid, (off_t)0); 19855856Sbostic if (ifp < 0) 19955856Sbostic err(1, "get_ifile: mmap failed"); 20055491Sbostic #endif /* MMAP_WORKS */ 20155491Sbostic 20255491Sbostic close (fid); 20355491Sbostic 20455856Sbostic fsp->fi_cip = (CLEANERINFO *)ifp; 20555856Sbostic fsp->fi_segusep = (SEGUSE *)(ifp + CLEANSIZE(fsp)); 20655856Sbostic fsp->fi_ifilep = (IFILE *)((caddr_t)fsp->fi_segusep + SEGTABSIZE(fsp)); 20755856Sbostic 20855856Sbostic /* 20955856Sbostic * The number of ifile entries is equal to the number of blocks 21055856Sbostic * blocks in the ifile minus the ones allocated to cleaner info 21155856Sbostic * and segment usage table multiplied by the number of ifile 21255856Sbostic * entries per page. 21355856Sbostic */ 21455856Sbostic fsp->fi_ifile_count = (fsp->fi_ifile_length >> fsp->fi_lfs.lfs_bshift - 21555856Sbostic fsp->fi_lfs.lfs_cleansz - fsp->fi_lfs.lfs_segtabsz) * 21655856Sbostic fsp->fi_lfs.lfs_ifpb; 21755856Sbostic 21855491Sbostic free (ifile_name); 21955491Sbostic } 22055491Sbostic 22155491Sbostic /* 22255856Sbostic * This function will scan a segment and return a list of 22355491Sbostic * <inode, blocknum> pairs which indicate which blocks were 22455856Sbostic * contained as live data within the segment when the segment 22555856Sbostic * summary was read (it may have "died" since then). Any given 22655856Sbostic * pair will be listed at most once. 22755491Sbostic */ 22855491Sbostic int 22955491Sbostic lfs_segmapv(fsp, seg, seg_buf, blocks, bcount, inodes, icount) 23055856Sbostic FS_INFO *fsp; /* pointer to local file system information */ 23155856Sbostic int seg; /* the segment number */ 23255856Sbostic caddr_t seg_buf; /* the buffer containing the segment's data */ 23355856Sbostic BLOCK_INFO **blocks; /* OUT: array of block_info for live blocks */ 23455856Sbostic int *bcount; /* OUT: number of active blocks in segment */ 23555856Sbostic INODE_INFO **inodes; /* OUT: array of inode_info for live inodes */ 23655856Sbostic int *icount; /* OUT: number of active inodes in segment */ 23755491Sbostic { 23855856Sbostic BLOCK_INFO *bip; 23955856Sbostic INODE_INFO *iip; 24055856Sbostic SEGSUM *sp; 24155856Sbostic SEGUSE *sup; 24255856Sbostic struct lfs *lfsp; 24355856Sbostic caddr_t s, segend; 24455856Sbostic daddr_t pseg_addr, seg_addr; 24555856Sbostic int nblocks, num_iblocks; 24655856Sbostic time_t timestamp; 24755491Sbostic 24855856Sbostic lfsp = &fsp->fi_lfs; 24955856Sbostic num_iblocks = lfsp->lfs_ssize; 25055856Sbostic if (!(bip = malloc(lfsp->lfs_ssize * sizeof(BLOCK_INFO)))) 25155856Sbostic goto err0; 25255856Sbostic if (!(iip = malloc(lfsp->lfs_ssize * sizeof(INODE_INFO)))) 25355856Sbostic goto err1; 25455491Sbostic 25555856Sbostic sup = SEGUSE_ENTRY(lfsp, fsp->fi_segusep, seg); 25655856Sbostic s = seg_buf + (sup->su_flags & SEGUSE_SUPERBLOCK ? LFS_SBPAD : 0); 25755856Sbostic seg_addr = sntoda(lfsp, seg); 25855856Sbostic pseg_addr = seg_addr + (sup->su_flags & SEGUSE_SUPERBLOCK ? btodb(LFS_SBPAD) : 0); 25955856Sbostic #ifdef VERBOSE 26055856Sbostic printf("\tsegment buffer at: 0x%x\tseg_addr 0x%x\n", s, seg_addr); 26155856Sbostic #endif /* VERBOSE */ 26255491Sbostic 26355856Sbostic *bcount = 0; 26455856Sbostic *icount = 0; 26555856Sbostic for (segend = seg_buf + seg_size(lfsp), timestamp = 0; s < segend; ) { 26655856Sbostic sp = (SEGSUM *)s; 26755491Sbostic #ifdef VERBOSE 26855856Sbostic printf("\tpartial at: 0x%x\n", pseg_addr); 26955856Sbostic print_SEGSUM(lfsp, sp); 27055491Sbostic fflush(stdout); 27155491Sbostic #endif /* VERBOSE */ 27255491Sbostic 27355856Sbostic nblocks = pseg_valid(fsp, sp); 27455856Sbostic if (nblocks <= 0) 27555856Sbostic break; 27655491Sbostic 27755856Sbostic /* Check if we have hit old data */ 27855856Sbostic if (timestamp > ((SEGSUM*)s)->ss_create) 27955856Sbostic break; 28055491Sbostic timestamp = ((SEGSUM*)s)->ss_create; 28155491Sbostic 28255856Sbostic /* 28355856Sbostic * Right now we die if we run out of room, we could probably 28455856Sbostic * recover if we were smart. 28555856Sbostic */ 28655856Sbostic if (*icount + sp->ss_ninos > num_iblocks) { 28755856Sbostic num_iblocks = *icount + sp->ss_ninos; 28855856Sbostic iip = realloc (iip, num_iblocks * sizeof(INODE_INFO)); 28955856Sbostic if (!iip) 29055856Sbostic goto err1; 29155856Sbostic } 29255856Sbostic add_inodes(fsp, iip, icount, sp, seg_buf, seg_addr); 29355856Sbostic add_blocks(fsp, bip, bcount, sp, seg_buf, seg_addr, pseg_addr); 29455856Sbostic pseg_addr += fsbtodb(lfsp, nblocks) + 29555856Sbostic bytetoda(fsp, LFS_SUMMARY_SIZE); 29655856Sbostic s += (nblocks << lfsp->lfs_bshift) + LFS_SUMMARY_SIZE; 29755856Sbostic } 29855856Sbostic qsort(iip, *icount, sizeof(INODE_INFO), ii_compare); 29955856Sbostic qsort(bip, *bcount, sizeof(BLOCK_INFO), bi_compare); 30055856Sbostic toss(iip, icount, sizeof(INODE_INFO), ii_toss, NULL); 30155856Sbostic toss(bip, bcount, sizeof(BLOCK_INFO), bi_toss, NULL); 30255856Sbostic #ifdef VERBOSE 30355856Sbostic { 30455856Sbostic BLOCK_INFO *_bip; 30555856Sbostic INODE_INFO *_iip; 30655856Sbostic int i; 30755491Sbostic 30855856Sbostic printf("BLOCK INFOS\n"); 30955856Sbostic for (_bip = bip, i=0; i < *bcount; ++_bip, ++i) 31055856Sbostic PRINT_BINFO(_bip); 31155856Sbostic printf("INODE INFOS\n"); 31255856Sbostic for (_iip = iip, i=0; i < *icount; ++_iip, ++i) 31355856Sbostic PRINT_IINFO(1, _iip); 31455491Sbostic } 31555856Sbostic #endif 31655856Sbostic *blocks = bip; 31755856Sbostic *inodes = iip; 31855856Sbostic return (0); 31955856Sbostic 32055856Sbostic err1: free(bip); 32155856Sbostic err0: *bcount = 0; 32255856Sbostic *icount = 0; 32355856Sbostic return (-1); 32455491Sbostic 32555491Sbostic } 32655491Sbostic 32755491Sbostic /* 32855856Sbostic * This will parse a partial segment and fill in BLOCK_INFO structures 32955856Sbostic * for each block described in the segment summary. It will not include 33055856Sbostic * blocks or inodes from files with new version numbers. 33155491Sbostic */ 33255491Sbostic void 33355856Sbostic add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr) 33455491Sbostic FS_INFO *fsp; /* pointer to super block */ 33555856Sbostic BLOCK_INFO *bip; /* Block info array */ 33655856Sbostic int *countp; /* IN/OUT: number of blocks in array */ 33755856Sbostic SEGSUM *sp; /* segment summmary pointer */ 33855856Sbostic caddr_t seg_buf; /* buffer containing segment */ 33955856Sbostic daddr_t segaddr; /* address of this segment */ 34055856Sbostic daddr_t psegaddr; /* address of this partial segment */ 34155491Sbostic { 34255856Sbostic IFILE *ifp; 34355856Sbostic FINFO *fip; 34455856Sbostic caddr_t bp; 34555856Sbostic daddr_t *dp; 34655856Sbostic daddr_t *iaddrp; /* pointer to current inode block */ 34755856Sbostic int db_per_block, i, j; 34855856Sbostic u_long page_size; 34955491Sbostic 35055491Sbostic #ifdef VERBOSE 35155856Sbostic printf("FILE INFOS\n"); 35255491Sbostic #endif 35355856Sbostic db_per_block = fsbtodb(&fsp->fi_lfs, 1); 35455856Sbostic page_size = fsp->fi_lfs.lfs_bsize; 35555856Sbostic bp = seg_buf + datobyte(fsp, psegaddr - segaddr) + LFS_SUMMARY_SIZE; 35655856Sbostic bip += *countp; 35755856Sbostic psegaddr += bytetoda(fsp, LFS_SUMMARY_SIZE); 35855856Sbostic iaddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE); 35955856Sbostic --iaddrp; 36055856Sbostic for (fip = (FINFO *)(sp + 1), i = 0; i < sp->ss_nfinfo; 36155856Sbostic ++i, fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks])) { 36255491Sbostic 36355856Sbostic ifp = IFILE_ENTRY(&fsp->fi_lfs, fsp->fi_ifilep, fip->fi_ino); 36455856Sbostic PRINT_FINFO(fip, ifp); 36555856Sbostic if (ifp->if_version > fip->fi_version) 36655491Sbostic continue; 36755856Sbostic dp = &(fip->fi_blocks[0]); 36855856Sbostic for (j = 0; j < fip->fi_nblocks; j++, dp++) { 36955856Sbostic while (psegaddr == *iaddrp) { 37055856Sbostic psegaddr += db_per_block; 37155856Sbostic bp += page_size; 37255856Sbostic --iaddrp; 37355491Sbostic } 37455856Sbostic bip->bi_inode = fip->fi_ino; 37555856Sbostic bip->bi_lbn = *dp; 37655856Sbostic bip->bi_daddr = psegaddr; 37755856Sbostic bip->bi_segcreate = (time_t)(sp->ss_create); 37855856Sbostic bip->bi_bp = bp; 37955856Sbostic psegaddr += db_per_block; 38055856Sbostic bp += page_size; 38155856Sbostic ++bip; 38255856Sbostic ++(*countp); 38355491Sbostic } 38455491Sbostic } 38555491Sbostic } 38655491Sbostic 38755856Sbostic /* 38855856Sbostic * For a particular segment summary, reads the inode blocks and adds 38955856Sbostic * INODE_INFO structures to the array. Returns the number of inodes 39055856Sbostic * actually added. 39155856Sbostic */ 39255491Sbostic void 39355856Sbostic add_inodes (fsp, iip, countp, sp, seg_buf, seg_addr) 39455491Sbostic FS_INFO *fsp; /* pointer to super block */ 39555856Sbostic INODE_INFO *iip; 39655856Sbostic int *countp; /* pointer to current number of inodes */ 39755856Sbostic SEGSUM *sp; /* segsum pointer */ 39855491Sbostic caddr_t seg_buf; /* the buffer containing the segment's data */ 39955856Sbostic daddr_t seg_addr; /* disk address of seg_buf */ 40055491Sbostic { 40155856Sbostic struct dinode *di; 40255856Sbostic struct lfs *lfsp; 40355856Sbostic IFILE *ifp; 40455856Sbostic INODE_INFO *ip; 40555856Sbostic daddr_t *daddrp; 40655856Sbostic ino_t inum; 40755856Sbostic int i; 40855491Sbostic 40955856Sbostic if (sp->ss_ninos <= 0) 41055856Sbostic return; 41155491Sbostic 41255856Sbostic ip = iip + *countp; 41355856Sbostic lfsp = &fsp->fi_lfs; 41455491Sbostic #ifdef VERBOSE 41555856Sbostic (void) printf("INODE_INFOS:\n"); 41655491Sbostic #endif 41755856Sbostic daddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE); 41855856Sbostic for (i = 0; i < sp->ss_ninos; ++i) { 41955491Sbostic if (i % INOPB(lfsp) == 0) { 42055856Sbostic --daddrp; 42155856Sbostic di = (struct dinode *)(seg_buf + 42255856Sbostic ((*daddrp - seg_addr) << fsp->fi_daddr_shift)); 42355491Sbostic } else 42455491Sbostic ++di; 42555491Sbostic 42655491Sbostic inum = di->di_inum; 42755856Sbostic ip->ii_daddr = *daddrp; 42855856Sbostic ip->ii_inode = inum; 42955856Sbostic ip->ii_dinode = di; 43055856Sbostic ip->ii_segcreate = sp->ss_create; 43155491Sbostic 43255856Sbostic ifp = IFILE_ENTRY(lfsp, fsp->fi_ifilep, inum); 43355856Sbostic PRINT_IINFO(ifp->if_daddr == *daddrp, ip); 43455856Sbostic if (ifp->if_daddr == *daddrp) { 43555856Sbostic ip++; 43655856Sbostic ++(*countp); 43755491Sbostic } 43855491Sbostic } 43955491Sbostic } 44055491Sbostic 44155491Sbostic /* 44255856Sbostic * Checks the summary checksum and the data checksum to determine if the 44355856Sbostic * segment is valid or not. Returns the size of the partial segment if it 44455856Sbostic * is valid, * and 0 otherwise. Use dump_summary to figure out size of the 44555856Sbostic * the partial as well as whether or not the checksum is valid. 44655491Sbostic */ 44755491Sbostic int 44855491Sbostic pseg_valid (fsp, ssp) 44955491Sbostic FS_INFO *fsp; /* pointer to file system info */ 45055856Sbostic SEGSUM *ssp; /* pointer to segment summary block */ 45155491Sbostic { 45255491Sbostic caddr_t p; 45355856Sbostic int i, nblocks; 45455856Sbostic u_long *datap; 45555491Sbostic 45655856Sbostic if ((nblocks = dump_summary(&fsp->fi_lfs, ssp, 0, NULL)) <= 0) 45755856Sbostic return(0); 45855491Sbostic 45955856Sbostic /* check data/inode block(s) checksum too */ 46055856Sbostic datap = (u_long *)malloc(nblocks * sizeof(u_long)); 46155491Sbostic p = (caddr_t)ssp + LFS_SUMMARY_SIZE; 46255856Sbostic for (i = 0; i < nblocks; ++i) { 46355491Sbostic datap[i] = *((u_long *)p); 46455856Sbostic p += fsp->fi_lfs.lfs_bsize; 46555491Sbostic } 46655856Sbostic if (cksum ((void *)datap, nblocks * sizeof(u_long)) != ssp->ss_datasum) 46755856Sbostic return (0); 46855491Sbostic 46955856Sbostic return (nblocks); 47055491Sbostic } 47155491Sbostic 47255491Sbostic 47355491Sbostic /* #define MMAP_SEGMENT */ 47455491Sbostic /* 47555491Sbostic * read a segment into a memory buffer 47655491Sbostic */ 47755491Sbostic int 47855856Sbostic mmap_segment (fsp, segment, segbuf) 47955856Sbostic FS_INFO *fsp; /* file system information */ 48055856Sbostic int segment; /* segment number */ 48155856Sbostic caddr_t *segbuf; /* pointer to buffer area */ 48255491Sbostic { 48355856Sbostic struct lfs *lfsp; 48455856Sbostic int fid; /* fildes for file system device */ 48555856Sbostic daddr_t seg_daddr; /* base disk address of segment */ 48655856Sbostic off_t seg_byte; 48755856Sbostic size_t ssize; 48855856Sbostic char mntfromname[MNAMELEN+2]; 48955491Sbostic 49055856Sbostic lfsp = &fsp->fi_lfs; 49155856Sbostic 49255491Sbostic /* get the disk address of the beginning of the segment */ 49355491Sbostic seg_daddr = sntoda(lfsp, segment); 49455856Sbostic seg_byte = datobyte(fsp, seg_daddr); 49555856Sbostic ssize = seg_size(lfsp); 49655491Sbostic 49755491Sbostic strcpy(mntfromname, "/dev/r"); 49855856Sbostic strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5); 49955491Sbostic 50055491Sbostic if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) { 50155856Sbostic err(0, "mmap_segment: bad open"); 50255856Sbostic return (-1); 50355491Sbostic } 50455491Sbostic 50555491Sbostic #ifdef MMAP_SEGMENT 50655856Sbostic *segbuf = mmap ((caddr_t)0, seg_size(lfsp), PROT_READ, 50755856Sbostic MAP_FILE, fid, seg_byte); 50855856Sbostic if (*(long *)segbuf < 0) { 50955856Sbostic err(0, "mmap_segment: mmap failed"); 51055856Sbostic return (NULL); 51155491Sbostic } 51255491Sbostic #else /* MMAP_SEGMENT */ 51355856Sbostic #ifdef VERBOSE 51455856Sbostic printf("mmap_segment\tseg_daddr: %lu\tseg_size: %lu\tseg_offset: %qu\n", 51555856Sbostic seg_daddr, ssize, seg_byte); 51655856Sbostic #endif 51755491Sbostic /* malloc the space for the buffer */ 51855856Sbostic *segbuf = malloc(ssize); 51955856Sbostic if (!*segbuf) { 52055856Sbostic err(0, "mmap_segment: malloc failed"); 52155856Sbostic return(NULL); 52255856Sbostic } 52355491Sbostic 52455491Sbostic /* read the segment data into the buffer */ 52555856Sbostic if (lseek (fid, seg_byte, SEEK_SET) != seg_byte) { 52655856Sbostic err (0, "mmap_segment: bad lseek"); 52755856Sbostic free(*segbuf); 52855856Sbostic return (-1); 52955491Sbostic } 53055491Sbostic 53155856Sbostic if (read (fid, *segbuf, ssize) != ssize) { 53255856Sbostic err (0, "mmap_segment: bad read"); 53355856Sbostic free(*segbuf); 53455856Sbostic return (-1); 53555491Sbostic } 53655491Sbostic #endif /* MMAP_SEGMENT */ 53755491Sbostic close (fid); 53855491Sbostic 53955856Sbostic return (0); 54055491Sbostic } 54155491Sbostic 54255491Sbostic void 54355491Sbostic munmap_segment (fsp, seg_buf) 54455856Sbostic FS_INFO *fsp; /* file system information */ 54555856Sbostic caddr_t seg_buf; /* pointer to buffer area */ 54655491Sbostic { 54755491Sbostic #ifdef MMAP_SEGMENT 54855856Sbostic munmap (seg_buf, seg_size(&fsp->fi_lfs)); 54955491Sbostic #else /* MMAP_SEGMENT */ 55055491Sbostic free (seg_buf); 55155491Sbostic #endif /* MMAP_SEGMENT */ 55255491Sbostic } 55355491Sbostic 55455491Sbostic 55555491Sbostic /* 55655491Sbostic * USEFUL DEBUGGING TOOLS: 55755491Sbostic */ 55855491Sbostic void 55955856Sbostic print_SEGSUM (lfsp, p) 56055856Sbostic struct lfs *lfsp; 56155856Sbostic SEGSUM *p; 56255491Sbostic { 56355856Sbostic if (p) 56455856Sbostic (void) dump_summary(lfsp, p, DUMP_ALL, NULL); 56555491Sbostic else printf("0x0"); 56655491Sbostic fflush(stdout); 56755491Sbostic } 56855491Sbostic 56955856Sbostic int 57055856Sbostic bi_compare(a, b) 57155856Sbostic const void *a; 57255856Sbostic const void *b; 57355491Sbostic { 57455856Sbostic const BLOCK_INFO *ba, *bb; 57555856Sbostic int diff; 57655491Sbostic 57755856Sbostic ba = a; 57855856Sbostic bb = b; 57955491Sbostic 58055856Sbostic if (diff = (int)(ba->bi_inode - bb->bi_inode)) 58155856Sbostic return (diff); 58255856Sbostic if (diff = (int)(ba->bi_lbn - bb->bi_lbn)) 58355856Sbostic return (diff); 58455856Sbostic if (diff = (int)(ba->bi_segcreate - bb->bi_segcreate)) 58555856Sbostic return (diff); 58655856Sbostic diff = (int)(ba->bi_daddr - bb->bi_daddr); 58755856Sbostic return (diff); 58855856Sbostic } 58955491Sbostic 59055856Sbostic int 59155856Sbostic bi_toss(dummy, a, b) 59255856Sbostic const void *dummy; 59355856Sbostic const void *a; 59455856Sbostic const void *b; 59555491Sbostic { 59655856Sbostic const BLOCK_INFO *ba, *bb; 59755491Sbostic 59855856Sbostic ba = a; 59955856Sbostic bb = b; 60055856Sbostic 60155856Sbostic return(ba->bi_inode == bb->bi_inode && ba->bi_lbn == bb->bi_lbn); 60255491Sbostic } 60355491Sbostic 60455856Sbostic /* 60555856Sbostic * Right now, we never look at the actually data being 60655856Sbostic * passed to the kernel in iip->ii_dinode. Therefore, 60755856Sbostic * if the same inode appears twice in the same block 60855856Sbostic * (i.e. has the same disk address), it doesn't matter 60955856Sbostic * which entry we pass. However, if we get the kernel 61055856Sbostic * to start looking at the dinode, then we will care 61155856Sbostic * and we'll need some way to distinguish which inode 61255856Sbostic * is the more recent one. 61355856Sbostic */ 61455856Sbostic int 61555856Sbostic ii_compare(a, b) 61655856Sbostic const void *a; 61755856Sbostic const void *b; 61855491Sbostic { 61955856Sbostic const INODE_INFO *ia, *ib; 62055856Sbostic int diff; 62155491Sbostic 62255856Sbostic ia = a; 62355856Sbostic ib = b; 62455856Sbostic 62555856Sbostic if (diff = (int)(ia->ii_inode - ib->ii_inode)) 62655856Sbostic return (diff); 62755856Sbostic if (diff = (int)(ia->ii_segcreate - ib->ii_segcreate)) 62855856Sbostic return (diff); 62955856Sbostic diff = (int)(ia->ii_daddr - ib->ii_daddr); 63055856Sbostic return (diff); 63155491Sbostic } 63255491Sbostic 63355856Sbostic int 63455856Sbostic ii_toss(dummy, a, b) 63555856Sbostic const void *dummy; 63655856Sbostic const void *a; 63755856Sbostic const void *b; 63855491Sbostic { 63955856Sbostic const INODE_INFO *ia, *ib; 64055491Sbostic 64155856Sbostic ia = a; 64255856Sbostic ib = b; 64355856Sbostic 64455856Sbostic return(ia->ii_inode == ib->ii_inode); 64555491Sbostic } 64655491Sbostic 64755491Sbostic void 64855856Sbostic toss(p, nump, size, dotoss, client) 64955856Sbostic void *p; 65055856Sbostic int *nump; 65155856Sbostic size_t size; 65255856Sbostic int (*dotoss) __P((const void *, const void *, const void *)); 65355856Sbostic void *client; 65455491Sbostic { 65555856Sbostic int i; 65655856Sbostic void *p1; 65755491Sbostic 65855856Sbostic if (*nump == 0) 65955856Sbostic return; 66055491Sbostic 66155856Sbostic for (i = *nump; --i > 0;) { 66255856Sbostic p1 = p + size; 66355856Sbostic if (dotoss(client, p, p1)) { 66455856Sbostic bcopy(p1, p, i * size); 66555856Sbostic --(*nump); 66655856Sbostic } else 66755856Sbostic p += size; 66855491Sbostic } 66955491Sbostic } 670