|
|
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 == TRUE) && ((flags(ino)&MODEMASK) == IPIPE) ) {
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==FALSE) && (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 {
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.