1 /* 2 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7 /* All Rights Reserved */ 8 9 /* 10 * Copyright (c) 1980, 1986, 1990 The Regents of the University of California. 11 * All rights reserved. 12 * 13 * Redistribution and use in source and binary forms are permitted 14 * provided that: (1) source distributions retain this entire copyright 15 * notice and comment, and (2) distributions including binaries display 16 * the following acknowledgement: ``This product includes software 17 * developed by the University of California, Berkeley and its contributors'' 18 * in the documentation or other materials provided with the distribution 19 * and in all advertising materials mentioning features or use of this 20 * software. Neither the name of the University nor the names of its 21 * contributors may be used to endorse or promote products derived 22 * from this software without specific prior written permission. 23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 26 */ 27 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 #include <sys/param.h> 31 #include <sys/types.h> 32 #include <sys/sysmacros.h> 33 #include <sys/mntent.h> 34 35 #define bcopy(f, t, n) memcpy(t, f, n) 36 #define bzero(s, n) memset(s, 0, n) 37 #define bcmp(s, d, n) memcmp(s, d, n) 38 39 #define index(s, r) strchr(s, r) 40 #define rindex(s, r) strrchr(s, r) 41 42 #include <sys/fs/ufs_fs.h> 43 #include <sys/vnode.h> 44 #include <sys/fs/ufs_inode.h> 45 #include <sys/fs/ufs_log.h> 46 #include "fsck.h" 47 48 /* 49 * for each large file ( size > MAXOFF_T) this global counter 50 * gets incremented here. 51 */ 52 53 extern uint_t largefile_count; 54 55 static uint32_t badblk; 56 static uint32_t dupblk; 57 int pass1check(); 58 struct dinode *getnextinode(); 59 60 pass1() 61 { 62 uint_t c, i, j; 63 struct dinode *dp; 64 struct zlncnt *zlnp; 65 int ndb, cgd; 66 struct inodesc idesc; 67 ino_t inumber, shadow, attrinode; 68 ino_t maxinumber; 69 int32_t tmpblks; 70 71 /* 72 * Set file system reserved blocks in used block map. 73 */ 74 for (c = 0; c < sblock.fs_ncg; c++) { 75 cgd = cgdmin(&sblock, c); 76 if (c == 0) { 77 i = cgbase(&sblock, c); 78 cgd += howmany(sblock.fs_cssize, sblock.fs_fsize); 79 } else 80 i = cgsblock(&sblock, c); 81 for (; i < cgd; i++) 82 setbmap(i); 83 } 84 /* 85 * Record log blocks 86 */ 87 if (islog && islogok && sblock.fs_logbno) { 88 struct bufarea *bp; 89 extent_block_t *ebp; 90 extent_t *ep; 91 daddr32_t nfno, fno; 92 int i; 93 int j; 94 95 bp = getdatablk(logbtofrag(&sblock, 96 sblock.fs_logbno), sblock.fs_bsize); 97 ebp = (void *)bp->b_un.b_buf; 98 ep = &ebp->extents[0]; 99 for (i = 0; i < ebp->nextents; ++i, ++ep) { 100 fno = logbtofrag(&sblock, ep->pbno); 101 nfno = dbtofsb(&sblock, ep->nbno); 102 for (j = 0; j < nfno; ++j, ++fno) 103 setbmap(fno); 104 } 105 brelse(bp); 106 107 fno = logbtofrag(&sblock, sblock.fs_logbno); 108 for (j = 0; j < sblock.fs_frag; ++j, ++fno) 109 setbmap(fno); 110 } 111 /* 112 * Find all allocated blocks. 113 */ 114 bzero((char *)&idesc, sizeof (struct inodesc)); 115 idesc.id_type = ADDR; 116 idesc.id_func = pass1check; 117 inumber = 0; 118 n_files = n_blks = 0; 119 resetinodebuf(); 120 maxinumber = sblock.fs_ncg * sblock.fs_ipg; 121 for (c = 0; c < sblock.fs_ncg; c++) { 122 for (i = 0; i < sblock.fs_ipg; i++, inumber++) { 123 if (inumber < UFSROOTINO) 124 continue; 125 dp = getnextinode(inumber); 126 if ((dp->di_mode & IFMT) == 0) { 127 /* mode and type of file is not set */ 128 if (bcmp((char *)dp->di_db, (char *)zino.di_db, 129 NDADDR * sizeof (daddr32_t)) || 130 bcmp((char *)dp->di_ib, (char *)zino.di_ib, 131 NIADDR * sizeof (daddr32_t)) || 132 dp->di_mode || dp->di_size) { 133 pfatal("PARTIALLY ALLOCATED INODE I=%u", 134 inumber); 135 if (reply("CLEAR") == 1) { 136 dp = ginode(inumber); 137 clearinode(dp); 138 inodirty(); 139 } 140 } 141 statemap[inumber] = USTATE; 142 continue; 143 } 144 lastino = inumber; 145 if (dp->di_size > (u_offset_t)UFS_MAXOFFSET_T) { 146 if (debug) 147 printf("bad size %llu:", 148 dp->di_size); 149 goto unknown; 150 } 151 if (!preen && (dp->di_mode & IFMT) == IFMT && 152 reply("BAD MODE: MAKE IT A FILE") == 1) { 153 dp = ginode(inumber); 154 dp->di_size = (u_offset_t)sblock.fs_fsize; 155 dp->di_mode = IFREG|0600; 156 inodirty(); 157 } 158 /* number of blocks is a 32 bit value */ 159 ndb = howmany(dp->di_size, 160 (u_offset_t)sblock.fs_bsize); 161 if (ndb < 0) { 162 if (debug) 163 printf("bad size %llu ndb %d:", 164 dp->di_size, ndb); 165 goto unknown; 166 } 167 if (dp->di_blocks < 0) { 168 if (debug) { 169 printf("bad number of sectors %d: ", 170 dp->di_blocks); 171 } 172 dp = ginode(inumber); 173 tmpblks = (int32_t) 174 ((dp->di_size + (512 - 1)) >> 9); 175 dp->di_blocks = (int32_t)(ndb*16); 176 inodirty(); 177 if (debug) { 178 printf("new number of sectors " 179 "%d (0x%x,0x%x)\n", dp->di_blocks, 180 dp->di_blocks, tmpblks); 181 } 182 183 } 184 if ((dp->di_mode & IFMT) == IFBLK || 185 (dp->di_mode & IFMT) == IFCHR) { 186 for (j = 0; j < NDADDR; j++) { 187 if (dp->di_db[j] != 0 && 188 &dp->di_db[j] != &dp->di_ordev) { 189 if (debug) { 190 printf("special file contains value %d at indirect addr[%d] - should be 0\n", 191 dp->di_db[j], j); 192 } 193 goto unknown; 194 } 195 } 196 } else { 197 for (j = ndb; j < NDADDR; j++) 198 if (dp->di_db[j] != 0) { 199 if (debug) { 200 printf("bad direct addr[%lld]: 0x%x mode:%o\n", 201 j, dp->di_db[j], dp->di_mode); 202 } 203 goto unknown; 204 } 205 } 206 for (j = 0, ndb -= NDADDR; ndb > 0; j++) 207 ndb /= NINDIR(&sblock); 208 for (; j < NIADDR; j++) 209 if (dp->di_ib[j] != 0) { 210 if (debug) { 211 printf("bad indirect addr: %d\n", 212 dp->di_ib[j]); 213 } 214 goto unknown; 215 } 216 if (ftypeok(dp) == 0) { 217 printf("mode: %o\n", dp->di_mode); 218 goto unknown; 219 } 220 n_files++; 221 lncntp[inumber] = dp->di_nlink; 222 /* 223 * if errorlocked then open deleted files will 224 * manifest as di_nlink <= 0 and di_mode != 0 225 * so skip them; they're ok. 226 */ 227 if (dp->di_nlink <= 0 && 228 !(errorlocked && dp->di_mode == 0)) { 229 zlnp = (struct zlncnt *)malloc(sizeof (*zlnp)); 230 if (zlnp == NULL) { 231 pfatal("LINK COUNT TABLE OVERFLOW"); 232 if (reply("CONTINUE") == 0) 233 errexit(""); 234 } else { 235 zlnp->zlncnt = inumber; 236 zlnp->next = zlnhead; 237 zlnhead = zlnp; 238 } 239 } 240 241 /* 242 * Check for holes in a directory inode. 243 * 244 * Handle holes in direct blocks here. 245 * Holes in indirect blocks for large directories 246 * (>NDADDR blocks) will be checked in ckinode(). 247 */ 248 249 idesc.id_llbna = 0; 250 idesc.id_hasholes = 0; 251 if ((((dp->di_mode & IFMT) == IFDIR) || 252 ((dp->di_mode & IFMT) == IFATTRDIR)) && 253 dp->di_size > 0) { 254 255 ndb = howmany(dp->di_size, 256 (u_offset_t)sblock.fs_bsize); 257 ndb = ndb < NDADDR ? ndb : NDADDR; 258 259 for (j = 0; j < ndb; j++) { 260 if (dp->di_db[j] == 0) { 261 pwarn("DIRECTORY I=%d " 262 "HAS HOLES", 263 inumber); 264 if (preen) 265 printf("(CORRECTED)\n"); 266 else if (reply("CORRECT") == 0) 267 break; 268 idesc.id_hasholes = 1; 269 break; 270 } else { 271 idesc.id_llbna++; 272 } 273 } 274 275 if (idesc.id_hasholes) { 276 dp = ginode(inumber); 277 278 /* 279 * Move the existing entries in the 280 * direct block list, down. 281 * 282 * Do this only if the hole is 283 * not in the first block, or else 284 * the "." & the ".." entries will be 285 * missing and cannot be fixed. 286 * Such directories will get cleared. 287 */ 288 for (; j > 0 && j < ndb; j++) { 289 if (!dp->di_db[j]) 290 continue; 291 dp->di_db[idesc.id_llbna++] = 292 dp->di_db[j]; 293 } 294 /* 295 * Clear out rest of the direct block 296 * entries as they could be non zero 297 * as a result of the above operation. 298 */ 299 for (j = idesc.id_llbna; j < NDADDR; 300 j++) 301 dp->di_db[j] = 0; 302 /* 303 * Clear out indirect blocks, if any. 304 * We don't move indirect blocks down 305 * into the direct blocks, as it gets 306 * complicated. 307 * 308 * These blocks have not been accounted 309 * for yet. All the resulting orphaned 310 * directory entries will be taken 311 * care of in this run of pass1() and 312 * hence we do not need another run of 313 * fsck(no need for setting dirholes) 314 */ 315 for (j = 0; j < NIADDR; j++) 316 dp->di_ib[j] = 0; 317 318 /* 319 * update the inode size & blocks count 320 */ 321 dp->di_size = (idesc.id_llbna) * 322 sblock.fs_bsize; 323 dp->di_blocks = dp->di_size / DEV_BSIZE; 324 inodirty(); 325 } 326 } 327 if (((dp->di_mode & IFMT) == IFDIR) || 328 ((dp->di_mode & IFMT) == IFATTRDIR)) { 329 if (dp->di_size == 0) 330 statemap[inumber] = DCLEAR; 331 else 332 statemap[inumber] = DSTATE; 333 cacheino(dp, inumber); 334 } else if ((dp->di_mode & IFMT) == IFSHAD) { 335 if (dp->di_size == 0) 336 statemap[inumber] = SCLEAR; 337 else 338 statemap[inumber] = SSTATE; 339 cacheacl(dp, inumber); 340 } else 341 statemap[inumber] = FSTATE; 342 badblk = dupblk = 0; 343 idesc.id_number = inumber; 344 idesc.id_fix = DONTKNOW; 345 if (dp->di_size > (u_offset_t)MAXOFF_T) { 346 largefile_count++; 347 if (debug) 348 printf("largefile: size=%lld," 349 "count=%d\n", dp->di_size, 350 largefile_count); 351 } 352 (void) ckinode(dp, &idesc); 353 354 /* 355 * Check if we have holes in the directory's indirect 356 * blocks. Update the size. This requires another 357 * pass1 run (fsck once again). 358 */ 359 ndb = howmany(dp->di_size, 360 (u_offset_t)sblock.fs_bsize); 361 if ((((dp->di_mode & IFMT) == IFDIR) || 362 ((dp->di_mode & IFMT) == IFATTRDIR)) && 363 idesc.id_hasholes && idesc.id_llbna >= NDADDR && 364 idesc.id_llbna < ndb) { 365 366 pwarn("DIRECTORY I=%d HAS HOLES", inumber); 367 368 if (preen || reply("CORRECT") == 1) { 369 /* 370 * update the size 371 */ 372 dp = ginode(inumber); 373 dp->di_size = (idesc.id_llbna) * 374 sblock.fs_bsize; 375 /* 376 * Clear out indirect blocks in the 377 * inode beyond the new size. 378 * 379 * All the disk block pointers in the 380 * the indirect blocks past the hole 381 * will get cleared out by the pass1() 382 * run as part of the re-check. 383 */ 384 ndb = howmany(dp->di_size, 385 (u_offset_t)sblock.fs_bsize); 386 for (j = 0, ndb -= NDADDR; ndb > 0; j++) 387 ndb /= NINDIR(&sblock); 388 for (; j < NIADDR; j++) 389 dp->di_ib[j] = 0; 390 391 inodirty(); 392 /* 393 * flag that we need to re-check this 394 * filesystem to recover the blocks we 395 * just orphaned. 396 */ 397 dirholes = 1; 398 } 399 if (preen) 400 printf(" (CORRECTED)\n"); 401 } 402 403 idesc.id_entryno *= btodb(sblock.fs_fsize); 404 if (dp->di_blocks != idesc.id_entryno) { 405 pwarn("INCORRECT BLOCK COUNT I=%u (%d should be %d)", 406 inumber, (uint32_t)dp->di_blocks, 407 idesc.id_entryno); 408 if (preen) 409 printf(" (CORRECTED)\n"); 410 else if (reply("CORRECT") == 0) 411 continue; 412 dp = ginode(inumber); 413 dp->di_blocks = idesc.id_entryno; 414 inodirty(); 415 } 416 if (((dp->di_mode & IFMT) == IFDIR) || 417 ((dp->di_mode & IFMT) == IFATTRDIR)) 418 if (dp->di_blocks == 0) 419 statemap[inumber] = DCLEAR; 420 /* 421 * Check that the ACL is on a valid file type 422 */ 423 shadow = dp->di_shadow; 424 if (shadow != 0) { 425 if (acltypeok(dp) == 0) { 426 pwarn("NON-ZERO ACL REFERENCE, I=%ld", 427 inumber); 428 if (preen) 429 printf(" (CORRECTED)\n"); 430 else if (reply("CORRECT") == 0) 431 continue; 432 dp = ginode(inumber); 433 dp->di_shadow = 0; 434 inodirty(); 435 } else if ((shadow <= UFSROOTINO) || 436 (shadow > maxinumber)) { 437 /* 438 * The shadow inode # must be realistic - 439 * either 0 or a real inode number. 440 */ 441 pwarn("BAD ACL REFERENCE I=%ld", 442 inumber); 443 if (preen) 444 printf(" (CORRECTED)\n"); 445 else if (reply("CORRECT") == 0) 446 continue; 447 dp = ginode(inumber); 448 dp->di_shadow = 0; 449 dp->di_mode &= IFMT; 450 dp->di_smode = dp->di_mode; 451 inodirty(); 452 } else { 453 /* 454 * "register" this inode/shadow pair 455 */ 456 registershadowclient(shadow, 457 inumber, &shadowclientinfo); 458 } 459 } 460 461 attrinode = dp->di_oeftflag; 462 if (attrinode != 0) { 463 if ((attrinode <= UFSROOTINO) || 464 (attrinode > maxinumber)) { 465 /* 466 * The attrdir inode # must be realistic - 467 * either 0 or a real inode number. 468 */ 469 pwarn("BAD ATTRIBUTE REFERENCE I=%ld" 470 " parent file/dir I=%ld", 471 attrinode, inumber); 472 if (preen) 473 printf(" (CORRECTED)\n"); 474 else if (reply("CORRECT") == 0) 475 continue; 476 dp = ginode(inumber); 477 dp->di_oeftflag = 0; 478 dp->di_mode &= IFMT; 479 dp->di_smode = dp->di_mode; 480 inodirty(); 481 } else { 482 /* 483 * "register" this inode/shadow pair 484 */ 485 dp = ginode(attrinode); 486 if ((dp->di_mode & IFMT) != IFATTRDIR) { 487 pwarn("BAD ATTRIBUTE DIR I=%ld" 488 " parent file/dir I=%ld", 489 attrinode, inumber); 490 if (preen) 491 printf( 492 " (CORRECTED)\n"); 493 else if (reply("CORRECT") == 494 0) 495 continue; 496 dp = ginode(inumber); 497 dp->di_oeftflag = 0; 498 inodirty(); 499 } else { 500 registershadowclient(attrinode, 501 inumber, 502 &attrclientinfo); 503 } 504 } 505 } 506 continue; 507 unknown: 508 pfatal("UNKNOWN FILE TYPE I=%u", inumber); 509 if (((dp->di_mode & IFMT) == IFDIR) || 510 ((dp->di_mode & IFMT) == IFATTRDIR)) { 511 statemap[inumber] = DCLEAR; 512 cacheino(dp, inumber); 513 } else 514 statemap[inumber] = FCLEAR; 515 if (reply("CLEAR") == 1) { 516 statemap[inumber] = USTATE; 517 dp = ginode(inumber); 518 clearinode(dp); 519 inodirty(); 520 } 521 } 522 } 523 freeinodebuf(); 524 } 525 526 pass1check(idesc) 527 struct inodesc *idesc; 528 { 529 int res = KEEPON; 530 int anyout; 531 int nfrags; 532 daddr32_t blkno = idesc->id_blkno; 533 struct dups *dlp; 534 struct dups *new; 535 536 if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) { 537 blkerror(idesc->id_number, "BAD", blkno); 538 if (++badblk >= MAXBAD) { 539 pwarn("EXCESSIVE BAD BLKS I=%u", 540 idesc->id_number); 541 if (preen) 542 printf(" (SKIPPING)\n"); 543 else if (reply("CONTINUE") == 0) 544 errexit(""); 545 return (STOP); 546 } 547 } 548 for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { 549 if (anyout && chkrange(blkno, 1)) { 550 res = SKIP; 551 } else if (!testbmap(blkno)) { 552 n_blks++; 553 setbmap(blkno); 554 } else { 555 blkerror(idesc->id_number, "DUP", blkno); 556 if (++dupblk >= MAXDUP) { 557 pwarn("EXCESSIVE DUP BLKS I=%u", 558 idesc->id_number); 559 if (preen) 560 printf(" (SKIPPING)\n"); 561 else if (reply("CONTINUE") == 0) 562 errexit(""); 563 return (STOP); 564 } 565 new = (struct dups *)malloc(sizeof (struct dups)); 566 if (new == NULL) { 567 pfatal("DUP TABLE OVERFLOW."); 568 if (reply("CONTINUE") == 0) 569 errexit(""); 570 return (STOP); 571 } 572 new->dup = blkno; 573 if (muldup == 0) { 574 duplist = muldup = new; 575 new->next = 0; 576 } else { 577 new->next = muldup->next; 578 muldup->next = new; 579 } 580 for (dlp = duplist; dlp != muldup; dlp = dlp->next) 581 if (dlp->dup == blkno) 582 break; 583 if (dlp == muldup && dlp->dup != blkno) 584 muldup = new; 585 } 586 /* 587 * count the number of blocks found in id_entryno 588 */ 589 idesc->id_entryno++; 590 } 591 return (res); 592 } 593