1 /* $NetBSD: pass1.c,v 1.43 2006/11/14 21:01:46 apb Exp $ */ 2 3 /* 4 * Copyright (c) 1980, 1986, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)pass1.c 8.6 (Berkeley) 4/28/95"; 36 #else 37 __RCSID("$NetBSD: pass1.c,v 1.43 2006/11/14 21:01:46 apb Exp $"); 38 #endif 39 #endif /* not lint */ 40 41 #include <sys/param.h> 42 #include <sys/stat.h> 43 #include <sys/time.h> 44 45 #include <ufs/ufs/dinode.h> 46 #include <ufs/ufs/dir.h> 47 #include <ufs/ffs/fs.h> 48 #include <ufs/ufs/ufs_bswap.h> 49 #include <ufs/ffs/ffs_extern.h> 50 51 #include <err.h> 52 #include <stdio.h> 53 #include <stdlib.h> 54 #include <string.h> 55 56 #include "fsck.h" 57 #include "extern.h" 58 #include "fsutil.h" 59 60 static daddr_t badblk; 61 static daddr_t dupblk; 62 static void checkinode(ino_t, struct inodesc *); 63 static ino_t lastino; 64 65 void 66 pass1(void) 67 { 68 ino_t inumber, inosused; 69 int c; 70 daddr_t i, cgd; 71 struct inodesc idesc; 72 struct cg *cgp = cgrp; 73 struct inostat *info; 74 uint8_t *cp; 75 76 /* 77 * Set file system reserved blocks in used block map. 78 */ 79 for (c = 0; c < sblock->fs_ncg; c++) { 80 cgd = cgdmin(sblock, c); 81 if (c == 0) 82 i = cgbase(sblock, c); 83 else 84 i = cgsblock(sblock, c); 85 for (; i < cgd; i++) 86 setbmap(i); 87 } 88 i = sblock->fs_csaddr; 89 cgd = i + howmany(sblock->fs_cssize, sblock->fs_fsize); 90 for (; i < cgd; i++) 91 setbmap(i); 92 /* 93 * Find all allocated blocks. 94 */ 95 memset(&idesc, 0, sizeof(struct inodesc)); 96 idesc.id_func = pass1check; 97 n_files = n_blks = 0; 98 for (c = 0; c < sblock->fs_ncg; c++) { 99 inumber = c * sblock->fs_ipg; 100 setinodebuf(inumber); 101 getblk(&cgblk, cgtod(sblock, c), sblock->fs_cgsize); 102 memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize); 103 if((doswap && !needswap) || (!doswap && needswap)) 104 ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock); 105 if (is_ufs2) 106 inosused = cgp->cg_initediblk; 107 else 108 inosused = sblock->fs_ipg; 109 if (got_siginfo) { 110 printf("%s: phase 1: cyl group %d of %d (%d%%)\n", 111 cdevname(), c, sblock->fs_ncg, 112 c * 100 / sblock->fs_ncg); 113 got_siginfo = 0; 114 } 115 #ifdef PROGRESS 116 progress_bar(cdevname(), preen ? NULL : "phase 1", 117 c, sblock->fs_ncg); 118 #endif /* PROGRESS */ 119 /* 120 * If we are using soft updates, then we can trust the 121 * cylinder group inode allocation maps to tell us which 122 * inodes are allocated. We will scan the used inode map 123 * to find the inodes that are really in use, and then 124 * read only those inodes in from disk. 125 */ 126 if (preen && usedsoftdep) { 127 if (!cg_chkmagic(cgp, 0)) 128 pfatal("CG %d: BAD MAGIC NUMBER\n", c); 129 cp = &cg_inosused(cgp, 0)[(inosused - 1) / CHAR_BIT]; 130 for ( ; inosused > 0; inosused -= CHAR_BIT, cp--) { 131 if (*cp == 0) 132 continue; 133 for (i = 1 << (CHAR_BIT - 1); i > 0; i >>= 1) { 134 if (*cp & i) 135 break; 136 inosused--; 137 } 138 break; 139 } 140 #ifdef notdef 141 if (inosused < 0) 142 inosused = 0; 143 #endif 144 } 145 /* 146 * Allocate inoinfo structures for the allocated inodes. 147 */ 148 inostathead[c].il_numalloced = inosused; 149 if (inosused == 0) { 150 inostathead[c].il_stat = 0; 151 continue; 152 } 153 info = calloc((unsigned)inosused, sizeof(struct inostat)); 154 if (info == NULL) { 155 pfatal("cannot alloc %u bytes for inoinfo\n", 156 (unsigned)(sizeof(struct inostat) * inosused)); 157 exit(EEXIT); 158 } 159 inostathead[c].il_stat = info; 160 /* 161 * Scan the allocated inodes. 162 */ 163 for (i = 0; i < inosused; i++, inumber++) { 164 if (inumber < ROOTINO) { 165 (void)getnextinode(inumber); 166 continue; 167 } 168 checkinode(inumber, &idesc); 169 } 170 lastino += 1; 171 if (inosused < sblock->fs_ipg || inumber == lastino) 172 continue; 173 /* 174 * If we were not able to determine in advance which inodes 175 * were in use, then reduce the size of the inoinfo structure 176 * to the size necessary to describe the inodes that we 177 * really found. 178 */ 179 if (lastino < (c * sblock->fs_ipg)) 180 inosused = 0; 181 else 182 inosused = lastino - (c * sblock->fs_ipg); 183 inostathead[c].il_numalloced = inosused; 184 if (inosused == 0) { 185 free(inostathead[c].il_stat); 186 inostathead[c].il_stat = 0; 187 continue; 188 } 189 info = calloc((unsigned)inosused, sizeof(struct inostat)); 190 if (info == NULL) { 191 pfatal("cannot alloc %u bytes for inoinfo\n", 192 (unsigned)(sizeof(struct inostat) * inosused)); 193 exit(EEXIT); 194 } 195 memmove(info, inostathead[c].il_stat, inosused * sizeof(*info)); 196 free(inostathead[c].il_stat); 197 inostathead[c].il_stat = info; 198 } 199 #ifdef PROGRESS 200 if (!preen) 201 progress_done(); 202 #endif /* PROGRESS */ 203 freeinodebuf(); 204 do_blkswap = 0; /* has been done */ 205 } 206 207 static void 208 checkinode(ino_t inumber, struct inodesc *idesc) 209 { 210 union dinode *dp; 211 struct zlncnt *zlnp; 212 daddr_t ndb; 213 int j; 214 mode_t mode; 215 u_int64_t size, kernmaxfilesize; 216 int64_t blocks; 217 char symbuf[MAXBSIZE]; 218 struct inostat *info; 219 220 dp = getnextinode(inumber); 221 info = inoinfo(inumber); 222 mode = iswap16(DIP(dp, mode)) & IFMT; 223 size = iswap64(DIP(dp, size)); 224 if (mode == 0) { 225 if ((is_ufs2 && 226 (memcmp(dp->dp2.di_db, ufs2_zino.di_db, 227 NDADDR * sizeof(int64_t)) || 228 memcmp(dp->dp2.di_ib, ufs2_zino.di_ib, 229 NIADDR * sizeof(int64_t)))) 230 || 231 (!is_ufs2 && 232 (memcmp(dp->dp1.di_db, ufs1_zino.di_db, 233 NDADDR * sizeof(int32_t)) || 234 memcmp(dp->dp1.di_ib, ufs1_zino.di_ib, 235 NIADDR * sizeof(int32_t)))) || 236 mode || size) { 237 pfatal("PARTIALLY ALLOCATED INODE I=%llu", 238 (unsigned long long)inumber); 239 if (reply("CLEAR") == 1) { 240 dp = ginode(inumber); 241 clearinode(dp); 242 inodirty(); 243 } else 244 markclean = 0; 245 } 246 info->ino_state = USTATE; 247 return; 248 } 249 lastino = inumber; 250 /* This should match the file size limit in ffs_mountfs(). */ 251 if (is_ufs2) 252 kernmaxfilesize = sblock->fs_maxfilesize; 253 else 254 kernmaxfilesize = (u_int64_t)0x80000000 * sblock->fs_bsize - 1; 255 if (size > kernmaxfilesize || size + sblock->fs_bsize - 1 < size || 256 (mode == IFDIR && size > MAXDIRSIZE)) { 257 if (debug) 258 printf("bad size %llu:",(unsigned long long)size); 259 goto unknown; 260 } 261 if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) { 262 dp = ginode(inumber); 263 DIP_SET(dp, size, iswap64(sblock->fs_fsize)); 264 size = sblock->fs_fsize; 265 DIP_SET(dp, mode, iswap16(IFREG|0600)); 266 inodirty(); 267 } 268 ndb = howmany(size, sblock->fs_bsize); 269 if (ndb < 0) { 270 if (debug) 271 printf("bad size %llu ndb %lld:", 272 (unsigned long long)size, (long long)ndb); 273 goto unknown; 274 } 275 if (mode == IFBLK || mode == IFCHR) 276 ndb++; 277 if (mode == IFLNK) { 278 /* 279 * Note that the old fastlink format always had di_blocks set 280 * to 0. Other than that we no longer use the `spare' field 281 * (which is now the extended uid) for sanity checking, the 282 * new format is the same as the old. We simply ignore the 283 * conversion altogether. - mycroft, 19MAY1994 284 */ 285 if (!is_ufs2 && doinglevel2 && 286 size > 0 && size < MAXSYMLINKLEN_UFS1 && 287 DIP(dp, blocks) != 0) { 288 if (bread(fsreadfd, symbuf, 289 fsbtodb(sblock, iswap32(DIP(dp, db[0]))), 290 (long)secsize) != 0) 291 errx(EEXIT, "cannot read symlink"); 292 if (debug) { 293 symbuf[size] = 0; 294 printf("convert symlink %llu(%s) " 295 "of size %lld\n", 296 (unsigned long long)inumber, symbuf, 297 (unsigned long long)size); 298 } 299 dp = ginode(inumber); 300 memmove(dp->dp1.di_db, symbuf, (long)size); 301 DIP_SET(dp, blocks, 0); 302 inodirty(); 303 } 304 /* 305 * Fake ndb value so direct/indirect block checks below 306 * will detect any garbage after symlink string. 307 */ 308 if ((sblock->fs_maxsymlinklen < 0) || 309 (size < sblock->fs_maxsymlinklen) || 310 (isappleufs && (size < APPLEUFS_MAXSYMLINKLEN)) || 311 (sblock->fs_maxsymlinklen == 0 && DIP(dp, blocks) == 0)) { 312 if (is_ufs2) 313 ndb = howmany(size, sizeof(int64_t)); 314 else 315 ndb = howmany(size, sizeof(int32_t)); 316 if (ndb > NDADDR) { 317 j = ndb - NDADDR; 318 for (ndb = 1; j > 1; j--) 319 ndb *= NINDIR(sblock); 320 ndb += NDADDR; 321 } 322 } 323 } 324 if (ndb < NDADDR) { 325 for (j = ndb; j < NDADDR; j++) 326 if (DIP(dp, db[j]) != 0) { 327 if (debug) { 328 if (!is_ufs2) 329 printf("bad direct addr ix %d: %d [ndb %lld]\n", 330 j, iswap32(dp->dp1.di_db[j]), 331 (long long)ndb); 332 else 333 printf("bad direct addr ix %d: %lld [ndb %lld]\n", 334 j, (long long)iswap64(dp->dp2.di_db[j]), 335 (long long)ndb); 336 } 337 goto unknown; 338 } 339 } 340 341 for (j = 0, ndb -= NDADDR; ndb > 0; j++) 342 ndb /= NINDIR(sblock); 343 344 for (; j < NIADDR; j++) 345 if (DIP(dp, ib[j]) != 0) { 346 if (debug) { 347 if (!is_ufs2) 348 printf("bad indirect addr: %d\n", 349 iswap32(dp->dp1.di_ib[j])); 350 else 351 printf("bad indirect addr: %lld\n", 352 (long long)iswap64(dp->dp2.di_ib[j])); 353 } 354 goto unknown; 355 } 356 if (ftypeok(dp) == 0) 357 goto unknown; 358 n_files++; 359 info->ino_linkcnt = iswap16(DIP(dp, nlink)); 360 if (info->ino_linkcnt <= 0) { 361 zlnp = (struct zlncnt *)malloc(sizeof *zlnp); 362 if (zlnp == NULL) { 363 markclean = 0; 364 pfatal("LINK COUNT TABLE OVERFLOW"); 365 if (reply("CONTINUE") == 0) { 366 ckfini(); 367 exit(EEXIT); 368 } 369 } else { 370 zlnp->zlncnt = inumber; 371 zlnp->next = zlnhead; 372 zlnhead = zlnp; 373 } 374 } 375 if (mode == IFDIR) { 376 if (size == 0) 377 info->ino_state = DCLEAR; 378 else 379 info->ino_state = DSTATE; 380 cacheino(dp, inumber); 381 countdirs++; 382 } else 383 info->ino_state = FSTATE; 384 info->ino_type = IFTODT(mode); 385 if (!is_ufs2 && doinglevel2 && 386 (iswap16(dp->dp1.di_ouid) != (u_short)-1 || 387 iswap16(dp->dp1.di_ogid) != (u_short)-1)) { 388 dp = ginode(inumber); 389 dp->dp1.di_uid = iswap32(iswap16(dp->dp1.di_ouid)); 390 dp->dp1.di_ouid = iswap16(-1); 391 dp->dp1.di_gid = iswap32(iswap16(dp->dp1.di_ogid)); 392 dp->dp1.di_ogid = iswap16(-1); 393 inodirty(); 394 } 395 badblk = dupblk = 0; 396 idesc->id_number = inumber; 397 if (iswap32(DIP(dp, flags)) & SF_SNAPSHOT) 398 idesc->id_type = SNAP; 399 else 400 idesc->id_type = ADDR; 401 (void)ckinode(dp, idesc); 402 #ifdef notyet 403 if (is_ufs2 && iswap32(dp->dp2.di_extsize) > 0) { 404 int ret, offset; 405 idesc->id_type = ADDR; 406 ndb = howmany(iswap32(dp->dp2.di_extsize), sblock->fs_bsize); 407 for (j = 0; j < NXADDR; j++) { 408 if (--ndb == 0 && 409 (offset = blkoff(sblock, iswap32(dp->dp2.di_extsize))) != 0) 410 idesc->id_numfrags = numfrags(sblock, 411 fragroundup(sblock, offset)); 412 else 413 idesc->id_numfrags = sblock->fs_frag; 414 if (dp->dp2.di_extb[j] == 0) 415 continue; 416 idesc->id_blkno = iswap64(dp->dp2.di_extb[j]); 417 ret = (*idesc->id_func)(idesc); 418 if (ret & STOP) 419 break; 420 } 421 } 422 #endif 423 idesc->id_entryno *= btodb(sblock->fs_fsize); 424 if (is_ufs2) 425 blocks = iswap64(dp->dp2.di_blocks); 426 else 427 blocks = iswap32(dp->dp1.di_blocks); 428 if (blocks != idesc->id_entryno) { 429 pwarn("INCORRECT BLOCK COUNT I=%llu (%lld should be %lld)", 430 (unsigned long long)inumber, (long long)blocks, 431 (long long)idesc->id_entryno); 432 if (preen) 433 printf(" (CORRECTED)\n"); 434 else if (reply("CORRECT") == 0) { 435 markclean = 0; 436 return; 437 } 438 dp = ginode(inumber); 439 if (is_ufs2) 440 dp->dp2.di_blocks = iswap64(idesc->id_entryno); 441 else 442 dp->dp1.di_blocks = iswap32((int32_t)idesc->id_entryno); 443 inodirty(); 444 } 445 return; 446 unknown: 447 pfatal("UNKNOWN FILE TYPE I=%llu", (unsigned long long)inumber); 448 info->ino_state = FCLEAR; 449 if (reply("CLEAR") == 1) { 450 info->ino_state = USTATE; 451 dp = ginode(inumber); 452 clearinode(dp); 453 inodirty(); 454 } else 455 markclean = 0; 456 } 457 458 int 459 pass1check(struct inodesc *idesc) 460 { 461 int res = KEEPON; 462 int anyout, nfrags; 463 daddr_t blkno = idesc->id_blkno; 464 struct dups *dlp; 465 struct dups *new; 466 467 if (idesc->id_type == SNAP) { 468 if (blkno == BLK_NOCOPY || blkno == BLK_SNAP) 469 return (KEEPON); 470 } 471 if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) { 472 blkerror(idesc->id_number, "BAD", blkno); 473 if (badblk++ >= MAXBAD) { 474 pwarn("EXCESSIVE BAD BLKS I=%llu", 475 (unsigned long long)idesc->id_number); 476 if (preen) 477 printf(" (SKIPPING)\n"); 478 else if (reply("CONTINUE") == 0) { 479 markclean = 0; 480 ckfini(); 481 exit(EEXIT); 482 } 483 return (STOP); 484 } 485 } 486 for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { 487 if (anyout && chkrange(blkno, 1)) { 488 res = SKIP; 489 } else if (!testbmap(blkno)) { 490 n_blks++; 491 setbmap(blkno); 492 } else { 493 blkerror(idesc->id_number, "DUP", blkno); 494 if (dupblk++ >= MAXDUP) { 495 pwarn("EXCESSIVE DUP BLKS I=%llu", 496 (unsigned long long)idesc->id_number); 497 if (preen) 498 printf(" (SKIPPING)\n"); 499 else if (reply("CONTINUE") == 0) { 500 markclean = 0; 501 ckfini(); 502 exit(EEXIT); 503 } 504 return (STOP); 505 } 506 new = (struct dups *)malloc(sizeof(struct dups)); 507 if (new == NULL) { 508 markclean = 0; 509 pfatal("DUP TABLE OVERFLOW."); 510 if (reply("CONTINUE") == 0) { 511 markclean = 0; 512 ckfini(); 513 exit(EEXIT); 514 } 515 return (STOP); 516 } 517 new->dup = blkno; 518 if (muldup == 0) { 519 duplist = muldup = new; 520 new->next = 0; 521 } else { 522 new->next = muldup->next; 523 muldup->next = new; 524 } 525 for (dlp = duplist; dlp != muldup; dlp = dlp->next) 526 if (dlp->dup == blkno) 527 break; 528 if (dlp == muldup && dlp->dup != blkno) 529 muldup = new; 530 } 531 /* 532 * count the number of blocks found in id_entryno 533 */ 534 idesc->id_entryno++; 535 } 536 return (res); 537 } 538