1 2 #include <sys/param.h> 3 #include <sys/time.h> 4 #include <sys/uio.h> 5 #include <sys/vnode.h> 6 #include <sys/stat.h> 7 #include <sys/mount.h> 8 9 #include <ufs/ufs/dinode.h> 10 #include <ufs/lfs/lfs.h> 11 #include <ufs/lfs/lfs_extern.h> 12 13 #include <fcntl.h> 14 #include <stdio.h> 15 #include <unistd.h> 16 #include "clean.h" 17 18 /* 19 * fs_getmntinfo: 20 * 21 * This function will get information on all mounted file systems 22 * of a given type. 23 */ 24 int 25 fs_getmntinfo(buf, type) 26 struct statfs **buf; 27 int type; 28 { 29 int i; 30 int count; 31 int tcount; 32 struct statfs *tstatfsp; 33 34 tcount = getmntinfo(&tstatfsp, 0); 35 36 if (tcount < 0) { 37 perror ("fs_getmntinfo: getmntinfo failed"); 38 return -1; 39 } 40 41 for (count = 0, i = 0 ; i < tcount ; i ++) 42 if (type == 0 || tstatfsp[i].f_type == type) 43 ++ count; 44 45 if (count > 0) { 46 *buf = (struct statfs *) 47 malloc(count*sizeof(struct statfs)); 48 if (*buf == 0) { perror ("fs_getmntinfo: out of space"); exit (1); } 49 for (i = 0, count = 0 ; i < tcount ; i ++) { 50 if (type == 0 || tstatfsp[i].f_type == type) { 51 (*buf)[count] = tstatfsp[i]; 52 ++count; 53 } 54 } 55 return count; 56 } 57 return 0; 58 } 59 60 /* 61 * get_fs_info: 62 * 63 * get all the information available on a file system 64 */ 65 int 66 get_fs_info (lstatfsp, fspp, count) 67 struct statfs *lstatfsp; /* IN: array of statfs structs */ 68 FS_INFO **fspp; /* OUT: resulting array of FS_INFOs */ 69 int count; /* IN: number of file systems */ 70 { 71 int i; 72 caddr_t ifp; 73 FS_INFO *fsp; 74 75 *fspp = (FS_INFO *)malloc(count * sizeof(FS_INFO)); 76 77 for (i = 0 ; i < count ; i++) { 78 fsp = *fspp + i; 79 statfsp = lstatfsp + i; 80 lfsp = (struct lfs *)malloc (LFS_SBPAD); 81 if (get_superblock (fsp, lfsp) < 0) { 82 perror("get_fs_info: get_superblock failed"); 83 return -1; 84 } 85 fsp->fi_daddr_shift = lfsp->lfs_bshift - lfsp->lfs_fsbtodb; 86 if (get_ifile (fsp) < 0) { 87 perror("get_fs_info: get_ifile failed"); 88 return -1; 89 } 90 } 91 return 0; 92 } 93 94 /* this is needed temporarily, because of the bug in mmap'ed files */ 95 void 96 free_fs_info (fsp, count) 97 FS_INFO *fsp; /* IN: array of fs_infos we will dispose of */ 98 int count; /* IN: number of file systems */ 99 { 100 int i; 101 caddr_t fsp_base = (caddr_t)fsp; 102 103 for (i = 0 ; i < count ; i++, fsp++) { 104 /* free superblock */ 105 free (lfsp); 106 /* sdp points to the beginning of the ifile area */ 107 #ifndef MMAP_WORKS 108 free (cip); 109 #else 110 if (munmap (cip, ifile_length) < 0) { 111 perror("free_fs_info: munmap failed\n"); 112 } 113 #endif /* MMAP_WORKS */ 114 } 115 116 free (fsp_base); 117 } 118 119 /* 120 * get_superblock: 121 * gets the superblock from disk (possibly in face of errors) 122 */ 123 int 124 get_superblock (fsp, sbp) 125 FS_INFO *fsp; /* IN: array of fs_infos we will dispose of */ 126 struct lfs *sbp; 127 { 128 int fid; 129 char mntfromname[MNAMELEN+1]; 130 131 strcpy(mntfromname, "/dev/r"); 132 strcat(mntfromname, statfsp->f_mntfromname+5); 133 134 if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) { 135 perror("get_superblock: bad open"); 136 return -1; 137 } 138 139 if(lseek (fid, LFS_LABELPAD, SEEK_SET) != LFS_LABELPAD) { 140 perror("get_superblock: bad seek"); 141 return -1; 142 } 143 if(read (fid, (char *)sbp, LFS_SBPAD) != LFS_SBPAD) { 144 perror("get_superblock: bad read"); 145 return -1; 146 } 147 close (fid); 148 149 return 0; 150 } 151 152 /* 153 * get_ifile: 154 * This function will map the ifile into memory. It returns 155 * NULL on failure. 156 */ 157 int 158 get_ifile (fsp) 159 FS_INFO *fsp; 160 { 161 int fid; 162 int count; 163 caddr_t ifp = NULL; 164 char *ifile_name; 165 struct stat file_stat; 166 167 ifile_name = (char *) 168 malloc(strlen(statfsp->f_mntonname)+strlen(IFILE_NAME)+2); 169 strcpy(ifile_name, statfsp->f_mntonname); 170 strcat(ifile_name, "/"); 171 strcat(ifile_name, IFILE_NAME); 172 173 if ((fid = open(ifile_name, O_RDWR, (mode_t)0)) < 0) { 174 perror("get_ifile: bad open"); 175 return -1; 176 } 177 178 if(fstat (fid, &file_stat)) { 179 perror("get_ifile: fstat failed"); 180 return -1; 181 } 182 ifile_length = file_stat.st_size; 183 184 /* get the ifile */ 185 #ifndef MMAP_WORKS 186 ifp = (caddr_t)malloc (ifile_length); 187 if (ifp == 0) { 188 perror ("get_ifile: malloc failed, out of memory?"); 189 return -1; 190 } 191 count = read (fid, ifp, ifile_length); 192 193 if (count != ifile_length) { 194 perror("get_ifile: bad ifile read"); 195 return -1; 196 } 197 #else /* MMAP_WORKS */ 198 ifp = mmap ((caddr_t)0, ifile_length, PROT_READ|PROT_WRITE, 199 MAP_FILE|MAP_SHARED, fid, (off_t)0); 200 if (ifp < 0) { 201 perror("get_ifile: mmap failed"); 202 return NULL; 203 } 204 #endif /* MMAP_WORKS */ 205 206 close (fid); 207 208 cip = (CLEANERINFO*)ifp; 209 segusep = (SEGUSE*)(ifp + CLEANSIZE(lfsp)); 210 ifilep = (IFILE*)(ifp + CLEANSIZE(lfsp) + SEGTABSIZE(lfsp)); 211 /* # of bytes in ifile table */ 212 ifile_count = ifile_length - (CLEANSIZE(lfsp) + SEGTABSIZE(lfsp)); 213 /* # of ifile entries in ifile table */ 214 ifile_count = (ifile_count / lfsp->lfs_bsize) * lfsp->lfs_ifpb; 215 free (ifile_name); 216 return 0; 217 } 218 219 220 /* 221 * segmapv: 222 * 223 * This function will scan a segment and return a list of 224 * <inode, blocknum> pairs which indicate which blocks were 225 * contained as live data within the segment at some point 226 * (it may have "died" since then). Any given pair will be 227 * listed at most once. 228 */ 229 int 230 lfs_segmapv(fsp, seg, seg_buf, blocks, bcount, inodes, icount) 231 FS_INFO *fsp; /* pointer to super block */ 232 int seg; /* the segment id */ 233 caddr_t seg_buf; /* the buffer containing the segment's data */ 234 /* OUT: array of block_info for live blocks */ 235 BLOCK_INFO **blocks; 236 int *bcount; /* OUT: number of active blocks in segment */ 237 /* OUT: array of inode_info for live inodes */ 238 INODE_INFO **inodes; 239 int *icount; /* OUT: number of active inodes in segment */ 240 { 241 caddr_t s; 242 caddr_t endofseg; 243 int nextsum; 244 u_long sb_off; 245 time_t timestamp; 246 247 *bcount = 0; 248 *blocks = (BLOCK_INFO *)malloc (sizeof(BLOCK_INFO)); 249 250 *icount = 0; 251 *inodes = (INODE_INFO *)malloc(sizeof(INODE_INFO)); 252 253 sb_off = (SEGUSE_ENTRY(lfsp, segusep, seg)->su_flags & SEGUSE_SUPERBLOCK) ? 254 LFS_SBPAD : 0; 255 256 for (s = seg_buf + sb_off, endofseg = seg_buf + seg_size(lfsp), 257 timestamp = 0 ; 258 s < endofseg ; 259 s += pseg_size (fsp, (SEGSUM*)s)) { 260 BLOCK_INFO *pblocks; 261 int pbcount; 262 INODE_INFO *pinodes; 263 int picount; 264 265 #ifdef VERBOSE 266 printf("lfs_segmapv: seg_buf = 0x%x, pseg_buf = 0x%x, offset = %lu (0x%x), pseg = \n\t", 267 (u_int)seg_buf, (u_int)s, 268 (u_int)s - (u_int)seg_buf - (u_int)sb_off, 269 (u_int)s - (u_int)seg_buf - (u_int)sb_off); 270 /* this can cause core dumps when printing an invalid segsum 271 * print_SEGSUM ((SEGSUM*)s); 272 * printf("\n"); 273 * printf("pseg_size = %lu\n", pseg_size(fsp, (SEGSUM*)s)); 274 */ 275 fflush(stdout); 276 #endif /* VERBOSE */ 277 278 /* we have hit the end of the valid data */ 279 if (! pseg_valid (fsp, (SEGSUM*)s)) break; 280 281 /* we have gone back in time and hit old data */ 282 if (timestamp > ((SEGSUM*)s)->ss_create) break; 283 284 timestamp = ((SEGSUM*)s)->ss_create; 285 286 /* get the block and inode list */ 287 pseg_blocks (fsp, seg, (SEGSUM*)s, seg_buf, 288 &pblocks, &pbcount); 289 pseg_bjoin (fsp, blocks, bcount, pblocks, pbcount); 290 291 pseg_inodes (fsp, seg, (SEGSUM*)s, seg_buf, 292 &pinodes, &picount); 293 pseg_ijoin (fsp, inodes, icount, pinodes, picount); 294 295 /* free the temporary tables */ 296 free (pblocks); 297 free (pinodes); 298 } 299 300 } 301 302 /* 303 * this will parse a partial segment and create a vector of block_info's 304 * for live data and a vector of inode_info's for live inodes. It will 305 * not include blocks or inodes from files with new version numbers. 306 */ 307 void 308 pseg_blocks (fsp, seg, s, seg_buf, blocks, count) 309 FS_INFO *fsp; /* pointer to super block */ 310 int seg; /* the segment id */ 311 SEGSUM *s; /* (unvalidated) segsum pointer */ 312 caddr_t seg_buf; /* the buffer containing the segment's data */ 313 /* OUT: array of block_info for live blocks */ 314 BLOCK_INFO **blocks; 315 int *count; /* OUT: number of active blocks in segment */ 316 { 317 FINFO **finfos; 318 int finfoc; 319 int blockc; 320 int i; 321 int j; 322 int ninob; /* number of inode blocks passed */ 323 daddr_t seg_daddr; 324 daddr_t *cur_iaddrp; /* pointer to current inode block */ 325 u_long offset; /* the offset (in bytes) within the segment */ 326 327 *count = 0; 328 *blocks = NULL; 329 330 pseg_finfos (fsp, s, &finfos, &finfoc); 331 332 #ifdef VERBOSE 333 for(i=0;i<finfoc;i++){print_FINFO(finfos[i]);printf("\n");fflush(stdout);} 334 printf("pseg_blocks: finfoc = %d\n", finfoc);fflush(stdout); 335 #endif 336 337 /* count how many blocks are held by live FINFO's */ 338 for (i = 0, blockc = 0 ; i < finfoc ; ++i) 339 if (finfos[i]->fi_version == 340 IFILE_ENTRY(lfsp, ifilep, finfos[i]->fi_ino)->if_version) 341 blockc += finfos[i]->fi_nblocks; 342 343 if (finfoc == 0 || blockc == 0) return; 344 345 ninob = 0; 346 offset = LFS_SUMMARY_SIZE + ((u_int)s - (u_int)seg_buf) + 347 s->ss_next * datobyte(fsp, 1<<lfsp->lfs_bshift); 348 cur_iaddrp = (daddr_t*)(s->ss_ninos == 0 ? 0 : 349 (char *)s + LFS_SUMMARY_SIZE - sizeof(daddr_t)); 350 seg_daddr = sntoda(lfsp, seg); 351 *blocks = (BLOCK_INFO *)malloc (blockc*sizeof(BLOCK_INFO)); 352 353 for (i = 0 ; i < finfoc ; i ++) { 354 FINFO *f = finfos[i]; 355 356 if (f->fi_version != IFILE_ENTRY(lfsp, ifilep, f->fi_ino)->if_version) 357 continue; 358 359 #ifdef VERBOSE 360 printf("finfo %d = ", i); 361 print_FINFO(f); 362 printf("\n"); 363 fflush(stdout); 364 printf("IFILE entry for file %d = ", f->fi_ino); 365 print_IFILE (IFILE_ENTRY(lfsp, ifilep, f->fi_ino)); 366 printf("\n"); 367 fflush(stdout); 368 #endif 369 for (j = 0 ; j < finfos[i]->fi_nblocks ; j ++) { 370 BLOCK_INFO *b = &(*blocks)[*count]; 371 372 /* 373 * XXX: 374 * this changes if we have variable size blocks 375 */ 376 for (;cur_iaddrp && 377 seg_daddr + bytetoda(fsp, offset) == *cur_iaddrp; 378 offset += datobyte(fsp, 1<<lfsp->lfs_bshift)) { 379 if (ninob <= (s->ss_ninos + INOPB(lfsp) - 1) 380 / INOPB(lfsp)) { 381 ++ninob; 382 --cur_iaddrp; 383 } else 384 cur_iaddrp = NULL; 385 } 386 b->bi_inode = f->fi_ino; 387 b->bi_lbn = f->fi_blocks[j]; 388 b->bi_daddr = seg_daddr + bytetoda(fsp, offset); 389 b->bi_segcreate = s->ss_create; 390 b->bi_bp = seg_buf + offset; 391 392 (*count) ++; 393 offset += blocksize(fsp, b->bi_lbn); 394 #ifdef VERBOSE 395 printf("\tb[%d] = ", j); 396 print_BLOCK_INFO(b); 397 printf("\n"); 398 fflush(stdout); 399 #endif 400 } 401 } 402 free (finfos); 403 } 404 405 void 406 pseg_inodes (fsp, seg, s, seg_buf, inodes, count) 407 FS_INFO *fsp; /* pointer to super block */ 408 int seg; /* the segment id */ 409 SEGSUM *s; /* (unvalidated) segsum pointer */ 410 caddr_t seg_buf; /* the buffer containing the segment's data */ 411 /* OUT: array of inode_info for live inodes */ 412 INODE_INFO **inodes; 413 int *count; /* OUT: number of active inodes in segment */ 414 { 415 int i; 416 ino_t inum; 417 daddr_t *daddrp, i_daddr, seg_daddr; 418 struct dinode *di; 419 420 *count = 0; 421 *inodes = NULL; 422 423 if (s->ss_ninos <= 0) return; 424 425 *inodes = (INODE_INFO *)malloc (s->ss_ninos * sizeof(INODE_INFO)); 426 427 seg_daddr = sntoda(lfsp, seg); 428 429 #ifdef VERBOSE 430 printf("pseg_inodes:\n"); 431 print_SEGSUM(s); 432 printf("\n"); 433 fflush(stdout); 434 #endif 435 436 daddrp = (daddr_t *)((caddr_t)s + LFS_SUMMARY_SIZE); 437 438 for (i = 0 ; i < s->ss_ninos ; ++i) { 439 440 if (i % INOPB(lfsp) == 0) { 441 i_daddr = *--daddrp; 442 if (datosn(lfsp, i_daddr) != seg || 443 datobyte(fsp, i_daddr - seg_daddr) > seg_size(lfsp)) { 444 printf("pseg_inodes: bad i_daddr\n"); 445 print_SEGSUM(s); 446 printf("\n"); 447 fflush(stdout); 448 printf("i_daddr = %d, seg_daddr = %d, offset = %d, pseg_size = %d\n", 449 i_daddr, seg_daddr, i_daddr - seg_daddr, 450 pseg_size(fsp, (SEGSUM*)s)); 451 fflush(stdout); 452 } 453 di = (struct dinode *) 454 (seg_buf + datobyte(fsp, i_daddr - seg_daddr)); 455 } else 456 ++di; 457 458 inum = di->di_inum; 459 460 if (IFILE_ENTRY(lfsp, ifilep, inum)->if_daddr == i_daddr) { 461 (*inodes)[*count].ii_inode = inum; 462 (*inodes)[*count].ii_daddr = i_daddr; 463 (*inodes)[*count].ii_segcreate = s->ss_create; 464 (*inodes)[*count].ii_dinode = di; 465 466 (*count) ++; 467 } 468 } 469 } 470 471 /* return the size of the partial segment in bytes. */ 472 u_long 473 pseg_size (fsp, s) 474 FS_INFO *fsp; /* pointer to super block */ 475 SEGSUM *s; /* segsum pointer */ 476 { 477 int i; 478 int j; 479 FINFO **finfos; 480 int finfoc; 481 u_long size = LFS_SUMMARY_SIZE; 482 483 pseg_finfos (fsp, s, &finfos, &finfoc); 484 for (i = 0 ; i < finfoc ; i ++) 485 for (j = 0 ; j < finfos[i]->fi_nblocks ; j ++) 486 size += blocksize(fsp, finfos[i]->fi_blocks[j]); 487 488 /* inodes are packed INOPB inodes per block */ 489 /* there can be unused space in an inode block */ 490 size += datobyte(fsp, fsbtodb(lfsp,1)*((s->ss_ninos+INOPB(lfsp)-1)/INOPB(lfsp))); 491 492 return size; 493 } 494 495 /* 496 * join block list b with list a (eliminating duplicates), leaving result 497 * in list a. 498 */ 499 void 500 pseg_bjoin (fsp, ablocks, acount, bblocks, bcount) 501 FS_INFO *fsp; /* pointer to file system info */ 502 /* INOUT: array of live blocks block_info */ 503 BLOCK_INFO **ablocks; 504 int *acount; /* INOUT: number of active blocks */ 505 /* IN: array of live blocks block_info */ 506 BLOCK_INFO *bblocks; 507 int bcount; /* IN: number of active blocks */ 508 { 509 int i; 510 int j; 511 BLOCK_INFO *abp; 512 BLOCK_INFO *bbp; 513 514 #ifdef VERBOSE 515 printf("pseg_bjoin: *acount = %d, bcount = %d\n", *acount, bcount); 516 /**/ 517 printf("ablocks = \n"); 518 for(i=0;i<*acount;i++){print_BLOCK_INFO((*ablocks)+i); printf("\n");} 519 /**/ 520 printf("bblocks = \n"); 521 for(i=0;i<bcount;i++){print_BLOCK_INFO(bblocks+i); printf("\n");} 522 /**/ 523 fflush(stdout); 524 /**/ 525 #endif 526 527 for (i = 0, bbp = bblocks ; i < bcount ; ++i, ++bbp) { 528 for (j = 0, abp = *ablocks ; j < *acount ; ++j, ++abp) { 529 if (abp->bi_inode == bbp->bi_inode 530 && abp->bi_lbn == bbp->bi_lbn) { 531 /* the data is for the same file and logical block */ 532 if (abp->bi_segcreate < bbp->bi_segcreate) 533 *abp = *bbp; 534 break; 535 } 536 } 537 if (j == *acount) { 538 /* this is a block we haven't seen before */ 539 *ablocks = (BLOCK_INFO*) 540 realloc (*ablocks, sizeof(BLOCK_INFO)*(*acount + 1)); 541 (*ablocks)[*acount] = *bbp; 542 (*acount) ++; 543 } 544 } 545 } 546 547 /* 548 * join block list b with list a (eliminating duplicates), leaving result 549 * in list a. 550 */ 551 void 552 pseg_ijoin (fsp, ainodes, acount, binodes, bcount) 553 FS_INFO *fsp; /* pointer to file system info */ 554 /* INOUT: array of live inodes inode_info */ 555 INODE_INFO **ainodes; 556 int *acount; /* INOUT: number of active inodes */ 557 /* IN: array of live inodes inode_info */ 558 INODE_INFO *binodes; 559 int bcount; /* IN: number of active inodes */ 560 { 561 int i; 562 int j; 563 daddr_t daddr; 564 INODE_INFO *aip; 565 INODE_INFO *bip; 566 567 /* we assume that we have no duplicate live inodes on "a" and "b" */ 568 569 /* eliminate dead inodes from "a" */ 570 for (i = 0, aip = *ainodes ; i < *acount ; ++aip ) { 571 daddr = IFILE_ENTRY(lfsp, ifilep, aip->ii_inode)->if_daddr; 572 if (daddr != aip->ii_daddr) 573 *aip = (*ainodes)[--(*acount)]; 574 else i++; 575 } 576 577 /* eliminate dead inodes from "b" */ 578 for (i = 0, bip = binodes ; i < bcount ; ++bip) { 579 daddr = IFILE_ENTRY(lfsp, ifilep, bip->ii_inode)->if_daddr; 580 if (daddr != bip->ii_daddr) { 581 /* don't really need to do this, only we don't want 582 to lose any inodes, just in case */ 583 INODE_INFO tmp; 584 tmp = *bip; 585 *bip = binodes[bcount]; 586 binodes[bcount] = tmp; 587 bcount --; 588 } 589 else i++; 590 } 591 /* append "b" to "a" */ 592 if (bcount > 0) { 593 *ainodes = (INODE_INFO *)realloc ((void *)*ainodes, 594 (*acount + bcount + 1)*sizeof(INODE_INFO)); 595 for (i = 0 ; i < bcount ; i ++) 596 (*ainodes)[(*acount)++] = binodes[i]; 597 } 598 } 599 600 /* is the segsum block valid? return TRUE if it is, FALSE otherwise */ 601 int 602 segsum_valid (fsp, ssp) 603 FS_INFO *fsp; /* pointer to file system info */ 604 SEGSUM *ssp; /* pointer to segment summary block */ 605 { 606 u_long sumsum; 607 608 /* check segsum block checksum */ 609 sumsum = cksum(&ssp->ss_datasum, 610 LFS_SUMMARY_SIZE - sizeof(ssp->ss_sumsum)); 611 612 if (sumsum != ssp->ss_sumsum) return FALSE; 613 614 return TRUE; 615 } 616 617 /* 618 * pseg_valid: 619 * 620 * returns 1 if the partial segment is valid, and 0 if it is invalid. 621 * it uses the checksums to verify validity. 622 */ 623 int 624 pseg_valid (fsp, ssp) 625 FS_INFO *fsp; /* pointer to file system info */ 626 SEGSUM *ssp; /* pointer to segment summary block */ 627 { 628 u_long datasum; 629 u_long size; 630 int nblocks; 631 int i; 632 u_long *datap; 633 caddr_t p; 634 635 /* check segsum block checksum */ 636 if (segsum_valid (fsp, ssp) == FALSE) return FALSE; 637 638 return TRUE; 639 640 /* check data/inode block(s) checksum too... */ 641 size = pseg_size (fsp, ssp); 642 nblocks = size/fsbtodb(lfsp, 1); 643 datap = (u_long*)malloc(sizeof(u_long)*nblocks); 644 p = (caddr_t)ssp + LFS_SUMMARY_SIZE; 645 for (i = 0 ; i < nblocks ; i ++) { 646 datap[i] = *((u_long *)p); 647 p += lfsp->lfs_bsize; 648 } 649 datasum = cksum ((void *)datap, nblocks*sizeof(u_long)); 650 if (datasum != ssp->ss_datasum) return FALSE; 651 652 return TRUE; 653 } 654 655 /* get array of FINFO pointers for partial segment */ 656 void 657 pseg_finfos (fsp, ssp, finfos, count) 658 FS_INFO *fsp; /* pointer to file system info */ 659 SEGSUM *ssp; /* pointer to segment summary block */ 660 FINFO ***finfos; /* OUT: return an array of FINFO pointers */ 661 int *count; /* OUT: return size of array */ 662 { 663 caddr_t p = (caddr_t)ssp + sizeof(SEGSUM); 664 int i; 665 FINFO *fip; 666 667 *count = 0; 668 *finfos = NULL; 669 670 if (ssp->ss_nfinfo > 0) 671 *finfos = (FINFO**)malloc (ssp->ss_nfinfo*sizeof(FINFO*)); 672 673 for (i = 0 ; i < ssp->ss_nfinfo ; i ++) { 674 fip = (FINFO *)p; 675 (*finfos)[*count] = fip; 676 (*count) ++; 677 p += finfo_size (fip); 678 } 679 } 680 681 /* 682 * blocksize: 683 * 684 * returns the size (in bytes) of a (logical) block. 685 * this is used because lfs uses different block sizes, depending 686 * on the logical # of the block. Lfs uses various sizes so 687 * it doesn't need fragments. 688 */ 689 u_long 690 blocksize (fsp, index) 691 FS_INFO *fsp; /* pointer to file system info */ 692 int index; /* logical block # w/in file */ 693 { 694 return lfsp->lfs_bsize; /* XXX: blocksize might depend on 695 the logical block number */ 696 } 697 698 /* 699 * finfo_size 700 * 701 * returns the size in bytes of an FINFO structure 702 */ 703 u_long 704 finfo_size (finfop) 705 FINFO *finfop; 706 { 707 return sizeof(FINFO) + sizeof(long)*(finfop->fi_nblocks-1); 708 } 709 710 711 /* #define MMAP_SEGMENT */ 712 /* 713 * read a segment into a memory buffer 714 */ 715 int 716 mmap_segment (fsp, segment, seg_buf) 717 FS_INFO *fsp; /* file system information */ 718 int segment; /* the index of the segment to be cleaned */ 719 caddr_t *seg_buf; /* pointer to buffer area */ 720 { 721 off_t seg_daddr; /* base disk address of segment */ 722 int fid; /* fildes for file system device */ 723 char mntfromname[MNAMELEN+2]; 724 725 /* get the disk address of the beginning of the segment */ 726 seg_daddr = sntoda(lfsp, segment); 727 728 strcpy(mntfromname, "/dev/r"); 729 strcat(mntfromname, statfsp->f_mntfromname+5); 730 731 if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) { 732 perror("mmap_segment: bad open"); 733 return -1; 734 } 735 736 #ifdef MMAP_SEGMENT 737 *seg_buf = mmap ((caddr_t)0, seg_size(lfsp), PROT_READ, 738 MAP_FILE, fid, (off_t)datobyte(fsp, seg_daddr)); 739 if ((long)*seg_buf < 0) { 740 perror("mmap_segment: mmap failed"); 741 return NULL; 742 } 743 #else /* MMAP_SEGMENT */ 744 printf("mmap_segment: seg_daddr = %lu, seg_size = %lu, seg_offset = %lu\n", 745 seg_daddr, seg_size(lfsp), datobyte(fsp, seg_daddr)); 746 /* malloc the space for the buffer */ 747 *seg_buf = (caddr_t)malloc(seg_size(lfsp)); 748 749 /* read the segment data into the buffer */ 750 if (datobyte(fsp, seg_daddr) != lseek (fid, datobyte(fsp, seg_daddr), SEEK_SET)) { 751 perror ("mmap_segment: bad lseek"); 752 return -1; 753 } 754 755 if (seg_size(lfsp) != read (fid, *seg_buf, seg_size(lfsp))) { 756 perror ("mmap_segment: bad read"); 757 return -1; 758 } 759 #endif /* MMAP_SEGMENT */ 760 close (fid); 761 762 return 0; 763 } 764 765 void 766 munmap_segment (fsp, seg_buf) 767 FS_INFO *fsp; /* file system information */ 768 caddr_t seg_buf; /* pointer to buffer area */ 769 { 770 #ifdef MMAP_SEGMENT 771 munmap (seg_buf, seg_size(lfsp)); 772 #else /* MMAP_SEGMENT */ 773 free (seg_buf); 774 #endif /* MMAP_SEGMENT */ 775 } 776 777 778 /* 779 * USEFUL DEBUGGING TOOLS: 780 */ 781 782 void 783 print_IFILE (p) 784 IFILE *p; 785 { 786 if (p) { 787 if (p->if_daddr == 0) 788 printf("{free, if_version=%lu, if_nextfree=%lu}", 789 p->if_version, p->if_nextfree); 790 else 791 printf("{if_version=%lu, if_daddr=%lu}", 792 p->if_version, p->if_daddr); 793 } 794 else printf("0x0"); 795 fflush(stdout); 796 } 797 798 void 799 print_SEGUSE (p) 800 SEGUSE *p; 801 { 802 if (p) { 803 printf("{su_nbytes=%lu, su_flags=%c%c%c, su_lastmod=", 804 p->su_nbytes, 805 ((p->su_flags & SEGUSE_DIRTY) ? 'D' : 'C'), 806 ((p->su_flags & SEGUSE_ACTIVE) ? 'A' : ' '), 807 ((p->su_flags & SEGUSE_SUPERBLOCK) ? 'S' : ' ')); 808 print_time_t(p->su_lastmod); 809 printf("}"); 810 } 811 else 812 printf("0x0"); 813 fflush(stdout); 814 } 815 816 void 817 print_CLEANERINFO (p) 818 CLEANERINFO *p; 819 { 820 if (p) printf("{clean=%lu, dirty=%lu}", p->clean, p->dirty); 821 else printf("0x0"); 822 fflush(stdout); 823 } 824 825 void 826 print_SEGSUM (p) 827 SEGSUM *p; 828 { 829 if (p) { 830 printf("{ss_sumsum=%lu, ss_datasum=%lu, ss_next=%lu, ", 831 p->ss_sumsum, p->ss_datasum, p->ss_next); 832 printf("ss_create=%lu, ss_nfinfo=%lu, ss_ninos=%lu", 833 p->ss_create, p->ss_nfinfo, p->ss_ninos); 834 printf("}"); 835 } 836 else printf("0x0"); 837 fflush(stdout); 838 } 839 840 void 841 print_time_t (t) 842 time_t t; 843 { 844 char temp[128]; 845 int len; 846 847 strcpy (temp, ctime(&t)); 848 len = strlen(temp); 849 if (temp[len-1] == '\n') temp[len-1] = 0; 850 printf("%s", temp); 851 fflush(stdout); 852 } 853 854 void 855 print_FINFO (p) 856 FINFO *p; 857 { 858 int i; 859 860 if (p) { 861 printf("{fi_nblocks=%lu, fi_version=%lu, fi_ino=%lu, fi_blocks={", 862 p->fi_nblocks, p->fi_version, p->fi_ino); 863 for (i = 0 ; i < p->fi_nblocks ; i ++) { 864 if (i > 0) printf(", "); 865 printf("%ld", p->fi_blocks[i]); 866 } 867 printf("}}"); 868 } else printf("0x0"); 869 fflush(stdout); 870 } 871 872 void 873 print_BLOCK_INFO (p) 874 BLOCK_INFO *p; 875 { 876 if (p) { 877 printf("{bi_inode=%lu, bi_lbn=%ld, bi_daddr=%lu, bi_segcreate=", 878 p->bi_inode, p->bi_lbn, p->bi_daddr); 879 print_time_t(p->bi_segcreate); 880 printf(", bi_bp = 0x%x}", p->bi_bp); 881 } 882 else 883 printf("0x0"); 884 fflush(stdout); 885 } 886 887 void 888 print_INODE_INFO (p) 889 INODE_INFO *p; 890 { 891 if (p) { 892 printf("{ii_inode=%lu, ii_daddr=%lu, ii_segcreate=", 893 p->ii_inode, p->ii_daddr); 894 print_time_t (p->ii_segcreate); 895 printf(", ii_dinode=0x%x}", p->ii_dinode); 896 } 897 else 898 printf("0x0"); 899 fflush(stdout); 900 } 901 902 void 903 print_lfs (p) 904 struct lfs *p; 905 { 906 int i; 907 908 if (p) { 909 printf("{\n"); 910 printf("\tlfs_magic=0x%x\n", p->lfs_magic); 911 printf("\tlfs_version=%lu\n", p->lfs_version); 912 printf("\tlfs_size=%lu\n", p->lfs_size); 913 printf("\tlfs_ssize=%lu\n", p->lfs_ssize); 914 printf("\tlfs_dsize=%lu\n", p->lfs_dsize); 915 printf("\tlfs_bsize=%lu\n", p->lfs_bsize); 916 printf("\tlfs_fsize=%lu\n", p->lfs_fsize); 917 printf("\tlfs_frag=%lu\n", p->lfs_frag); 918 /* checkpoint region */ 919 printf("\tlfs_free=%lu\n", p->lfs_free); 920 printf("\tlfs_bfree=%lu\n", p->lfs_bfree); 921 printf("\tlfs_nfiles=%lu\n", p->lfs_nfiles); 922 printf("\tlfs_idaddr=%lu\n", p->lfs_idaddr); 923 printf("\tlfs_ifile=%lu\n", p->lfs_ifile); 924 printf("\tlfs_lastseg=%lu\n", p->lfs_lastseg); 925 printf("\tlfs_nextseg=%lu\n", p->lfs_nextseg); 926 printf("\tlfs_curseg=%lu\n", p->lfs_curseg); 927 printf("\tlfs_offset=%lu\n", p->lfs_offset); 928 printf("\tlfs_tstamp=%lu\n", p->lfs_tstamp); 929 /* configuration parameters */ 930 printf("\tlfs_minfree=%lu\n", p->lfs_minfree); 931 /* these fields can be computed from the others */ 932 printf("\tlfs_dbpseg=%lu\n", p->lfs_dbpseg); 933 printf("\tlfs_inopb=%lu\n", p->lfs_inopb); 934 printf("\tlfs_ifpb=%lu\n", p->lfs_ifpb); 935 printf("\tlfs_sepb=%lu\n", p->lfs_sepb); 936 printf("\tlfs_nindir=%lu\n", p->lfs_nindir); 937 printf("\tlfs_nseg=%lu\n", p->lfs_nseg); 938 printf("\tlfs_nspf=%lu\n", p->lfs_nspf); 939 printf("\tlfs_cleansz=%lu\n", p->lfs_cleansz); 940 printf("\tlfs_segtabsz=%lu\n", p->lfs_segtabsz); 941 942 printf("\tlfs_segmask=%lu\n", p->lfs_segmask); 943 printf("\tlfs_segshift=%lu\n", p->lfs_segshift); 944 printf("\tlfs_bmask=%lu\n", p->lfs_bmask); 945 printf("\tlfs_bshift=%lu\n", p->lfs_bshift); 946 printf("\tlfs_ffmask=%lu\n", p->lfs_ffmask); 947 printf("\tlfs_ffshift=%lu\n", p->lfs_ffshift); 948 printf("\tlfs_fbmask=%lu\n", p->lfs_fbmask); 949 printf("\tlfs_fbshift=%lu\n", p->lfs_fbshift); 950 printf("\tlfs_fsbtodb=%lu\n", p->lfs_fsbtodb); 951 /* superblock offsets */ 952 printf("\tlfs_sboffs={"); 953 for (i = 0 ; i < LFS_MAXNUMSB ; i ++) { 954 if (i > 0) printf(", "); 955 printf("%lu", p->lfs_sboffs[i]); 956 } 957 printf("}\n"); 958 959 printf("}"); 960 } 961 else 962 printf("0x0"); 963 fflush(stdout); 964 } 965