|
|
1.1 ! root 1: /* ! 2: * phase 4 of fsck - Check Reference Counts ! 3: */ ! 4: ! 5: #include "fsck.h" ! 6: ! 7: extern char *reconnect; ! 8: fsize_t lostsize; ! 9: ! 10: phase4() ! 11: { ! 12: ino_t i; ! 13: short actlink; ! 14: ! 15: if (!qflag) ! 16: printf("Phase 4 : Check Reference Counts\n"); ! 17: for (i=FIRSTIN; i<=ninodes; i++) { ! 18: if ( badblks(i) ) ! 19: if ( bddp(i) == YES ) ! 20: continue; /* inode zeroed */ ! 21: ! 22: if ( (linkctr(i) == 0) && ! 23: ((flags(i)&MODEMASK) != IDIR) && ! 24: ((flags(i)&ALLOCMASK) != UNALLOC) ) ! 25: if ( unreflink(i) == YES ) ! 26: continue; /* inode zeroed */ ! 27: ! 28: if ( (linkctr(i) == 0) && ! 29: ((flags(i)&ALLOCMASK) != UNALLOC) ) ! 30: if ( unrefclr(i) == YES ) ! 31: continue; /* inode zeroed */ ! 32: ! 33: if ( (actlink=getlink(i)) == (-1) ) { ! 34: i += INOPB-1; ! 35: continue; /* bad inode block */ ! 36: } ! 37: ! 38: if ( actlink != linkctr(i) ) ! 39: linkprob(i, actlink); /* fix link count */ ! 40: } ! 41: ! 42: freeilist(); ! 43: } ! 44: ! 45: short ! 46: getlink(inum) ! 47: register ino_t inum; ! 48: { ! 49: register unsigned offset; ! 50: static ibuf[BSIZE]; ! 51: register struct dinode *dip; ! 52: register daddr_t bn; ! 53: ! 54: offset = iblocko(inum); ! 55: if ( (offset==0) || (inum==FIRSTIN) ) { ! 56: bn = iblockn(inum); ! 57: if ( (testblock(bn)) && (inum!=FIRSTIN) ) ! 58: return(-1); ! 59: bread(bn, ibuf); ! 60: } ! 61: dip = ((struct dinode *) ibuf) + offset; ! 62: candino(dip); ! 63: return(dip->di_nlink); ! 64: } ! 65: ! 66: char *clearit = "(Clear i-node)"; ! 67: ! 68: unreflink(ino) ! 69: ino_t ino; ! 70: { ! 71: fsize_t size; ! 72: ! 73: if ( qflag && ((flags(ino)&MODEMASK)==IPIPE) && (daction!=NO) ) { ! 74: doclear(ino); ! 75: return(YES); ! 76: } ! 77: ! 78: printf("Unref %s\n", typename(ino)); ! 79: size = pinfo(ino); ! 80: if ( (daction != NO) && (size == 0) && (mounted == FALSE) ! 81: && ((flags(ino)&MODEMASK) == IREG) ) { ! 82: printf("%s [Forced - Yes]\n", clearit); ! 83: doclear(ino); ! 84: return(YES); ! 85: } ! 86: if ( action(reconnect) == TRUE ) ! 87: if( connect(ino, IREG) == FAILURE ) /* connect back in the */ ! 88: return(askclear(ino)); /* non dir inode */ ! 89: ! 90: return(NO); ! 91: } ! 92: ! 93: askclear(ino) ! 94: ino_t ino; ! 95: { ! 96: if ( action(clearit) == TRUE ) { ! 97: doclear(ino); ! 98: return(YES); ! 99: } ! 100: return(NO); ! 101: } ! 102: ! 103: doclear(ino) ! 104: ino_t ino; ! 105: { ! 106: struct dinode *dip; ! 107: ! 108: dip = ptrino(ino, databuf); ! 109: zeroinode(dip); ! 110: writeino(ino, databuf); ! 111: setflags(ino, UNALLOC); ! 112: setlinkctr(ino, 0); ! 113: } ! 114: ! 115: char *adjust = "(Adjust)"; ! 116: ! 117: linkprob(ino, actlink) ! 118: ino_t ino; ! 119: short actlink; ! 120: { ! 121: printf("Link Count discrepancy in %s\n", typename(ino)); ! 122: pinfo(ino); ! 123: printf("Count = %u, should be %u ", actlink, linkctr(ino)); ! 124: if ( action(adjust) == TRUE ) ! 125: chglink(ino); ! 126: } ! 127: ! 128: chglink(ino) ! 129: ino_t ino; ! 130: { ! 131: struct dinode *dip; ! 132: ! 133: dip = ptrino(ino, databuf); ! 134: dip->di_nlink = linkctr(ino); ! 135: writeino(ino, databuf); ! 136: } ! 137: ! 138: unrefclr(ino) ! 139: ino_t ino; ! 140: { ! 141: printf("Unref %s\n", typename(ino)); ! 142: pinfo(ino); ! 143: return(askclear(ino)); ! 144: } ! 145: ! 146: bddp(ino) ! 147: ino_t ino; ! 148: { ! 149: printf("Bad/Dup blocks in %s\n", typename(ino)); ! 150: pinfo(ino); ! 151: return(askclear(ino)); ! 152: } ! 153: ! 154: char *fixit = "(FIX)"; ! 155: ! 156: freeilist() ! 157: { ! 158: ino_t i, count=0; ! 159: daddr_t bn; ! 160: ! 161: for (i=FIRSTIN; i<=ninodes; i++) ! 162: if ( (flags(i)&ALLOCMASK) == UNALLOC ) ! 163: count++; ! 164: ! 165: for (bn=INODEI+1; bn<isize; bn++) /* block # INODEI can't */ ! 166: if ( testblock(bn) ) /* be bad since ROOTIN */ ! 167: count -= INOPB; /* is in it, otherwise */ ! 168: /* big time bad news. */ ! 169: if ( sbp->s_tinode != count ) ! 170: if ( !qflag || (daction==NO) ) { ! 171: printf("Free i-node count wrong in superblock. "); ! 172: if ( action(fixit) == TRUE ) { ! 173: sbp->s_tinode = count; ! 174: sbpfix = TRUE; ! 175: } ! 176: } else if ( daction != NO ) { ! 177: sbp->s_tinode = count; ! 178: sbpfix = TRUE; ! 179: } ! 180: ! 181: if ( (daction!=NO) && ! 182: ( (sflag==TRUE) || (sbpfix==TRUE) || (badilist()==BAD) ) ) ! 183: rebuild(); ! 184: ! 185: } ! 186: ! 187: badilist() ! 188: { ! 189: ino_t i, inum; ! 190: unsigned numfree; ! 191: daddr_t bn; ! 192: ! 193: if ( (numfree=(unsigned) sbp->s_ninode) > NICINOD ) ! 194: return(BAD); ! 195: for (i=0; i<numfree; i++) { ! 196: inum = sbp->s_inode[i]; ! 197: if ( (inum < FIRSTIN) || (inum > ninodes) ) ! 198: return(BAD); ! 199: bn = iblockn(inum); ! 200: if ( (testblock(bn)) && (bn!=INODEI) ) ! 201: return(BAD); ! 202: if ( (flags(inum)&ALLOCMASK) != UNALLOC ) ! 203: return(BAD); ! 204: if ( flags(inum)&IFREELIST ) ! 205: return(BAD); /* dup in ifree list */ ! 206: orflags(inum, IFREELIST); ! 207: } ! 208: return(GOOD); ! 209: } ! 210: ! 211: rebuild() ! 212: { ! 213: daddr_t bn; ! 214: ino_t i; ! 215: int index; ! 216: ! 217: sbpfix = TRUE; ! 218: for (i=FIRSTIN, index=0; (i<=ninodes) && (index<NICINOD); i++) { ! 219: if ( (flags(i)&ALLOCMASK) == UNALLOC ) { ! 220: bn = iblockn(i); ! 221: if ( (!testblock(bn)) || (bn==INODEI) ) ! 222: index++; ! 223: } ! 224: } ! 225: sbp->s_ninode = index; ! 226: for (i=FIRSTIN; (i<=ninodes) && (index>0); i++) { ! 227: if ( (flags(i)&ALLOCMASK) == UNALLOC ) { ! 228: bn = iblockn(i); ! 229: if ( (!testblock(bn)) || (bn==INODEI) ) ! 230: sbp->s_inode[--index] = i; ! 231: } ! 232: } ! 233: printf("Free i-node list in superblock rebuilt.\n"); ! 234: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.