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 * @(#)pass1.c 8.6 (Berkeley) 4/28/95 34 * $FreeBSD: src/sbin/fsck/pass1.c,v 1.16.2.5 2002/06/23 22:34:58 iedowse Exp $ 35 * $DragonFly: src/sbin/fsck/pass1.c,v 1.7 2005/11/06 12:13:53 swildner Exp $ 36 */ 37 38 #include <sys/param.h> 39 40 #include <vfs/ufs/dinode.h> 41 #include <vfs/ufs/dir.h> 42 #include <vfs/ufs/fs.h> 43 44 #include <err.h> 45 #include <string.h> 46 47 #include "fsck.h" 48 49 static ufs_daddr_t badblk; 50 static ufs_daddr_t dupblk; 51 static ino_t lastino; /* last inode in use */ 52 53 static void checkinode(ino_t inumber, struct inodesc *); 54 55 void 56 pass1(void) 57 { 58 u_int8_t *cp; 59 ino_t inumber; 60 int c, i, cgd, inosused; 61 struct inostat *info; 62 struct inodesc idesc; 63 64 /* 65 * Set file system reserved blocks in used block map. 66 */ 67 for (c = 0; c < sblock.fs_ncg; c++) { 68 cgd = cgdmin(&sblock, c); 69 if (c == 0) { 70 i = cgbase(&sblock, c); 71 } else 72 i = cgsblock(&sblock, c); 73 for (; i < cgd; i++) 74 setbmap(i); 75 } 76 i = sblock.fs_csaddr; 77 cgd = i+ howmany(sblock.fs_cssize, sblock.fs_fsize); 78 for (; i < cgd; i++) 79 setbmap(i); 80 /* 81 * Find all allocated blocks. 82 */ 83 memset(&idesc, 0, sizeof(struct inodesc)); 84 idesc.id_type = ADDR; 85 idesc.id_func = pass1check; 86 n_files = n_blks = 0; 87 for (c = 0; c < sblock.fs_ncg; c++) { 88 inumber = c * sblock.fs_ipg; 89 setinodebuf(inumber); 90 inosused = sblock.fs_ipg; 91 if (got_siginfo) { 92 printf("%s: phase 1: cyl group %d of %d (%d%%)\n", 93 cdevname, c, sblock.fs_ncg, 94 c * 100 / sblock.fs_ncg); 95 got_siginfo = 0; 96 } 97 /* 98 * If we are using soft updates, then we can trust the 99 * cylinder group inode allocation maps to tell us which 100 * inodes are allocated. We will scan the used inode map 101 * to find the inodes that are really in use, and then 102 * read only those inodes in from disk. 103 */ 104 if (preen && usedsoftdep) { 105 getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize); 106 if (!cg_chkmagic(&cgrp)) 107 pfatal("CG %d: BAD MAGIC NUMBER\n", c); 108 cp = &cg_inosused(&cgrp)[(sblock.fs_ipg - 1) / NBBY]; 109 for ( ; inosused > 0; inosused -= NBBY, cp--) { 110 if (*cp == 0) 111 continue; 112 for (i = 1 << (NBBY - 1); i > 0; i >>= 1) { 113 if (*cp & i) 114 break; 115 inosused--; 116 } 117 break; 118 } 119 if (inosused < 0) 120 inosused = 0; 121 } 122 /* 123 * Allocate inoinfo structures for the allocated inodes. 124 */ 125 inostathead[c].il_numalloced = inosused; 126 if (inosused == 0) { 127 inostathead[c].il_stat = 0; 128 continue; 129 } 130 info = calloc((unsigned)inosused, sizeof(struct inostat)); 131 if (info == NULL) 132 pfatal("cannot alloc %u bytes for inoinfo\n", 133 (unsigned)(sizeof(struct inostat) * inosused)); 134 inostathead[c].il_stat = info; 135 /* 136 * Scan the allocated inodes. 137 */ 138 for (i = 0; i < inosused; i++, inumber++) { 139 if (inumber < ROOTINO) { 140 getnextinode(inumber); 141 continue; 142 } 143 checkinode(inumber, &idesc); 144 } 145 lastino += 1; 146 if (inosused < sblock.fs_ipg || inumber == lastino) 147 continue; 148 /* 149 * If we were not able to determine in advance which inodes 150 * were in use, then reduce the size of the inoinfo structure 151 * to the size necessary to describe the inodes that we 152 * really found. 153 */ 154 inosused = lastino - (c * sblock.fs_ipg); 155 if (inosused < 0) 156 inosused = 0; 157 inostathead[c].il_numalloced = inosused; 158 if (inosused == 0) { 159 free(inostathead[c].il_stat); 160 inostathead[c].il_stat = 0; 161 continue; 162 } 163 info = calloc((unsigned)inosused, sizeof(struct inostat)); 164 if (info == NULL) 165 pfatal("cannot alloc %u bytes for inoinfo\n", 166 (unsigned)(sizeof(struct inostat) * inosused)); 167 memmove(info, inostathead[c].il_stat, inosused * sizeof(*info)); 168 free(inostathead[c].il_stat); 169 inostathead[c].il_stat = info; 170 } 171 freeinodebuf(); 172 } 173 174 static void 175 checkinode(ino_t inumber, struct inodesc *idesc) 176 { 177 struct dinode *dp; 178 struct zlncnt *zlnp; 179 u_int64_t kernmaxfilesize; 180 ufs_daddr_t ndb, j; 181 mode_t mode; 182 char *symbuf; 183 184 dp = getnextinode(inumber); 185 mode = dp->di_mode & IFMT; 186 if (mode == 0) { 187 if (memcmp(dp->di_db, zino.di_db, 188 NDADDR * sizeof(ufs_daddr_t)) || 189 memcmp(dp->di_ib, zino.di_ib, 190 NIADDR * sizeof(ufs_daddr_t)) || 191 dp->di_mode || dp->di_size) { 192 pfatal("PARTIALLY ALLOCATED INODE I=%lu", inumber); 193 if (reply("CLEAR") == 1) { 194 dp = ginode(inumber); 195 clearinode(dp); 196 inodirty(); 197 } 198 } 199 inoinfo(inumber)->ino_state = USTATE; 200 return; 201 } 202 lastino = inumber; 203 /* This should match the file size limit in ffs_mountfs(). */ 204 kernmaxfilesize = (u_int64_t)0x40000000 * sblock.fs_bsize - 1; 205 if (kernmaxfilesize > (u_int64_t)0x80000000u * PAGE_SIZE - 1) 206 kernmaxfilesize = (u_int64_t)0x80000000u * PAGE_SIZE - 1; 207 if (dp->di_size > kernmaxfilesize || 208 dp->di_size > sblock.fs_maxfilesize || 209 (mode == IFDIR && dp->di_size > MAXDIRSIZE)) { 210 if (debug) 211 printf("bad size %qu:", dp->di_size); 212 goto unknown; 213 } 214 if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) { 215 dp = ginode(inumber); 216 dp->di_size = sblock.fs_fsize; 217 dp->di_mode = IFREG|0600; 218 inodirty(); 219 } 220 if ((mode == IFBLK || mode == IFCHR || mode == IFIFO || 221 mode == IFSOCK) && dp->di_size != 0) { 222 if (debug) 223 printf("bad special-file size %qu:", dp->di_size); 224 goto unknown; 225 } 226 ndb = howmany(dp->di_size, sblock.fs_bsize); 227 if (ndb < 0) { 228 if (debug) 229 printf("bad size %qu ndb %d:", 230 dp->di_size, ndb); 231 goto unknown; 232 } 233 if (mode == IFBLK || mode == IFCHR) 234 ndb++; 235 if (mode == IFLNK) { 236 if (doinglevel2 && 237 dp->di_size > 0 && dp->di_size < MAXSYMLINKLEN && 238 dp->di_blocks != 0) { 239 symbuf = alloca(secsize); 240 if (bread(fsreadfd, symbuf, 241 fsbtodb(&sblock, dp->di_db[0]), 242 (long)secsize) != 0) 243 errx(EEXIT, "cannot read symlink"); 244 if (debug) { 245 symbuf[dp->di_size] = 0; 246 printf("convert symlink %lu(%s) of size %ld\n", 247 (u_long)inumber, symbuf, (long)dp->di_size); 248 } 249 dp = ginode(inumber); 250 memmove(dp->di_shortlink, symbuf, (long)dp->di_size); 251 dp->di_blocks = 0; 252 inodirty(); 253 } 254 /* 255 * Fake ndb value so direct/indirect block checks below 256 * will detect any garbage after symlink string. 257 */ 258 if (dp->di_size < sblock.fs_maxsymlinklen) { 259 ndb = howmany(dp->di_size, sizeof(ufs_daddr_t)); 260 if (ndb > NDADDR) { 261 j = ndb - NDADDR; 262 for (ndb = 1; j > 1; j--) 263 ndb *= NINDIR(&sblock); 264 ndb += NDADDR; 265 } 266 } 267 } 268 for (j = ndb; j < NDADDR; j++) 269 if (dp->di_db[j] != 0) { 270 if (debug) 271 printf("bad direct addr: %ld\n", 272 (long)dp->di_db[j]); 273 goto unknown; 274 } 275 for (j = 0, ndb -= NDADDR; ndb > 0; j++) 276 ndb /= NINDIR(&sblock); 277 for (; j < NIADDR; j++) 278 if (dp->di_ib[j] != 0) { 279 if (debug) 280 printf("bad indirect addr: %ld\n", 281 (long)dp->di_ib[j]); 282 goto unknown; 283 } 284 if (ftypeok(dp) == 0) 285 goto unknown; 286 n_files++; 287 inoinfo(inumber)->ino_linkcnt = dp->di_nlink; 288 if (dp->di_nlink <= 0) { 289 zlnp = (struct zlncnt *)malloc(sizeof *zlnp); 290 if (zlnp == NULL) { 291 pfatal("LINK COUNT TABLE OVERFLOW"); 292 if (reply("CONTINUE") == 0) { 293 ckfini(0); 294 exit(EEXIT); 295 } 296 } else { 297 zlnp->zlncnt = inumber; 298 zlnp->next = zlnhead; 299 zlnhead = zlnp; 300 } 301 } 302 if (mode == IFDIR) { 303 if (dp->di_size == 0) 304 inoinfo(inumber)->ino_state = DCLEAR; 305 else 306 inoinfo(inumber)->ino_state = DSTATE; 307 cacheino(dp, inumber); 308 countdirs++; 309 } else 310 inoinfo(inumber)->ino_state = FSTATE; 311 inoinfo(inumber)->ino_type = IFTODT(mode); 312 if (doinglevel2 && 313 (dp->di_ouid != (u_short)-1 || dp->di_ogid != (u_short)-1)) { 314 dp = ginode(inumber); 315 dp->di_uid = dp->di_ouid; 316 dp->di_ouid = -1; 317 dp->di_gid = dp->di_ogid; 318 dp->di_ogid = -1; 319 inodirty(); 320 } 321 badblk = dupblk = 0; 322 idesc->id_number = inumber; 323 ckinode(dp, idesc); 324 idesc->id_entryno *= btodb(sblock.fs_fsize); 325 if (dp->di_blocks != idesc->id_entryno) { 326 pwarn("INCORRECT BLOCK COUNT I=%lu (%ld should be %ld)", 327 inumber, dp->di_blocks, idesc->id_entryno); 328 if (preen) 329 printf(" (CORRECTED)\n"); 330 else if (reply("CORRECT") == 0) 331 return; 332 dp = ginode(inumber); 333 dp->di_blocks = idesc->id_entryno; 334 inodirty(); 335 } 336 return; 337 unknown: 338 pfatal("UNKNOWN FILE TYPE I=%lu", inumber); 339 inoinfo(inumber)->ino_state = FCLEAR; 340 if (reply("CLEAR") == 1) { 341 inoinfo(inumber)->ino_state = USTATE; 342 dp = ginode(inumber); 343 clearinode(dp); 344 inodirty(); 345 } 346 } 347 348 int 349 pass1check(struct inodesc *idesc) 350 { 351 int res = KEEPON; 352 int anyout, nfrags; 353 ufs_daddr_t blkno = idesc->id_blkno; 354 struct dups *dlp; 355 struct dups *new; 356 357 if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) { 358 blkerror(idesc->id_number, "BAD", blkno); 359 if (badblk++ >= MAXBAD) { 360 pwarn("EXCESSIVE BAD BLKS I=%lu", 361 idesc->id_number); 362 if (preen) 363 printf(" (SKIPPING)\n"); 364 else if (reply("CONTINUE") == 0) { 365 ckfini(0); 366 exit(EEXIT); 367 } 368 return (STOP); 369 } 370 } 371 for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { 372 if (anyout && chkrange(blkno, 1)) { 373 res = SKIP; 374 } else if (!testbmap(blkno)) { 375 n_blks++; 376 setbmap(blkno); 377 } else { 378 blkerror(idesc->id_number, "DUP", blkno); 379 if (dupblk++ >= MAXDUP) { 380 pwarn("EXCESSIVE DUP BLKS I=%lu", 381 idesc->id_number); 382 if (preen) 383 printf(" (SKIPPING)\n"); 384 else if (reply("CONTINUE") == 0) { 385 ckfini(0); 386 exit(EEXIT); 387 } 388 return (STOP); 389 } 390 new = (struct dups *)malloc(sizeof(struct dups)); 391 if (new == NULL) { 392 pfatal("DUP TABLE OVERFLOW."); 393 if (reply("CONTINUE") == 0) { 394 ckfini(0); 395 exit(EEXIT); 396 } 397 return (STOP); 398 } 399 new->dup = blkno; 400 if (muldup == 0) { 401 duplist = muldup = new; 402 new->next = 0; 403 } else { 404 new->next = muldup->next; 405 muldup->next = new; 406 } 407 for (dlp = duplist; dlp != muldup; dlp = dlp->next) 408 if (dlp->dup == blkno) 409 break; 410 if (dlp == muldup && dlp->dup != blkno) 411 muldup = new; 412 } 413 /* 414 * count the number of blocks found in id_entryno 415 */ 416 idesc->id_entryno++; 417 } 418 return (res); 419 } 420