116262Smckusick #ifndef lint 2*17931Smckusick static char version[] = "@(#)pass1.c 3.2 (Berkeley) 02/07/85"; 316262Smckusick #endif 416262Smckusick 516262Smckusick #include <sys/param.h> 616262Smckusick #include <sys/inode.h> 716262Smckusick #include <sys/fs.h> 816262Smckusick #include "fsck.h" 916262Smckusick 1016262Smckusick int pass1check(); 1116262Smckusick 1216262Smckusick pass1() 1316262Smckusick { 1416262Smckusick register int c, i, n, j; 1516262Smckusick register DINODE *dp; 16*17931Smckusick int ndb, partial, cgd; 1716262Smckusick struct inodesc idesc; 1816262Smckusick ino_t inumber; 1916262Smckusick 20*17931Smckusick /* 21*17931Smckusick * Set file system reserved blocks in used block map. 22*17931Smckusick */ 23*17931Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 24*17931Smckusick cgd = cgdmin(&sblock, c); 25*17931Smckusick if (c == 0) { 26*17931Smckusick i = cgbase(&sblock, c); 27*17931Smckusick cgd += howmany(sblock.fs_cssize, sblock.fs_fsize); 28*17931Smckusick } else 29*17931Smckusick i = cgsblock(&sblock, c); 30*17931Smckusick for (; i < cgd; i++) 31*17931Smckusick setbmap(i); 32*17931Smckusick } 33*17931Smckusick /* 34*17931Smckusick * Find all allocated blocks. 35*17931Smckusick */ 3616262Smckusick bzero((char *)&idesc, sizeof(struct inodesc)); 3716262Smckusick idesc.id_type = ADDR; 3816262Smckusick idesc.id_func = pass1check; 3916262Smckusick inumber = 0; 4016262Smckusick n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize); 4116262Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 4216262Smckusick if (getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize) == 0) 4316262Smckusick continue; 4416262Smckusick if (cgrp.cg_magic != CG_MAGIC) { 4516262Smckusick pfatal("CG %d: BAD MAGIC NUMBER\n", c); 4616262Smckusick bzero((char *)&cgrp, (int)sblock.fs_cgsize); 4716262Smckusick } 4816262Smckusick n = 0; 4916262Smckusick for (i = 0; i < sblock.fs_ipg; i++, inumber++) { 5016262Smckusick dp = ginode(inumber); 5116262Smckusick if (dp == NULL) 5216262Smckusick continue; 5316262Smckusick n++; 54*17931Smckusick if (ALLOC(dp)) { 5516262Smckusick if (!isset(cgrp.cg_iused, i)) { 5616262Smckusick if (debug) 5716262Smckusick printf("%d bad, not used\n", 5816262Smckusick inumber); 5916262Smckusick inosumbad++; 6016262Smckusick } 6116262Smckusick n--; 6216262Smckusick lastino = inumber; 6316262Smckusick if (!preen && (dp->di_mode & IFMT) == IFMT && 6416262Smckusick reply("HOLD BAD BLOCK") == 1) { 6516262Smckusick dp->di_size = sblock.fs_fsize; 6616262Smckusick dp->di_mode = IFREG|0600; 6716262Smckusick inodirty(); 6816262Smckusick } else if (ftypeok(dp) == 0) 6916262Smckusick goto unknown; 7016262Smckusick if (dp->di_size < 0) { 7116262Smckusick if (debug) 7216262Smckusick printf("bad size %d:", 7316262Smckusick dp->di_size); 7416262Smckusick goto unknown; 7516262Smckusick } 7616262Smckusick ndb = howmany(dp->di_size, sblock.fs_bsize); 77*17931Smckusick if (SPECIAL(dp)) 7816262Smckusick ndb++; 7916262Smckusick for (j = ndb; j < NDADDR; j++) 8016262Smckusick if (dp->di_db[j] != 0) { 8116262Smckusick if (debug) 8216262Smckusick printf("bad direct addr: %d\n", 8316262Smckusick dp->di_db[j]); 8416262Smckusick goto unknown; 8516262Smckusick } 8616262Smckusick for (j = 0, ndb -= NDADDR; ndb > 0; j++) 8716262Smckusick ndb /= NINDIR(&sblock); 8816262Smckusick for (; j < NIADDR; j++) 8916262Smckusick if (dp->di_ib[j] != 0) { 9016262Smckusick if (debug) 9116262Smckusick printf("bad indirect addr: %d\n", 9216262Smckusick dp->di_ib[j]); 9316262Smckusick goto unknown; 9416262Smckusick } 9516262Smckusick n_files++; 9616262Smckusick lncntp[inumber] = dp->di_nlink; 9716262Smckusick if (dp->di_nlink <= 0) { 9816262Smckusick if (badlnp < &badlncnt[MAXLNCNT]) 9916262Smckusick *badlnp++ = inumber; 10016262Smckusick else { 10116262Smckusick pfatal("LINK COUNT TABLE OVERFLOW"); 10216262Smckusick if (reply("CONTINUE") == 0) 10316262Smckusick errexit(""); 10416262Smckusick } 10516262Smckusick } 106*17931Smckusick statemap[inumber] = DIRCT(dp) ? DSTATE : FSTATE; 10716262Smckusick badblk = dupblk = 0; maxblk = 0; 10816262Smckusick idesc.id_number = inumber; 10916262Smckusick idesc.id_filesize = 0; 11016262Smckusick (void)ckinode(dp, &idesc); 11116262Smckusick idesc.id_filesize *= btodb(sblock.fs_fsize); 11216262Smckusick if (dp->di_blocks != idesc.id_filesize) { 11316262Smckusick pwarn("INCORRECT BLOCK COUNT I=%u (%ld should be %ld)", 11416262Smckusick inumber, dp->di_blocks, 11516262Smckusick idesc.id_filesize); 11616262Smckusick if (preen) 11716262Smckusick printf(" (CORRECTED)\n"); 11816262Smckusick else if (reply("CORRECT") == 0) 11916262Smckusick continue; 12016262Smckusick dp->di_blocks = idesc.id_filesize; 12116262Smckusick inodirty(); 12216262Smckusick } 12316262Smckusick continue; 12416262Smckusick unknown: 12516262Smckusick pfatal("UNKNOWN FILE TYPE I=%u", inumber); 12616262Smckusick if (reply("CLEAR") == 1) { 12716262Smckusick zapino(dp); 12816262Smckusick inodirty(); 12916262Smckusick inosumbad++; 13016262Smckusick } 13116262Smckusick } else { 13216262Smckusick if (isset(cgrp.cg_iused, i)) { 13316262Smckusick if (debug) 13416262Smckusick printf("%d bad, marked used\n", 13516262Smckusick inumber); 13616262Smckusick inosumbad++; 13716262Smckusick n--; 13816262Smckusick } 13916262Smckusick partial = 0; 14016262Smckusick for (j = 0; j < NDADDR; j++) 14116262Smckusick if (dp->di_db[j] != 0) 14216262Smckusick partial++; 14316262Smckusick for (j = 0; j < NIADDR; j++) 14416262Smckusick if (dp->di_ib[j] != 0) 14516262Smckusick partial++; 14616262Smckusick if (partial || dp->di_mode != 0 || 14716262Smckusick dp->di_size != 0) { 14816262Smckusick pfatal("PARTIALLY ALLOCATED INODE I=%u", 14916262Smckusick inumber); 15016262Smckusick if (reply("CLEAR") == 1) { 15116262Smckusick zapino(dp); 15216262Smckusick inodirty(); 15316262Smckusick inosumbad++; 15416262Smckusick } 15516262Smckusick } 15616262Smckusick } 15716262Smckusick } 15816262Smckusick if (n != cgrp.cg_cs.cs_nifree) { 15916262Smckusick if (debug) 16016262Smckusick printf("cg[%d].cg_cs.cs_nifree is %d; calc %d\n", 16116262Smckusick c, cgrp.cg_cs.cs_nifree, n); 16216262Smckusick inosumbad++; 16316262Smckusick } 16416262Smckusick if (cgrp.cg_cs.cs_nbfree != sblock.fs_cs(&sblock, c).cs_nbfree 16516262Smckusick || cgrp.cg_cs.cs_nffree != sblock.fs_cs(&sblock, c).cs_nffree 16616262Smckusick || cgrp.cg_cs.cs_nifree != sblock.fs_cs(&sblock, c).cs_nifree 16716262Smckusick || cgrp.cg_cs.cs_ndir != sblock.fs_cs(&sblock, c).cs_ndir) 16816262Smckusick sbsumbad++; 16916262Smckusick } 17016262Smckusick } 17116262Smckusick 17216262Smckusick pass1check(idesc) 17316262Smckusick register struct inodesc *idesc; 17416262Smckusick { 17516262Smckusick register daddr_t *dlp; 17616262Smckusick int res = KEEPON; 17716262Smckusick int anyout, nfrags; 17816262Smckusick daddr_t blkno = idesc->id_blkno; 17916262Smckusick 180*17931Smckusick if ((anyout = outrange(blkno, idesc->id_numfrags)) != 0) { 181*17931Smckusick blkerr(idesc->id_number, "BAD", blkno); 182*17931Smckusick if (++badblk >= MAXBAD) { 183*17931Smckusick pwarn("EXCESSIVE BAD BLKS I=%u", 184*17931Smckusick idesc->id_number); 185*17931Smckusick if (preen) 186*17931Smckusick printf(" (SKIPPING)\n"); 187*17931Smckusick else if (reply("CONTINUE") == 0) 188*17931Smckusick errexit(""); 189*17931Smckusick return (STOP); 190*17931Smckusick } 191*17931Smckusick } 19216262Smckusick for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { 19316262Smckusick if (anyout && outrange(blkno, 1)) { 19416262Smckusick res = SKIP; 195*17931Smckusick } else if (!getbmap(blkno)) { 196*17931Smckusick n_blks++; 197*17931Smckusick setbmap(blkno); 198*17931Smckusick } else { 19916262Smckusick blkerr(idesc->id_number, "DUP", blkno); 20016262Smckusick if (++dupblk >= MAXDUP) { 20116262Smckusick pwarn("EXCESSIVE DUP BLKS I=%u", 20216262Smckusick idesc->id_number); 20316262Smckusick if (preen) 20416262Smckusick printf(" (SKIPPING)\n"); 20516262Smckusick else if (reply("CONTINUE") == 0) 20616262Smckusick errexit(""); 20716262Smckusick return (STOP); 20816262Smckusick } 20916262Smckusick if (enddup >= &duplist[DUPTBLSIZE]) { 21016262Smckusick pfatal("DUP TABLE OVERFLOW."); 21116262Smckusick if (reply("CONTINUE") == 0) 21216262Smckusick errexit(""); 21316262Smckusick return (STOP); 21416262Smckusick } 21516262Smckusick for (dlp = duplist; dlp < muldup; dlp++) 21616262Smckusick if (*dlp == blkno) { 21716262Smckusick *enddup++ = blkno; 21816262Smckusick break; 21916262Smckusick } 22016262Smckusick if (dlp >= muldup) { 22116262Smckusick *enddup++ = *muldup; 22216262Smckusick *muldup++ = blkno; 22316262Smckusick } 22416262Smckusick } 22516262Smckusick idesc->id_filesize++; 22616262Smckusick } 22716262Smckusick return (res); 22816262Smckusick } 229