1 /* 2 * Copyright (c) 1980, 1986, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #if 0 31 #ifndef lint 32 static const char sccsid[] = "@(#)inode.c 8.8 (Berkeley) 4/28/95"; 33 #endif /* not lint */ 34 #endif 35 #include <sys/cdefs.h> 36 __FBSDID("$FreeBSD$"); 37 38 #include <sys/param.h> 39 #include <sys/stdint.h> 40 #include <sys/time.h> 41 #include <sys/sysctl.h> 42 43 #include <ufs/ufs/dinode.h> 44 #include <ufs/ufs/dir.h> 45 #include <ufs/ffs/fs.h> 46 47 #include <err.h> 48 #include <pwd.h> 49 #include <string.h> 50 51 #include "fsck.h" 52 53 static ino_t startinum; 54 55 static int iblock(struct inodesc *, long ilevel, off_t isize); 56 57 int 58 ckinode(union dinode *dp, struct inodesc *idesc) 59 { 60 off_t remsize, sizepb; 61 int i, offset, ret; 62 union dinode dino; 63 ufs2_daddr_t ndb; 64 mode_t mode; 65 char pathbuf[MAXPATHLEN + 1]; 66 67 if (idesc->id_fix != IGNORE) 68 idesc->id_fix = DONTKNOW; 69 idesc->id_lbn = -1; 70 idesc->id_entryno = 0; 71 idesc->id_filesize = DIP(dp, di_size); 72 mode = DIP(dp, di_mode) & IFMT; 73 if (mode == IFBLK || mode == IFCHR || (mode == IFLNK && 74 DIP(dp, di_size) < (unsigned)sblock.fs_maxsymlinklen)) 75 return (KEEPON); 76 if (sblock.fs_magic == FS_UFS1_MAGIC) 77 dino.dp1 = dp->dp1; 78 else 79 dino.dp2 = dp->dp2; 80 ndb = howmany(DIP(&dino, di_size), sblock.fs_bsize); 81 for (i = 0; i < NDADDR; i++) { 82 idesc->id_lbn++; 83 if (--ndb == 0 && 84 (offset = blkoff(&sblock, DIP(&dino, di_size))) != 0) 85 idesc->id_numfrags = 86 numfrags(&sblock, fragroundup(&sblock, offset)); 87 else 88 idesc->id_numfrags = sblock.fs_frag; 89 if (DIP(&dino, di_db[i]) == 0) { 90 if (idesc->id_type == DATA && ndb >= 0) { 91 /* An empty block in a directory XXX */ 92 getpathname(pathbuf, idesc->id_number, 93 idesc->id_number); 94 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 95 pathbuf); 96 if (reply("ADJUST LENGTH") == 1) { 97 dp = ginode(idesc->id_number); 98 DIP(dp, di_size) = i * sblock.fs_bsize; 99 printf( 100 "YOU MUST RERUN FSCK AFTERWARDS\n"); 101 rerun = 1; 102 inodirty(); 103 104 } 105 } 106 continue; 107 } 108 idesc->id_blkno = DIP(&dino, di_db[i]); 109 if (idesc->id_type != DATA) 110 ret = (*idesc->id_func)(idesc); 111 else 112 ret = dirscan(idesc); 113 if (ret & STOP) 114 return (ret); 115 } 116 idesc->id_numfrags = sblock.fs_frag; 117 remsize = DIP(&dino, di_size) - sblock.fs_bsize * NDADDR; 118 sizepb = sblock.fs_bsize; 119 for (i = 0; i < NIADDR; i++) { 120 sizepb *= NINDIR(&sblock); 121 if (DIP(&dino, di_ib[i])) { 122 idesc->id_blkno = DIP(&dino, di_ib[i]); 123 ret = iblock(idesc, i + 1, remsize); 124 if (ret & STOP) 125 return (ret); 126 } else { 127 idesc->id_lbn += sizepb / sblock.fs_bsize; 128 if (idesc->id_type == DATA && remsize > 0) { 129 /* An empty block in a directory XXX */ 130 getpathname(pathbuf, idesc->id_number, 131 idesc->id_number); 132 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 133 pathbuf); 134 if (reply("ADJUST LENGTH") == 1) { 135 dp = ginode(idesc->id_number); 136 DIP(dp, di_size) -= remsize; 137 remsize = 0; 138 printf( 139 "YOU MUST RERUN FSCK AFTERWARDS\n"); 140 rerun = 1; 141 inodirty(); 142 break; 143 } 144 } 145 } 146 remsize -= sizepb; 147 } 148 return (KEEPON); 149 } 150 151 static int 152 iblock(struct inodesc *idesc, long ilevel, off_t isize) 153 { 154 struct bufarea *bp; 155 int i, n, (*func)(struct inodesc *), nif; 156 off_t sizepb; 157 char buf[BUFSIZ]; 158 char pathbuf[MAXPATHLEN + 1]; 159 union dinode *dp; 160 161 if (idesc->id_type != DATA) { 162 func = idesc->id_func; 163 if (((n = (*func)(idesc)) & KEEPON) == 0) 164 return (n); 165 } else 166 func = dirscan; 167 if (chkrange(idesc->id_blkno, idesc->id_numfrags)) 168 return (SKIP); 169 bp = getdatablk(idesc->id_blkno, sblock.fs_bsize); 170 ilevel--; 171 for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++) 172 sizepb *= NINDIR(&sblock); 173 if (howmany(isize, sizepb) > NINDIR(&sblock)) 174 nif = NINDIR(&sblock); 175 else 176 nif = howmany(isize, sizepb); 177 if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) { 178 for (i = nif; i < NINDIR(&sblock); i++) { 179 if (IBLK(bp, i) == 0) 180 continue; 181 (void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%lu", 182 (u_long)idesc->id_number); 183 if (preen) { 184 pfatal("%s", buf); 185 } else if (dofix(idesc, buf)) { 186 IBLK(bp, i) = 0; 187 dirty(bp); 188 } 189 } 190 flush(fswritefd, bp); 191 } 192 for (i = 0; i < nif; i++) { 193 if (ilevel == 0) 194 idesc->id_lbn++; 195 if (IBLK(bp, i)) { 196 idesc->id_blkno = IBLK(bp, i); 197 if (ilevel == 0) 198 n = (*func)(idesc); 199 else 200 n = iblock(idesc, ilevel, isize); 201 if (n & STOP) { 202 bp->b_flags &= ~B_INUSE; 203 return (n); 204 } 205 } else { 206 if (idesc->id_type == DATA && isize > 0) { 207 /* An empty block in a directory XXX */ 208 getpathname(pathbuf, idesc->id_number, 209 idesc->id_number); 210 pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", 211 pathbuf); 212 if (reply("ADJUST LENGTH") == 1) { 213 dp = ginode(idesc->id_number); 214 DIP(dp, di_size) -= isize; 215 isize = 0; 216 printf( 217 "YOU MUST RERUN FSCK AFTERWARDS\n"); 218 rerun = 1; 219 inodirty(); 220 bp->b_flags &= ~B_INUSE; 221 return(STOP); 222 } 223 } 224 } 225 isize -= sizepb; 226 } 227 bp->b_flags &= ~B_INUSE; 228 return (KEEPON); 229 } 230 231 /* 232 * Check that a block in a legal block number. 233 * Return 0 if in range, 1 if out of range. 234 */ 235 int 236 chkrange(ufs2_daddr_t blk, int cnt) 237 { 238 int c; 239 240 if (cnt <= 0 || blk <= 0 || blk > maxfsblock || 241 cnt - 1 > maxfsblock - blk) 242 return (1); 243 if (cnt > sblock.fs_frag || 244 fragnum(&sblock, blk) + cnt > sblock.fs_frag) { 245 if (debug) 246 printf("bad size: blk %ld, offset %i, size %d\n", 247 (long)blk, (int)fragnum(&sblock, blk), cnt); 248 return (1); 249 } 250 c = dtog(&sblock, blk); 251 if (blk < cgdmin(&sblock, c)) { 252 if ((blk + cnt) > cgsblock(&sblock, c)) { 253 if (debug) { 254 printf("blk %ld < cgdmin %ld;", 255 (long)blk, (long)cgdmin(&sblock, c)); 256 printf(" blk + cnt %ld > cgsbase %ld\n", 257 (long)(blk + cnt), 258 (long)cgsblock(&sblock, c)); 259 } 260 return (1); 261 } 262 } else { 263 if ((blk + cnt) > cgbase(&sblock, c+1)) { 264 if (debug) { 265 printf("blk %ld >= cgdmin %ld;", 266 (long)blk, (long)cgdmin(&sblock, c)); 267 printf(" blk + cnt %ld > sblock.fs_fpg %ld\n", 268 (long)(blk + cnt), (long)sblock.fs_fpg); 269 } 270 return (1); 271 } 272 } 273 return (0); 274 } 275 276 /* 277 * General purpose interface for reading inodes. 278 */ 279 union dinode * 280 ginode(ino_t inumber) 281 { 282 ufs2_daddr_t iblk; 283 284 if (inumber < ROOTINO || inumber > maxino) 285 errx(EEXIT, "bad inode number %d to ginode", inumber); 286 if (startinum == 0 || 287 inumber < startinum || inumber >= startinum + INOPB(&sblock)) { 288 iblk = ino_to_fsba(&sblock, inumber); 289 if (pbp != 0) 290 pbp->b_flags &= ~B_INUSE; 291 pbp = getdatablk(iblk, sblock.fs_bsize); 292 startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock); 293 } 294 if (sblock.fs_magic == FS_UFS1_MAGIC) 295 return ((union dinode *) 296 &pbp->b_un.b_dinode1[inumber % INOPB(&sblock)]); 297 return ((union dinode *)&pbp->b_un.b_dinode2[inumber % INOPB(&sblock)]); 298 } 299 300 /* 301 * Special purpose version of ginode used to optimize first pass 302 * over all the inodes in numerical order. 303 */ 304 static ino_t nextino, lastinum, lastvalidinum; 305 static long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; 306 static caddr_t inodebuf; 307 308 union dinode * 309 getnextinode(ino_t inumber) 310 { 311 long size; 312 ufs2_daddr_t dblk; 313 union dinode *dp; 314 static caddr_t nextinop; 315 316 if (inumber != nextino++ || inumber > lastvalidinum) 317 errx(EEXIT, "bad inode number %d to nextinode", inumber); 318 if (inumber >= lastinum) { 319 readcnt++; 320 dblk = fsbtodb(&sblock, ino_to_fsba(&sblock, lastinum)); 321 if (readcnt % readpercg == 0) { 322 size = partialsize; 323 lastinum += partialcnt; 324 } else { 325 size = inobufsize; 326 lastinum += fullcnt; 327 } 328 /* 329 * If bread returns an error, it will already have zeroed 330 * out the buffer, so we do not need to do so here. 331 */ 332 (void)bread(fsreadfd, inodebuf, dblk, size); 333 nextinop = inodebuf; 334 } 335 dp = (union dinode *)nextinop; 336 if (sblock.fs_magic == FS_UFS1_MAGIC) 337 nextinop += sizeof(struct ufs1_dinode); 338 else 339 nextinop += sizeof(struct ufs2_dinode); 340 return (dp); 341 } 342 343 void 344 setinodebuf(ino_t inum) 345 { 346 347 if (inum % sblock.fs_ipg != 0) 348 errx(EEXIT, "bad inode number %d to setinodebuf", inum); 349 lastvalidinum = inum + sblock.fs_ipg - 1; 350 startinum = 0; 351 nextino = inum; 352 lastinum = inum; 353 readcnt = 0; 354 if (inodebuf != NULL) 355 return; 356 inobufsize = blkroundup(&sblock, INOBUFSIZE); 357 fullcnt = inobufsize / ((sblock.fs_magic == FS_UFS1_MAGIC) ? 358 sizeof(struct ufs1_dinode) : sizeof(struct ufs2_dinode)); 359 readpercg = sblock.fs_ipg / fullcnt; 360 partialcnt = sblock.fs_ipg % fullcnt; 361 partialsize = partialcnt * ((sblock.fs_magic == FS_UFS1_MAGIC) ? 362 sizeof(struct ufs1_dinode) : sizeof(struct ufs2_dinode)); 363 if (partialcnt != 0) { 364 readpercg++; 365 } else { 366 partialcnt = fullcnt; 367 partialsize = inobufsize; 368 } 369 if ((inodebuf = malloc((unsigned)inobufsize)) == NULL) 370 errx(EEXIT, "cannot allocate space for inode buffer"); 371 } 372 373 void 374 freeinodebuf(void) 375 { 376 377 if (inodebuf != NULL) 378 free((char *)inodebuf); 379 inodebuf = NULL; 380 } 381 382 /* 383 * Routines to maintain information about directory inodes. 384 * This is built during the first pass and used during the 385 * second and third passes. 386 * 387 * Enter inodes into the cache. 388 */ 389 void 390 cacheino(union dinode *dp, ino_t inumber) 391 { 392 struct inoinfo *inp, **inpp; 393 int i, blks; 394 395 if (howmany(DIP(dp, di_size), sblock.fs_bsize) > NDADDR) 396 blks = NDADDR + NIADDR; 397 else 398 blks = howmany(DIP(dp, di_size), sblock.fs_bsize); 399 inp = (struct inoinfo *) 400 malloc(sizeof(*inp) + (blks - 1) * sizeof(ufs2_daddr_t)); 401 if (inp == NULL) 402 errx(EEXIT, "cannot increase directory list"); 403 inpp = &inphead[inumber % dirhash]; 404 inp->i_nexthash = *inpp; 405 *inpp = inp; 406 inp->i_parent = inumber == ROOTINO ? ROOTINO : (ino_t)0; 407 inp->i_dotdot = (ino_t)0; 408 inp->i_number = inumber; 409 inp->i_isize = DIP(dp, di_size); 410 inp->i_numblks = blks; 411 for (i = 0; i < (blks < NDADDR ? blks : NDADDR); i++) 412 inp->i_blks[i] = DIP(dp, di_db[i]); 413 if (blks > NDADDR) 414 for (i = 0; i < NIADDR; i++) 415 inp->i_blks[NDADDR + i] = DIP(dp, di_ib[i]); 416 if (inplast == listmax) { 417 listmax += 100; 418 inpsort = (struct inoinfo **)realloc((char *)inpsort, 419 (unsigned)listmax * sizeof(struct inoinfo *)); 420 if (inpsort == NULL) 421 errx(EEXIT, "cannot increase directory list"); 422 } 423 inpsort[inplast++] = inp; 424 } 425 426 /* 427 * Look up an inode cache structure. 428 */ 429 struct inoinfo * 430 getinoinfo(ino_t inumber) 431 { 432 struct inoinfo *inp; 433 434 for (inp = inphead[inumber % dirhash]; inp; inp = inp->i_nexthash) { 435 if (inp->i_number != inumber) 436 continue; 437 return (inp); 438 } 439 errx(EEXIT, "cannot find inode %d", inumber); 440 return ((struct inoinfo *)0); 441 } 442 443 /* 444 * Clean up all the inode cache structure. 445 */ 446 void 447 inocleanup(void) 448 { 449 struct inoinfo **inpp; 450 451 if (inphead == NULL) 452 return; 453 for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) 454 free((char *)(*inpp)); 455 free((char *)inphead); 456 free((char *)inpsort); 457 inphead = inpsort = NULL; 458 } 459 460 void 461 inodirty(void) 462 { 463 464 dirty(pbp); 465 } 466 467 void 468 clri(struct inodesc *idesc, const char *type, int flag) 469 { 470 union dinode *dp; 471 472 dp = ginode(idesc->id_number); 473 if (flag == 1) { 474 pwarn("%s %s", type, 475 (DIP(dp, di_mode) & IFMT) == IFDIR ? "DIR" : "FILE"); 476 pinode(idesc->id_number); 477 } 478 if (preen || reply("CLEAR") == 1) { 479 if (preen) 480 printf(" (CLEARED)\n"); 481 n_files--; 482 if (bkgrdflag == 0) { 483 (void)ckinode(dp, idesc); 484 inoinfo(idesc->id_number)->ino_state = USTATE; 485 clearinode(dp); 486 inodirty(); 487 } else { 488 cmd.value = idesc->id_number; 489 cmd.size = -DIP(dp, di_nlink); 490 if (debug) 491 printf("adjrefcnt ino %ld amt %lld\n", 492 (long)cmd.value, (long long)cmd.size); 493 if (sysctl(adjrefcnt, MIBSIZE, 0, 0, 494 &cmd, sizeof cmd) == -1) 495 rwerror("ADJUST INODE", cmd.value); 496 } 497 } 498 } 499 500 int 501 findname(struct inodesc *idesc) 502 { 503 struct direct *dirp = idesc->id_dirp; 504 505 if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) { 506 idesc->id_entryno++; 507 return (KEEPON); 508 } 509 memmove(idesc->id_name, dirp->d_name, (size_t)dirp->d_namlen + 1); 510 return (STOP|FOUND); 511 } 512 513 int 514 findino(struct inodesc *idesc) 515 { 516 struct direct *dirp = idesc->id_dirp; 517 518 if (dirp->d_ino == 0) 519 return (KEEPON); 520 if (strcmp(dirp->d_name, idesc->id_name) == 0 && 521 dirp->d_ino >= ROOTINO && dirp->d_ino <= maxino) { 522 idesc->id_parent = dirp->d_ino; 523 return (STOP|FOUND); 524 } 525 return (KEEPON); 526 } 527 528 int 529 clearentry(struct inodesc *idesc) 530 { 531 struct direct *dirp = idesc->id_dirp; 532 533 if (dirp->d_ino != idesc->id_parent || idesc->id_entryno < 2) { 534 idesc->id_entryno++; 535 return (KEEPON); 536 } 537 dirp->d_ino = 0; 538 return (STOP|FOUND|ALTERED); 539 } 540 541 void 542 pinode(ino_t ino) 543 { 544 union dinode *dp; 545 char *p; 546 struct passwd *pw; 547 time_t t; 548 549 printf(" I=%lu ", (u_long)ino); 550 if (ino < ROOTINO || ino > maxino) 551 return; 552 dp = ginode(ino); 553 printf(" OWNER="); 554 if ((pw = getpwuid((int)DIP(dp, di_uid))) != 0) 555 printf("%s ", pw->pw_name); 556 else 557 printf("%u ", (unsigned)DIP(dp, di_uid)); 558 printf("MODE=%o\n", DIP(dp, di_mode)); 559 if (preen) 560 printf("%s: ", cdevname); 561 printf("SIZE=%ju ", (uintmax_t)DIP(dp, di_size)); 562 t = DIP(dp, di_mtime); 563 p = ctime(&t); 564 printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]); 565 } 566 567 void 568 blkerror(ino_t ino, const char *type, ufs2_daddr_t blk) 569 { 570 571 pfatal("%jd %s I=%ju", (intmax_t)blk, type, (uintmax_t)ino); 572 printf("\n"); 573 switch (inoinfo(ino)->ino_state) { 574 575 case FSTATE: 576 inoinfo(ino)->ino_state = FCLEAR; 577 return; 578 579 case DSTATE: 580 inoinfo(ino)->ino_state = DCLEAR; 581 return; 582 583 case FCLEAR: 584 case DCLEAR: 585 return; 586 587 default: 588 errx(EEXIT, "BAD STATE %d TO BLKERR", inoinfo(ino)->ino_state); 589 /* NOTREACHED */ 590 } 591 } 592 593 /* 594 * allocate an unused inode 595 */ 596 ino_t 597 allocino(ino_t request, int type) 598 { 599 ino_t ino; 600 union dinode *dp; 601 struct cg *cgp = &cgrp; 602 int cg; 603 604 if (request == 0) 605 request = ROOTINO; 606 else if (inoinfo(request)->ino_state != USTATE) 607 return (0); 608 for (ino = request; ino < maxino; ino++) 609 if (inoinfo(ino)->ino_state == USTATE) 610 break; 611 if (ino == maxino) 612 return (0); 613 cg = ino_to_cg(&sblock, ino); 614 getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize); 615 if (!cg_chkmagic(cgp)) 616 pfatal("CG %d: BAD MAGIC NUMBER\n", cg); 617 setbit(cg_inosused(cgp), ino % sblock.fs_ipg); 618 cgp->cg_cs.cs_nifree--; 619 switch (type & IFMT) { 620 case IFDIR: 621 inoinfo(ino)->ino_state = DSTATE; 622 cgp->cg_cs.cs_ndir++; 623 break; 624 case IFREG: 625 case IFLNK: 626 inoinfo(ino)->ino_state = FSTATE; 627 break; 628 default: 629 return (0); 630 } 631 cgdirty(); 632 dp = ginode(ino); 633 DIP(dp, di_db[0]) = allocblk((long)1); 634 if (DIP(dp, di_db[0]) == 0) { 635 inoinfo(ino)->ino_state = USTATE; 636 return (0); 637 } 638 DIP(dp, di_mode) = type; 639 DIP(dp, di_flags) = 0; 640 DIP(dp, di_atime) = time(NULL); 641 DIP(dp, di_mtime) = DIP(dp, di_ctime) = DIP(dp, di_atime); 642 DIP(dp, di_mtimensec) = 0; 643 DIP(dp, di_ctimensec) = 0; 644 DIP(dp, di_atimensec) = 0; 645 DIP(dp, di_size) = sblock.fs_fsize; 646 DIP(dp, di_blocks) = btodb(sblock.fs_fsize); 647 n_files++; 648 inodirty(); 649 inoinfo(ino)->ino_type = IFTODT(type); 650 return (ino); 651 } 652 653 /* 654 * deallocate an inode 655 */ 656 void 657 freeino(ino_t ino) 658 { 659 struct inodesc idesc; 660 union dinode *dp; 661 662 memset(&idesc, 0, sizeof(struct inodesc)); 663 idesc.id_type = ADDR; 664 idesc.id_func = pass4check; 665 idesc.id_number = ino; 666 dp = ginode(ino); 667 (void)ckinode(dp, &idesc); 668 clearinode(dp); 669 inodirty(); 670 inoinfo(ino)->ino_state = USTATE; 671 n_files--; 672 } 673