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 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 #if 0 36 static const char sccsid[] = "@(#)pass1.c 8.6 (Berkeley) 4/28/95"; 37 #endif 38 static const char rcsid[] = 39 "$FreeBSD$"; 40 #endif /* not lint */ 41 42 #include <sys/param.h> 43 #include <sys/stat.h> 44 #include <sys/sysctl.h> 45 46 #include <ufs/ufs/dinode.h> 47 #include <ufs/ufs/dir.h> 48 #include <ufs/ffs/fs.h> 49 50 #include <err.h> 51 #include <stdint.h> 52 #include <string.h> 53 54 #include "fsck.h" 55 56 static ufs2_daddr_t badblk; 57 static ufs2_daddr_t dupblk; 58 static ino_t lastino; /* last inode in use */ 59 60 static void checkinode(ino_t inumber, struct inodesc *); 61 62 void 63 pass1(void) 64 { 65 struct inostat *info; 66 struct inodesc idesc; 67 ino_t inumber, inosused; 68 ufs2_daddr_t i, cgd; 69 u_int8_t *cp; 70 int c; 71 72 /* 73 * Set file system reserved blocks in used block map. 74 */ 75 for (c = 0; c < sblock.fs_ncg; c++) { 76 cgd = cgdmin(&sblock, c); 77 if (c == 0) { 78 i = cgbase(&sblock, c); 79 } else 80 i = cgsblock(&sblock, c); 81 for (; i < cgd; i++) 82 setbmap(i); 83 } 84 i = sblock.fs_csaddr; 85 cgd = i + howmany(sblock.fs_cssize, sblock.fs_fsize); 86 for (; i < cgd; i++) 87 setbmap(i); 88 89 /* 90 * Find all allocated blocks. 91 */ 92 memset(&idesc, 0, sizeof(struct inodesc)); 93 idesc.id_func = pass1check; 94 n_files = n_blks = 0; 95 for (c = 0; c < sblock.fs_ncg; c++) { 96 inumber = c * sblock.fs_ipg; 97 setinodebuf(inumber); 98 getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize); 99 if (sblock.fs_magic == FS_UFS2_MAGIC) 100 inosused = cgrp.cg_initediblk; 101 else 102 inosused = sblock.fs_ipg; 103 if (got_siginfo) { 104 printf("%s: phase 1: cyl group %d of %d (%d%%)\n", 105 cdevname, c, sblock.fs_ncg, 106 c * 100 / sblock.fs_ncg); 107 got_siginfo = 0; 108 } 109 /* 110 * If we are using soft updates, then we can trust the 111 * cylinder group inode allocation maps to tell us which 112 * inodes are allocated. We will scan the used inode map 113 * to find the inodes that are really in use, and then 114 * read only those inodes in from disk. 115 */ 116 if (preen && usedsoftdep) { 117 if (!cg_chkmagic(&cgrp)) 118 pfatal("CG %d: BAD MAGIC NUMBER\n", c); 119 cp = &cg_inosused(&cgrp)[(inosused - 1) / NBBY]; 120 for ( ; inosused > 0; inosused -= NBBY, cp--) { 121 if (*cp == 0) 122 continue; 123 for (i = 1 << (NBBY - 1); i > 0; i >>= 1) { 124 if (*cp & i) 125 break; 126 inosused--; 127 } 128 break; 129 } 130 if (inosused < 0) 131 inosused = 0; 132 } 133 /* 134 * Allocate inoinfo structures for the allocated inodes. 135 */ 136 inostathead[c].il_numalloced = inosused; 137 if (inosused == 0) { 138 inostathead[c].il_stat = 0; 139 continue; 140 } 141 info = calloc((unsigned)inosused, sizeof(struct inostat)); 142 if (info == NULL) 143 pfatal("cannot alloc %u bytes for inoinfo\n", 144 (unsigned)(sizeof(struct inostat) * inosused)); 145 inostathead[c].il_stat = info; 146 /* 147 * Scan the allocated inodes. 148 */ 149 for (i = 0; i < inosused; i++, inumber++) { 150 if (inumber < ROOTINO) { 151 (void)getnextinode(inumber); 152 continue; 153 } 154 checkinode(inumber, &idesc); 155 } 156 lastino += 1; 157 if (inosused < sblock.fs_ipg || inumber == lastino) 158 continue; 159 /* 160 * If we were not able to determine in advance which inodes 161 * were in use, then reduce the size of the inoinfo structure 162 * to the size necessary to describe the inodes that we 163 * really found. 164 */ 165 if (lastino < (c * sblock.fs_ipg)) 166 inosused = 0; 167 else 168 inosused = lastino - (c * sblock.fs_ipg); 169 inostathead[c].il_numalloced = inosused; 170 if (inosused == 0) { 171 free(inostathead[c].il_stat); 172 inostathead[c].il_stat = 0; 173 continue; 174 } 175 info = calloc((unsigned)inosused, sizeof(struct inostat)); 176 if (info == NULL) 177 pfatal("cannot alloc %u bytes for inoinfo\n", 178 (unsigned)(sizeof(struct inostat) * inosused)); 179 memmove(info, inostathead[c].il_stat, inosused * sizeof(*info)); 180 free(inostathead[c].il_stat); 181 inostathead[c].il_stat = info; 182 } 183 freeinodebuf(); 184 } 185 186 static void 187 checkinode(ino_t inumber, struct inodesc *idesc) 188 { 189 union dinode *dp; 190 struct zlncnt *zlnp; 191 off_t kernmaxfilesize; 192 ufs2_daddr_t ndb; 193 mode_t mode; 194 int j; 195 196 dp = getnextinode(inumber); 197 mode = DIP(dp, di_mode) & IFMT; 198 if (mode == 0) { 199 if ((sblock.fs_magic == FS_UFS1_MAGIC && 200 (memcmp(dp->dp1.di_db, ufs1_zino.di_db, 201 NDADDR * sizeof(ufs1_daddr_t)) || 202 memcmp(dp->dp1.di_ib, ufs1_zino.di_ib, 203 NIADDR * sizeof(ufs1_daddr_t)) || 204 dp->dp1.di_mode || dp->dp1.di_size)) || 205 (sblock.fs_magic == FS_UFS2_MAGIC && 206 (memcmp(dp->dp2.di_db, ufs2_zino.di_db, 207 NDADDR * sizeof(ufs2_daddr_t)) || 208 memcmp(dp->dp2.di_ib, ufs2_zino.di_ib, 209 NIADDR * sizeof(ufs2_daddr_t)) || 210 dp->dp2.di_mode || dp->dp2.di_size))) { 211 pfatal("PARTIALLY ALLOCATED INODE I=%lu", 212 (u_long)inumber); 213 if (reply("CLEAR") == 1) { 214 dp = ginode(inumber); 215 clearinode(dp); 216 inodirty(); 217 } 218 } 219 inoinfo(inumber)->ino_state = USTATE; 220 return; 221 } 222 lastino = inumber; 223 /* This should match the file size limit in ffs_mountfs(). */ 224 if (sblock.fs_magic == FS_UFS1_MAGIC) 225 kernmaxfilesize = (off_t)0x40000000 * sblock.fs_bsize - 1; 226 else 227 kernmaxfilesize = sblock.fs_maxfilesize; 228 if (DIP(dp, di_size) > kernmaxfilesize || 229 DIP(dp, di_size) > sblock.fs_maxfilesize || 230 (mode == IFDIR && DIP(dp, di_size) > MAXDIRSIZE)) { 231 if (debug) 232 printf("bad size %ju:", (uintmax_t)DIP(dp, di_size)); 233 goto unknown; 234 } 235 if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) { 236 dp = ginode(inumber); 237 DIP(dp, di_size) = sblock.fs_fsize; 238 DIP(dp, di_mode) = IFREG|0600; 239 inodirty(); 240 } 241 if ((mode == IFBLK || mode == IFCHR || mode == IFIFO || 242 mode == IFSOCK) && DIP(dp, di_size) != 0) { 243 if (debug) 244 printf("bad special-file size %ju:", 245 (uintmax_t)DIP(dp, di_size)); 246 goto unknown; 247 } 248 if ((mode == IFBLK || mode == IFCHR) && 249 (dev_t)DIP(dp, di_rdev) == NODEV) { 250 if (debug) 251 printf("bad special-file rdev NODEV:"); 252 goto unknown; 253 } 254 ndb = howmany(DIP(dp, di_size), sblock.fs_bsize); 255 if (ndb < 0) { 256 if (debug) 257 printf("bad size %ju ndb %ju:", 258 (uintmax_t)DIP(dp, di_size), (uintmax_t)ndb); 259 goto unknown; 260 } 261 if (mode == IFBLK || mode == IFCHR) 262 ndb++; 263 if (mode == IFLNK) { 264 /* 265 * Fake ndb value so direct/indirect block checks below 266 * will detect any garbage after symlink string. 267 */ 268 if (DIP(dp, di_size) < (off_t)sblock.fs_maxsymlinklen) { 269 if (sblock.fs_magic == FS_UFS1_MAGIC) 270 ndb = howmany(DIP(dp, di_size), 271 sizeof(ufs1_daddr_t)); 272 else 273 ndb = howmany(DIP(dp, di_size), 274 sizeof(ufs2_daddr_t)); 275 if (ndb > NDADDR) { 276 j = ndb - NDADDR; 277 for (ndb = 1; j > 1; j--) 278 ndb *= NINDIR(&sblock); 279 ndb += NDADDR; 280 } 281 } 282 } 283 for (j = ndb; ndb < NDADDR && j < NDADDR; j++) 284 if (DIP(dp, di_db[j]) != 0) { 285 if (debug) 286 printf("bad direct addr[%d]: %ju\n", j, 287 (uintmax_t)DIP(dp, di_db[j])); 288 goto unknown; 289 } 290 for (j = 0, ndb -= NDADDR; ndb > 0; j++) 291 ndb /= NINDIR(&sblock); 292 for (; j < NIADDR; j++) 293 if (DIP(dp, di_ib[j]) != 0) { 294 if (debug) 295 printf("bad indirect addr: %ju\n", 296 (uintmax_t)DIP(dp, di_ib[j])); 297 goto unknown; 298 } 299 if (ftypeok(dp) == 0) 300 goto unknown; 301 n_files++; 302 inoinfo(inumber)->ino_linkcnt = DIP(dp, di_nlink); 303 if (DIP(dp, di_nlink) <= 0) { 304 zlnp = (struct zlncnt *)malloc(sizeof *zlnp); 305 if (zlnp == NULL) { 306 pfatal("LINK COUNT TABLE OVERFLOW"); 307 if (reply("CONTINUE") == 0) { 308 ckfini(0); 309 exit(EEXIT); 310 } 311 } else { 312 zlnp->zlncnt = inumber; 313 zlnp->next = zlnhead; 314 zlnhead = zlnp; 315 } 316 } 317 if (mode == IFDIR) { 318 if (DIP(dp, di_size) == 0) 319 inoinfo(inumber)->ino_state = DCLEAR; 320 else 321 inoinfo(inumber)->ino_state = DSTATE; 322 cacheino(dp, inumber); 323 countdirs++; 324 } else 325 inoinfo(inumber)->ino_state = FSTATE; 326 inoinfo(inumber)->ino_type = IFTODT(mode); 327 badblk = dupblk = 0; 328 idesc->id_number = inumber; 329 if (DIP(dp, di_flags) & SF_SNAPSHOT) 330 idesc->id_type = SNAP; 331 else 332 idesc->id_type = ADDR; 333 (void)ckinode(dp, idesc); 334 idesc->id_entryno *= btodb(sblock.fs_fsize); 335 if (DIP(dp, di_blocks) != idesc->id_entryno) { 336 pwarn("INCORRECT BLOCK COUNT I=%lu (%ju should be %ju)", 337 (u_long)inumber, (uintmax_t)DIP(dp, di_blocks), 338 (uintmax_t)idesc->id_entryno); 339 if (preen) 340 printf(" (CORRECTED)\n"); 341 else if (reply("CORRECT") == 0) 342 return; 343 if (bkgrdflag == 0) { 344 dp = ginode(inumber); 345 DIP(dp, di_blocks) = idesc->id_entryno; 346 inodirty(); 347 } else { 348 cmd.value = idesc->id_number; 349 cmd.size = idesc->id_entryno - DIP(dp, di_blocks); 350 if (debug) 351 printf("adjblkcnt ino %ju amount %lld\n", 352 (uintmax_t)cmd.value, (long long)cmd.size); 353 if (sysctl(adjblkcnt, MIBSIZE, 0, 0, 354 &cmd, sizeof cmd) == -1) 355 rwerror("ADJUST INODE BLOCK COUNT", cmd.value); 356 } 357 } 358 return; 359 unknown: 360 pfatal("UNKNOWN FILE TYPE I=%lu", (u_long)inumber); 361 inoinfo(inumber)->ino_state = FCLEAR; 362 if (reply("CLEAR") == 1) { 363 inoinfo(inumber)->ino_state = USTATE; 364 dp = ginode(inumber); 365 clearinode(dp); 366 inodirty(); 367 } 368 } 369 370 int 371 pass1check(struct inodesc *idesc) 372 { 373 int res = KEEPON; 374 int anyout, nfrags; 375 ufs2_daddr_t blkno = idesc->id_blkno; 376 struct dups *dlp; 377 struct dups *new; 378 379 if (idesc->id_type == SNAP) { 380 if (blkno == BLK_NOCOPY) 381 return (KEEPON); 382 if (idesc->id_number == cursnapshot) { 383 if (blkno == blkstofrags(&sblock, idesc->id_lbn)) 384 return (KEEPON); 385 if (blkno == BLK_SNAP) { 386 blkno = blkstofrags(&sblock, idesc->id_lbn); 387 idesc->id_entryno -= idesc->id_numfrags; 388 } 389 } else { 390 if (blkno == BLK_SNAP) 391 return (KEEPON); 392 } 393 } 394 if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) { 395 blkerror(idesc->id_number, "BAD", blkno); 396 if (badblk++ >= MAXBAD) { 397 pwarn("EXCESSIVE BAD BLKS I=%lu", 398 (u_long)idesc->id_number); 399 if (preen) 400 printf(" (SKIPPING)\n"); 401 else if (reply("CONTINUE") == 0) { 402 ckfini(0); 403 exit(EEXIT); 404 } 405 return (STOP); 406 } 407 } 408 for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { 409 if (anyout && chkrange(blkno, 1)) { 410 res = SKIP; 411 } else if (!testbmap(blkno)) { 412 n_blks++; 413 setbmap(blkno); 414 } else { 415 blkerror(idesc->id_number, "DUP", blkno); 416 if (dupblk++ >= MAXDUP) { 417 pwarn("EXCESSIVE DUP BLKS I=%lu", 418 (u_long)idesc->id_number); 419 if (preen) 420 printf(" (SKIPPING)\n"); 421 else if (reply("CONTINUE") == 0) { 422 ckfini(0); 423 exit(EEXIT); 424 } 425 return (STOP); 426 } 427 new = (struct dups *)malloc(sizeof(struct dups)); 428 if (new == NULL) { 429 pfatal("DUP TABLE OVERFLOW."); 430 if (reply("CONTINUE") == 0) { 431 ckfini(0); 432 exit(EEXIT); 433 } 434 return (STOP); 435 } 436 new->dup = blkno; 437 if (muldup == 0) { 438 duplist = muldup = new; 439 new->next = 0; 440 } else { 441 new->next = muldup->next; 442 muldup->next = new; 443 } 444 for (dlp = duplist; dlp != muldup; dlp = dlp->next) 445 if (dlp->dup == blkno) 446 break; 447 if (dlp == muldup && dlp->dup != blkno) 448 muldup = new; 449 } 450 /* 451 * count the number of blocks found in id_entryno 452 */ 453 idesc->id_entryno++; 454 } 455 return (res); 456 } 457