155491Sbostic #include <sys/param.h> 255491Sbostic #include <sys/time.h> 355491Sbostic #include <sys/stat.h> 455491Sbostic #include <sys/mount.h> 555491Sbostic 655491Sbostic #include <ufs/ufs/dinode.h> 755491Sbostic #include <ufs/lfs/lfs.h> 855491Sbostic 955491Sbostic #include <fcntl.h> 1055491Sbostic #include <stdio.h> 1155491Sbostic #include <unistd.h> 12*55856Sbostic #include <stdlib.h> 13*55856Sbostic #include <string.h> 1455491Sbostic #include "clean.h" 1555491Sbostic 16*55856Sbostic void add_blocks __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t, 17*55856Sbostic daddr_t, daddr_t)); 18*55856Sbostic void add_inodes __P((FS_INFO *, INODE_INFO *, int *, SEGSUM *, caddr_t, 19*55856Sbostic daddr_t)); 20*55856Sbostic int bi_compare __P((const void *, const void *)); 21*55856Sbostic int bi_toss __P((const void *, const void *, const void *)); 22*55856Sbostic void get_ifile __P((FS_INFO *)); 23*55856Sbostic int get_superblock __P((FS_INFO *, struct lfs *)); 24*55856Sbostic int ii_compare __P((const void *, const void *)); 25*55856Sbostic int ii_toss __P((const void *, const void *, const void *)); 26*55856Sbostic int pseg_valid __P((FS_INFO *, SEGSUM *)); 27*55856Sbostic 2855491Sbostic /* 29*55856Sbostic * This function will get information on all mounted file systems 3055491Sbostic * of a given type. 3155491Sbostic */ 3255491Sbostic int 3355491Sbostic fs_getmntinfo(buf, type) 3455491Sbostic struct statfs **buf; 3555491Sbostic int type; 3655491Sbostic { 37*55856Sbostic struct statfs *tstatfsp; 38*55856Sbostic struct statfs *sbp; 39*55856Sbostic int count, i, tcount; 4055491Sbostic 4155491Sbostic tcount = getmntinfo(&tstatfsp, 0); 4255491Sbostic 4355491Sbostic if (tcount < 0) { 44*55856Sbostic err(0, "getmntinfo failed"); 45*55856Sbostic return (-1); 4655491Sbostic } 4755491Sbostic 48*55856Sbostic for (count = 0, i = 0; i < tcount ; ++i) 49*55856Sbostic if (tstatfsp[i].f_type == type) 50*55856Sbostic ++count; 5155491Sbostic 52*55856Sbostic if (count) { 53*55856Sbostic if (!(*buf = (struct statfs *) 54*55856Sbostic malloc(count * sizeof(struct statfs)))) 55*55856Sbostic err(1, "fs_getmntinfo: out of space"); 56*55856Sbostic for (i = 0, sbp = *buf; i < tcount ; ++i) { 57*55856Sbostic if (tstatfsp[i].f_type == type) { 58*55856Sbostic *sbp = tstatfsp[i]; 59*55856Sbostic ++sbp; 6055491Sbostic } 6155491Sbostic } 6255491Sbostic } 63*55856Sbostic return (count); 6455491Sbostic } 6555491Sbostic 6655491Sbostic /* 67*55856Sbostic * Get all the information available on an LFS file system. 68*55856Sbostic * Returns an array of FS_INFO structures, NULL on error. 6955491Sbostic */ 70*55856Sbostic FS_INFO * 71*55856Sbostic get_fs_info (lstatfsp, count) 72*55856Sbostic struct statfs *lstatfsp; /* IN: array of statfs structs */ 73*55856Sbostic int count; /* IN: number of file systems */ 7455491Sbostic { 75*55856Sbostic FS_INFO *fp, *fsp; 7655491Sbostic int i; 7755491Sbostic 78*55856Sbostic fsp = (FS_INFO *)malloc(count * sizeof(FS_INFO)); 7955491Sbostic 80*55856Sbostic for (fp = fsp, i = 0; i < count; ++i, ++fp) { 81*55856Sbostic fp->fi_statfsp = lstatfsp++; 82*55856Sbostic if (get_superblock (fp, &fp->fi_lfs)) 83*55856Sbostic err(1, "get_fs_info: get_superblock failed"); 84*55856Sbostic fp->fi_daddr_shift = 85*55856Sbostic fp->fi_lfs.lfs_bshift - fp->fi_lfs.lfs_fsbtodb; 86*55856Sbostic get_ifile (fp); 8755491Sbostic } 88*55856Sbostic return (fsp); 8955491Sbostic } 9055491Sbostic 91*55856Sbostic /* 92*55856Sbostic * If we are reading the ifile then we need to refresh it. Even if 93*55856Sbostic * we are mmapping it, it might have grown. Finally, we need to 94*55856Sbostic * refresh the file system information (statfs) info. 95*55856Sbostic */ 9655491Sbostic void 97*55856Sbostic reread_fs_info(fsp, count) 98*55856Sbostic FS_INFO *fsp; /* IN: array of fs_infos to free */ 99*55856Sbostic int count; /* IN: number of file systems */ 10055491Sbostic { 101*55856Sbostic int i; 10255491Sbostic 103*55856Sbostic for (i = 0; i < count; ++i, ++fsp) { 104*55856Sbostic if (statfs(fsp->fi_statfsp->f_mntonname, fsp->fi_statfsp)) 105*55856Sbostic err(0, "reread_fs_info: statfs failed"); 106*55856Sbostic #ifdef MMAP_WORKS 107*55856Sbostic if (munmap(fsp->fi_cip, fsp->fi_ifile_length) < 0) 108*55856Sbostic err(0, "reread_fs_info: munmap failed"); 10955491Sbostic #else 110*55856Sbostic free (fsp->fi_cip); 11155491Sbostic #endif /* MMAP_WORKS */ 112*55856Sbostic get_ifile (fsp); 11355491Sbostic } 11455491Sbostic } 11555491Sbostic 11655491Sbostic /* 117*55856Sbostic * Gets the superblock from disk (possibly in face of errors) 11855491Sbostic */ 11955491Sbostic int 12055491Sbostic get_superblock (fsp, sbp) 121*55856Sbostic FS_INFO *fsp; /* local file system info structure */ 122*55856Sbostic struct lfs *sbp; 12355491Sbostic { 124*55856Sbostic char mntfromname[MNAMELEN+1]; 125*55856Sbostic int fid; 12655491Sbostic 12755491Sbostic strcpy(mntfromname, "/dev/r"); 128*55856Sbostic strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5); 12955491Sbostic 13055491Sbostic if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) { 131*55856Sbostic err(0, "get_superblock: bad open"); 132*55856Sbostic return (-1); 13355491Sbostic } 13455491Sbostic 135*55856Sbostic get(fid, LFS_LABELPAD, sbp, sizeof(struct lfs)); 13655491Sbostic close (fid); 13755491Sbostic 138*55856Sbostic return (0); 13955491Sbostic } 14055491Sbostic 14155491Sbostic /* 142*55856Sbostic * This function will map the ifile into memory. It causes a 143*55856Sbostic * fatal error on failure. 14455491Sbostic */ 145*55856Sbostic void 14655491Sbostic get_ifile (fsp) 14755491Sbostic FS_INFO *fsp; 14855491Sbostic { 149*55856Sbostic struct stat file_stat; 150*55856Sbostic caddr_t ifp; 151*55856Sbostic char *ifile_name; 152*55856Sbostic int count, fid; 15355491Sbostic 154*55856Sbostic ifp = NULL; 155*55856Sbostic sync(); 156*55856Sbostic ifile_name = malloc(strlen(fsp->fi_statfsp->f_mntonname) + 157*55856Sbostic strlen(IFILE_NAME)+2); 158*55856Sbostic strcat(strcat(strcpy(ifile_name, fsp->fi_statfsp->f_mntonname), "/"), 159*55856Sbostic IFILE_NAME); 16055491Sbostic 161*55856Sbostic if ((fid = open(ifile_name, O_RDWR, (mode_t)0)) < 0) 162*55856Sbostic err(1, "get_ifile: bad open"); 16355491Sbostic 164*55856Sbostic if (fstat (fid, &file_stat)) 165*55856Sbostic err(1, "get_ifile: fstat failed"); 16655491Sbostic 167*55856Sbostic fsp->fi_ifile_length = file_stat.st_size; 168*55856Sbostic 16955491Sbostic /* get the ifile */ 17055491Sbostic #ifndef MMAP_WORKS 171*55856Sbostic if (!(ifp = malloc ((size_t)fsp->fi_ifile_length))) 172*55856Sbostic err (1, "get_ifile: malloc failed"); 173*55856Sbostic redo_read: 174*55856Sbostic count = read (fid, ifp, (size_t) fsp->fi_ifile_length); 17555491Sbostic 176*55856Sbostic if (count < 0) 177*55856Sbostic err(1, "get_ifile: bad ifile read"); 178*55856Sbostic else if (count < (int)fsp->fi_ifile_length) { 179*55856Sbostic err(0, "get_ifile"); 180*55856Sbostic if (lseek(fid, 0, SEEK_SET) < 0) 181*55856Sbostic err(1, "get_ifile: bad ifile lseek"); 182*55856Sbostic goto redo_read; 18355491Sbostic } 18455491Sbostic #else /* MMAP_WORKS */ 185*55856Sbostic ifp = mmap ((caddr_t)0, (size_t) fsp->fi_ifile_length, PROT_READ|PROT_WRITE, 18655491Sbostic MAP_FILE|MAP_SHARED, fid, (off_t)0); 187*55856Sbostic if (ifp < 0) 188*55856Sbostic err(1, "get_ifile: mmap failed"); 18955491Sbostic #endif /* MMAP_WORKS */ 19055491Sbostic 19155491Sbostic close (fid); 19255491Sbostic 193*55856Sbostic fsp->fi_cip = (CLEANERINFO *)ifp; 194*55856Sbostic fsp->fi_segusep = (SEGUSE *)(ifp + CLEANSIZE(fsp)); 195*55856Sbostic fsp->fi_ifilep = (IFILE *)((caddr_t)fsp->fi_segusep + SEGTABSIZE(fsp)); 196*55856Sbostic 197*55856Sbostic /* 198*55856Sbostic * The number of ifile entries is equal to the number of blocks 199*55856Sbostic * blocks in the ifile minus the ones allocated to cleaner info 200*55856Sbostic * and segment usage table multiplied by the number of ifile 201*55856Sbostic * entries per page. 202*55856Sbostic */ 203*55856Sbostic fsp->fi_ifile_count = (fsp->fi_ifile_length >> fsp->fi_lfs.lfs_bshift - 204*55856Sbostic fsp->fi_lfs.lfs_cleansz - fsp->fi_lfs.lfs_segtabsz) * 205*55856Sbostic fsp->fi_lfs.lfs_ifpb; 206*55856Sbostic 20755491Sbostic free (ifile_name); 20855491Sbostic } 20955491Sbostic 21055491Sbostic /* 211*55856Sbostic * This function will scan a segment and return a list of 21255491Sbostic * <inode, blocknum> pairs which indicate which blocks were 213*55856Sbostic * contained as live data within the segment when the segment 214*55856Sbostic * summary was read (it may have "died" since then). Any given 215*55856Sbostic * pair will be listed at most once. 21655491Sbostic */ 21755491Sbostic int 21855491Sbostic lfs_segmapv(fsp, seg, seg_buf, blocks, bcount, inodes, icount) 219*55856Sbostic FS_INFO *fsp; /* pointer to local file system information */ 220*55856Sbostic int seg; /* the segment number */ 221*55856Sbostic caddr_t seg_buf; /* the buffer containing the segment's data */ 222*55856Sbostic BLOCK_INFO **blocks; /* OUT: array of block_info for live blocks */ 223*55856Sbostic int *bcount; /* OUT: number of active blocks in segment */ 224*55856Sbostic INODE_INFO **inodes; /* OUT: array of inode_info for live inodes */ 225*55856Sbostic int *icount; /* OUT: number of active inodes in segment */ 22655491Sbostic { 227*55856Sbostic BLOCK_INFO *bip; 228*55856Sbostic INODE_INFO *iip; 229*55856Sbostic SEGSUM *sp; 230*55856Sbostic SEGUSE *sup; 231*55856Sbostic struct lfs *lfsp; 232*55856Sbostic caddr_t s, segend; 233*55856Sbostic daddr_t pseg_addr, seg_addr; 234*55856Sbostic int nblocks, num_iblocks; 235*55856Sbostic time_t timestamp; 23655491Sbostic 237*55856Sbostic lfsp = &fsp->fi_lfs; 238*55856Sbostic num_iblocks = lfsp->lfs_ssize; 239*55856Sbostic if (!(bip = malloc(lfsp->lfs_ssize * sizeof(BLOCK_INFO)))) 240*55856Sbostic goto err0; 241*55856Sbostic if (!(iip = malloc(lfsp->lfs_ssize * sizeof(INODE_INFO)))) 242*55856Sbostic goto err1; 24355491Sbostic 244*55856Sbostic sup = SEGUSE_ENTRY(lfsp, fsp->fi_segusep, seg); 245*55856Sbostic s = seg_buf + (sup->su_flags & SEGUSE_SUPERBLOCK ? LFS_SBPAD : 0); 246*55856Sbostic seg_addr = sntoda(lfsp, seg); 247*55856Sbostic pseg_addr = seg_addr + (sup->su_flags & SEGUSE_SUPERBLOCK ? btodb(LFS_SBPAD) : 0); 248*55856Sbostic #ifdef VERBOSE 249*55856Sbostic printf("\tsegment buffer at: 0x%x\tseg_addr 0x%x\n", s, seg_addr); 250*55856Sbostic #endif /* VERBOSE */ 25155491Sbostic 252*55856Sbostic *bcount = 0; 253*55856Sbostic *icount = 0; 254*55856Sbostic for (segend = seg_buf + seg_size(lfsp), timestamp = 0; s < segend; ) { 255*55856Sbostic sp = (SEGSUM *)s; 25655491Sbostic #ifdef VERBOSE 257*55856Sbostic printf("\tpartial at: 0x%x\n", pseg_addr); 258*55856Sbostic print_SEGSUM(lfsp, sp); 25955491Sbostic fflush(stdout); 26055491Sbostic #endif /* VERBOSE */ 26155491Sbostic 262*55856Sbostic nblocks = pseg_valid(fsp, sp); 263*55856Sbostic if (nblocks <= 0) 264*55856Sbostic break; 26555491Sbostic 266*55856Sbostic /* Check if we have hit old data */ 267*55856Sbostic if (timestamp > ((SEGSUM*)s)->ss_create) 268*55856Sbostic break; 26955491Sbostic timestamp = ((SEGSUM*)s)->ss_create; 27055491Sbostic 271*55856Sbostic /* 272*55856Sbostic * Right now we die if we run out of room, we could probably 273*55856Sbostic * recover if we were smart. 274*55856Sbostic */ 275*55856Sbostic if (*icount + sp->ss_ninos > num_iblocks) { 276*55856Sbostic num_iblocks = *icount + sp->ss_ninos; 277*55856Sbostic iip = realloc (iip, num_iblocks * sizeof(INODE_INFO)); 278*55856Sbostic if (!iip) 279*55856Sbostic goto err1; 280*55856Sbostic } 281*55856Sbostic add_inodes(fsp, iip, icount, sp, seg_buf, seg_addr); 282*55856Sbostic add_blocks(fsp, bip, bcount, sp, seg_buf, seg_addr, pseg_addr); 283*55856Sbostic pseg_addr += fsbtodb(lfsp, nblocks) + 284*55856Sbostic bytetoda(fsp, LFS_SUMMARY_SIZE); 285*55856Sbostic s += (nblocks << lfsp->lfs_bshift) + LFS_SUMMARY_SIZE; 286*55856Sbostic } 287*55856Sbostic qsort(iip, *icount, sizeof(INODE_INFO), ii_compare); 288*55856Sbostic qsort(bip, *bcount, sizeof(BLOCK_INFO), bi_compare); 289*55856Sbostic toss(iip, icount, sizeof(INODE_INFO), ii_toss, NULL); 290*55856Sbostic toss(bip, bcount, sizeof(BLOCK_INFO), bi_toss, NULL); 291*55856Sbostic #ifdef VERBOSE 292*55856Sbostic { 293*55856Sbostic BLOCK_INFO *_bip; 294*55856Sbostic INODE_INFO *_iip; 295*55856Sbostic int i; 29655491Sbostic 297*55856Sbostic printf("BLOCK INFOS\n"); 298*55856Sbostic for (_bip = bip, i=0; i < *bcount; ++_bip, ++i) 299*55856Sbostic PRINT_BINFO(_bip); 300*55856Sbostic printf("INODE INFOS\n"); 301*55856Sbostic for (_iip = iip, i=0; i < *icount; ++_iip, ++i) 302*55856Sbostic PRINT_IINFO(1, _iip); 30355491Sbostic } 304*55856Sbostic #endif 305*55856Sbostic *blocks = bip; 306*55856Sbostic *inodes = iip; 307*55856Sbostic return (0); 308*55856Sbostic 309*55856Sbostic err1: free(bip); 310*55856Sbostic err0: *bcount = 0; 311*55856Sbostic *icount = 0; 312*55856Sbostic return (-1); 31355491Sbostic 31455491Sbostic } 31555491Sbostic 31655491Sbostic /* 317*55856Sbostic * This will parse a partial segment and fill in BLOCK_INFO structures 318*55856Sbostic * for each block described in the segment summary. It will not include 319*55856Sbostic * blocks or inodes from files with new version numbers. 32055491Sbostic */ 32155491Sbostic void 322*55856Sbostic add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr) 32355491Sbostic FS_INFO *fsp; /* pointer to super block */ 324*55856Sbostic BLOCK_INFO *bip; /* Block info array */ 325*55856Sbostic int *countp; /* IN/OUT: number of blocks in array */ 326*55856Sbostic SEGSUM *sp; /* segment summmary pointer */ 327*55856Sbostic caddr_t seg_buf; /* buffer containing segment */ 328*55856Sbostic daddr_t segaddr; /* address of this segment */ 329*55856Sbostic daddr_t psegaddr; /* address of this partial segment */ 33055491Sbostic { 331*55856Sbostic IFILE *ifp; 332*55856Sbostic FINFO *fip; 333*55856Sbostic caddr_t bp; 334*55856Sbostic daddr_t *dp; 335*55856Sbostic daddr_t *iaddrp; /* pointer to current inode block */ 336*55856Sbostic int db_per_block, i, j; 337*55856Sbostic u_long page_size; 33855491Sbostic 33955491Sbostic #ifdef VERBOSE 340*55856Sbostic printf("FILE INFOS\n"); 34155491Sbostic #endif 342*55856Sbostic db_per_block = fsbtodb(&fsp->fi_lfs, 1); 343*55856Sbostic page_size = fsp->fi_lfs.lfs_bsize; 344*55856Sbostic bp = seg_buf + datobyte(fsp, psegaddr - segaddr) + LFS_SUMMARY_SIZE; 345*55856Sbostic bip += *countp; 346*55856Sbostic psegaddr += bytetoda(fsp, LFS_SUMMARY_SIZE); 347*55856Sbostic iaddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE); 348*55856Sbostic --iaddrp; 349*55856Sbostic for (fip = (FINFO *)(sp + 1), i = 0; i < sp->ss_nfinfo; 350*55856Sbostic ++i, fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks])) { 35155491Sbostic 352*55856Sbostic ifp = IFILE_ENTRY(&fsp->fi_lfs, fsp->fi_ifilep, fip->fi_ino); 353*55856Sbostic PRINT_FINFO(fip, ifp); 354*55856Sbostic if (ifp->if_version > fip->fi_version) 35555491Sbostic continue; 356*55856Sbostic dp = &(fip->fi_blocks[0]); 357*55856Sbostic for (j = 0; j < fip->fi_nblocks; j++, dp++) { 358*55856Sbostic while (psegaddr == *iaddrp) { 359*55856Sbostic psegaddr += db_per_block; 360*55856Sbostic bp += page_size; 361*55856Sbostic --iaddrp; 36255491Sbostic } 363*55856Sbostic bip->bi_inode = fip->fi_ino; 364*55856Sbostic bip->bi_lbn = *dp; 365*55856Sbostic bip->bi_daddr = psegaddr; 366*55856Sbostic bip->bi_segcreate = (time_t)(sp->ss_create); 367*55856Sbostic bip->bi_bp = bp; 368*55856Sbostic psegaddr += db_per_block; 369*55856Sbostic bp += page_size; 370*55856Sbostic ++bip; 371*55856Sbostic ++(*countp); 37255491Sbostic } 37355491Sbostic } 37455491Sbostic } 37555491Sbostic 376*55856Sbostic /* 377*55856Sbostic * For a particular segment summary, reads the inode blocks and adds 378*55856Sbostic * INODE_INFO structures to the array. Returns the number of inodes 379*55856Sbostic * actually added. 380*55856Sbostic */ 38155491Sbostic void 382*55856Sbostic add_inodes (fsp, iip, countp, sp, seg_buf, seg_addr) 38355491Sbostic FS_INFO *fsp; /* pointer to super block */ 384*55856Sbostic INODE_INFO *iip; 385*55856Sbostic int *countp; /* pointer to current number of inodes */ 386*55856Sbostic SEGSUM *sp; /* segsum pointer */ 38755491Sbostic caddr_t seg_buf; /* the buffer containing the segment's data */ 388*55856Sbostic daddr_t seg_addr; /* disk address of seg_buf */ 38955491Sbostic { 390*55856Sbostic struct dinode *di; 391*55856Sbostic struct lfs *lfsp; 392*55856Sbostic IFILE *ifp; 393*55856Sbostic INODE_INFO *ip; 394*55856Sbostic daddr_t *daddrp; 395*55856Sbostic ino_t inum; 396*55856Sbostic int i; 39755491Sbostic 398*55856Sbostic if (sp->ss_ninos <= 0) 399*55856Sbostic return; 40055491Sbostic 401*55856Sbostic ip = iip + *countp; 402*55856Sbostic lfsp = &fsp->fi_lfs; 40355491Sbostic #ifdef VERBOSE 404*55856Sbostic (void) printf("INODE_INFOS:\n"); 40555491Sbostic #endif 406*55856Sbostic daddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE); 407*55856Sbostic for (i = 0; i < sp->ss_ninos; ++i) { 40855491Sbostic if (i % INOPB(lfsp) == 0) { 409*55856Sbostic --daddrp; 410*55856Sbostic di = (struct dinode *)(seg_buf + 411*55856Sbostic ((*daddrp - seg_addr) << fsp->fi_daddr_shift)); 41255491Sbostic } else 41355491Sbostic ++di; 41455491Sbostic 41555491Sbostic inum = di->di_inum; 416*55856Sbostic ip->ii_daddr = *daddrp; 417*55856Sbostic ip->ii_inode = inum; 418*55856Sbostic ip->ii_dinode = di; 419*55856Sbostic ip->ii_segcreate = sp->ss_create; 42055491Sbostic 421*55856Sbostic ifp = IFILE_ENTRY(lfsp, fsp->fi_ifilep, inum); 422*55856Sbostic PRINT_IINFO(ifp->if_daddr == *daddrp, ip); 423*55856Sbostic if (ifp->if_daddr == *daddrp) { 424*55856Sbostic ip++; 425*55856Sbostic ++(*countp); 42655491Sbostic } 42755491Sbostic } 42855491Sbostic } 42955491Sbostic 43055491Sbostic /* 431*55856Sbostic * Checks the summary checksum and the data checksum to determine if the 432*55856Sbostic * segment is valid or not. Returns the size of the partial segment if it 433*55856Sbostic * is valid, * and 0 otherwise. Use dump_summary to figure out size of the 434*55856Sbostic * the partial as well as whether or not the checksum is valid. 43555491Sbostic */ 43655491Sbostic int 43755491Sbostic pseg_valid (fsp, ssp) 43855491Sbostic FS_INFO *fsp; /* pointer to file system info */ 439*55856Sbostic SEGSUM *ssp; /* pointer to segment summary block */ 44055491Sbostic { 44155491Sbostic caddr_t p; 442*55856Sbostic int i, nblocks; 443*55856Sbostic u_long *datap; 44455491Sbostic 445*55856Sbostic if ((nblocks = dump_summary(&fsp->fi_lfs, ssp, 0, NULL)) <= 0) 446*55856Sbostic return(0); 44755491Sbostic 448*55856Sbostic /* check data/inode block(s) checksum too */ 449*55856Sbostic datap = (u_long *)malloc(nblocks * sizeof(u_long)); 45055491Sbostic p = (caddr_t)ssp + LFS_SUMMARY_SIZE; 451*55856Sbostic for (i = 0; i < nblocks; ++i) { 45255491Sbostic datap[i] = *((u_long *)p); 453*55856Sbostic p += fsp->fi_lfs.lfs_bsize; 45455491Sbostic } 455*55856Sbostic if (cksum ((void *)datap, nblocks * sizeof(u_long)) != ssp->ss_datasum) 456*55856Sbostic return (0); 45755491Sbostic 458*55856Sbostic return (nblocks); 45955491Sbostic } 46055491Sbostic 46155491Sbostic 46255491Sbostic /* #define MMAP_SEGMENT */ 46355491Sbostic /* 46455491Sbostic * read a segment into a memory buffer 46555491Sbostic */ 46655491Sbostic int 467*55856Sbostic mmap_segment (fsp, segment, segbuf) 468*55856Sbostic FS_INFO *fsp; /* file system information */ 469*55856Sbostic int segment; /* segment number */ 470*55856Sbostic caddr_t *segbuf; /* pointer to buffer area */ 47155491Sbostic { 472*55856Sbostic struct lfs *lfsp; 473*55856Sbostic int fid; /* fildes for file system device */ 474*55856Sbostic daddr_t seg_daddr; /* base disk address of segment */ 475*55856Sbostic off_t seg_byte; 476*55856Sbostic size_t ssize; 477*55856Sbostic char mntfromname[MNAMELEN+2]; 47855491Sbostic 479*55856Sbostic lfsp = &fsp->fi_lfs; 480*55856Sbostic 48155491Sbostic /* get the disk address of the beginning of the segment */ 48255491Sbostic seg_daddr = sntoda(lfsp, segment); 483*55856Sbostic seg_byte = datobyte(fsp, seg_daddr); 484*55856Sbostic ssize = seg_size(lfsp); 48555491Sbostic 48655491Sbostic strcpy(mntfromname, "/dev/r"); 487*55856Sbostic strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5); 48855491Sbostic 48955491Sbostic if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) { 490*55856Sbostic err(0, "mmap_segment: bad open"); 491*55856Sbostic return (-1); 49255491Sbostic } 49355491Sbostic 49455491Sbostic #ifdef MMAP_SEGMENT 495*55856Sbostic *segbuf = mmap ((caddr_t)0, seg_size(lfsp), PROT_READ, 496*55856Sbostic MAP_FILE, fid, seg_byte); 497*55856Sbostic if (*(long *)segbuf < 0) { 498*55856Sbostic err(0, "mmap_segment: mmap failed"); 499*55856Sbostic return (NULL); 50055491Sbostic } 50155491Sbostic #else /* MMAP_SEGMENT */ 502*55856Sbostic #ifdef VERBOSE 503*55856Sbostic printf("mmap_segment\tseg_daddr: %lu\tseg_size: %lu\tseg_offset: %qu\n", 504*55856Sbostic seg_daddr, ssize, seg_byte); 505*55856Sbostic #endif 50655491Sbostic /* malloc the space for the buffer */ 507*55856Sbostic *segbuf = malloc(ssize); 508*55856Sbostic if (!*segbuf) { 509*55856Sbostic err(0, "mmap_segment: malloc failed"); 510*55856Sbostic return(NULL); 511*55856Sbostic } 51255491Sbostic 51355491Sbostic /* read the segment data into the buffer */ 514*55856Sbostic if (lseek (fid, seg_byte, SEEK_SET) != seg_byte) { 515*55856Sbostic err (0, "mmap_segment: bad lseek"); 516*55856Sbostic free(*segbuf); 517*55856Sbostic return (-1); 51855491Sbostic } 51955491Sbostic 520*55856Sbostic if (read (fid, *segbuf, ssize) != ssize) { 521*55856Sbostic err (0, "mmap_segment: bad read"); 522*55856Sbostic free(*segbuf); 523*55856Sbostic return (-1); 52455491Sbostic } 52555491Sbostic #endif /* MMAP_SEGMENT */ 52655491Sbostic close (fid); 52755491Sbostic 528*55856Sbostic return (0); 52955491Sbostic } 53055491Sbostic 53155491Sbostic void 53255491Sbostic munmap_segment (fsp, seg_buf) 533*55856Sbostic FS_INFO *fsp; /* file system information */ 534*55856Sbostic caddr_t seg_buf; /* pointer to buffer area */ 53555491Sbostic { 53655491Sbostic #ifdef MMAP_SEGMENT 537*55856Sbostic munmap (seg_buf, seg_size(&fsp->fi_lfs)); 53855491Sbostic #else /* MMAP_SEGMENT */ 53955491Sbostic free (seg_buf); 54055491Sbostic #endif /* MMAP_SEGMENT */ 54155491Sbostic } 54255491Sbostic 54355491Sbostic 54455491Sbostic /* 54555491Sbostic * USEFUL DEBUGGING TOOLS: 54655491Sbostic */ 54755491Sbostic void 548*55856Sbostic print_SEGSUM (lfsp, p) 549*55856Sbostic struct lfs *lfsp; 550*55856Sbostic SEGSUM *p; 55155491Sbostic { 552*55856Sbostic if (p) 553*55856Sbostic (void) dump_summary(lfsp, p, DUMP_ALL, NULL); 55455491Sbostic else printf("0x0"); 55555491Sbostic fflush(stdout); 55655491Sbostic } 55755491Sbostic 558*55856Sbostic int 559*55856Sbostic bi_compare(a, b) 560*55856Sbostic const void *a; 561*55856Sbostic const void *b; 56255491Sbostic { 563*55856Sbostic const BLOCK_INFO *ba, *bb; 564*55856Sbostic int diff; 56555491Sbostic 566*55856Sbostic ba = a; 567*55856Sbostic bb = b; 56855491Sbostic 569*55856Sbostic if (diff = (int)(ba->bi_inode - bb->bi_inode)) 570*55856Sbostic return (diff); 571*55856Sbostic if (diff = (int)(ba->bi_lbn - bb->bi_lbn)) 572*55856Sbostic return (diff); 573*55856Sbostic if (diff = (int)(ba->bi_segcreate - bb->bi_segcreate)) 574*55856Sbostic return (diff); 575*55856Sbostic diff = (int)(ba->bi_daddr - bb->bi_daddr); 576*55856Sbostic return (diff); 577*55856Sbostic } 57855491Sbostic 579*55856Sbostic int 580*55856Sbostic bi_toss(dummy, a, b) 581*55856Sbostic const void *dummy; 582*55856Sbostic const void *a; 583*55856Sbostic const void *b; 58455491Sbostic { 585*55856Sbostic const BLOCK_INFO *ba, *bb; 58655491Sbostic 587*55856Sbostic ba = a; 588*55856Sbostic bb = b; 589*55856Sbostic 590*55856Sbostic return(ba->bi_inode == bb->bi_inode && ba->bi_lbn == bb->bi_lbn); 59155491Sbostic } 59255491Sbostic 593*55856Sbostic /* 594*55856Sbostic * Right now, we never look at the actually data being 595*55856Sbostic * passed to the kernel in iip->ii_dinode. Therefore, 596*55856Sbostic * if the same inode appears twice in the same block 597*55856Sbostic * (i.e. has the same disk address), it doesn't matter 598*55856Sbostic * which entry we pass. However, if we get the kernel 599*55856Sbostic * to start looking at the dinode, then we will care 600*55856Sbostic * and we'll need some way to distinguish which inode 601*55856Sbostic * is the more recent one. 602*55856Sbostic */ 603*55856Sbostic int 604*55856Sbostic ii_compare(a, b) 605*55856Sbostic const void *a; 606*55856Sbostic const void *b; 60755491Sbostic { 608*55856Sbostic const INODE_INFO *ia, *ib; 609*55856Sbostic int diff; 61055491Sbostic 611*55856Sbostic ia = a; 612*55856Sbostic ib = b; 613*55856Sbostic 614*55856Sbostic if (diff = (int)(ia->ii_inode - ib->ii_inode)) 615*55856Sbostic return (diff); 616*55856Sbostic if (diff = (int)(ia->ii_segcreate - ib->ii_segcreate)) 617*55856Sbostic return (diff); 618*55856Sbostic diff = (int)(ia->ii_daddr - ib->ii_daddr); 619*55856Sbostic return (diff); 62055491Sbostic } 62155491Sbostic 622*55856Sbostic int 623*55856Sbostic ii_toss(dummy, a, b) 624*55856Sbostic const void *dummy; 625*55856Sbostic const void *a; 626*55856Sbostic const void *b; 62755491Sbostic { 628*55856Sbostic const INODE_INFO *ia, *ib; 62955491Sbostic 630*55856Sbostic ia = a; 631*55856Sbostic ib = b; 632*55856Sbostic 633*55856Sbostic return(ia->ii_inode == ib->ii_inode); 63455491Sbostic } 63555491Sbostic 63655491Sbostic void 637*55856Sbostic toss(p, nump, size, dotoss, client) 638*55856Sbostic void *p; 639*55856Sbostic int *nump; 640*55856Sbostic size_t size; 641*55856Sbostic int (*dotoss) __P((const void *, const void *, const void *)); 642*55856Sbostic void *client; 64355491Sbostic { 644*55856Sbostic int i; 645*55856Sbostic void *p1; 64655491Sbostic 647*55856Sbostic if (*nump == 0) 648*55856Sbostic return; 64955491Sbostic 650*55856Sbostic for (i = *nump; --i > 0;) { 651*55856Sbostic p1 = p + size; 652*55856Sbostic if (dotoss(client, p, p1)) { 653*55856Sbostic bcopy(p1, p, i * size); 654*55856Sbostic --(*nump); 655*55856Sbostic } else 656*55856Sbostic p += size; 65755491Sbostic } 65855491Sbostic } 659