|
|
1.1 root 1: #include "fs.h"
2:
3: repairs()
4: { int i, j, k;
5: if(erptr <= 0) {
6: pmesg("all ok\n");
7: return;
8: }
9: i = errcnts[Einvalid] + errcnts[Esuperino] + errcnts[Esuperfree]
10: + errcnts[Efreelist];
11: if(!flags['i'] && i == erptr) {
12: pmesg("fixing super block\n");
13: fixfree();
14: if(!flags['w'])
15: return;
16: if(bwrite(1, (char *)&sblk, 1))
17: fatal("write failed\n");
18: pmesg("done\n");
19: return;
20: }
21: if(!flags['i'] && i + errcnts[Enullable] == erptr) {
22: pmesg("clearing %d inodes safely\n", errcnts[Enullable]);
23: /* even if it is a directory. no links means Edot, Edotdot... */
24: for(j = 0; j < erptr; j++)
25: if(erlist[j].type == Enullable)
26: clri(erlist[j].a);
27: fixfree();
28: return;
29: }
30: /* now we enter upon the realm of the speculative */
31: if(!flags['i'] && !errcnts[Edup]) {
32: pmesg("hi ho hi ho, it's off to work we go\n");
33: if(j = errcnts[Enullable])
34: pmesg("clearing %d inodes safely\n", j);
35: for(j = 0; j < erptr; j++)
36: switch(erlist[j].done? 0: erlist[j].type) {
37: case 0:
38: continue;
39: default:
40: pmesg("%s %d %d, not handled\n", errnm(erlist[j].type),
41: erlist[j].a, erlist[j].b);
42: exitcode++;
43: continue;
44: case Ehole:
45: pmesg("%s ends with a hole, remove or copy\n", prino(erlist[j].a));
46: continue;
47: case Enullable:
48: clri(erlist[j].a);
49: erlist[j].done = 1;
50: continue;
51: case Enotdot: case Enotdotdot: case Edotino: case Ebadparent:
52: k = erlist[j].a;
53: if(k > ROOTINO)
54: fixdots(k);
55: continue;
56: case Elinkcnt:
57: k = erlist[j].a;
58: if(imap[k].type == Weird) {
59: if(fixweird(k))
60: continue;
61: pmesg("weird ino %d (strange type): fix manually\n", k);
62: exitcode = 1;
63: continue;
64: }
65: if(imap[k].nrefs == 0)
66: attach(k);
67: else if(imap[k].type != Unalloc)
68: fixlinks(erlist[j].a);
69: else if(imap[k].nrefs == 1)
70: expunge(k);
71: else {
72: pmesg("%s has %d references! Expunging.\n", prino(k),
73: imap[k].nrefs);
74: expunge(k);
75: exitcode = 1; /* things are not ok */
76: continue;
77: }
78: erlist[j].done = 1;
79: continue;
80: case Ebadname:
81: pmesg("%s has a weird name, look at it\n", prino(erlist[j].b));
82: fixnames(erlist[j].a);
83: continue;
84: case Ebadino: /* these are lost files */
85: pmesg("removing bad inos from %s\n", prino(erlist[j].a));
86: fixnames(erlist[j].a);
87: continue;
88: case Einvalid: case Efreelist: case Esuperino:
89: continue; /* fixfree() comes later */
90: case Eattach:
91: attach(erlist[j].a);
92: erlist[j].done = 1;
93: continue;
94: case Efakeroot:
95: attach(erlist[j].a);
96: fixdots(erlist[j].a);
97: continue;
98: }
99: fixfree();
100: return;
101: }
102: rpterrs();
103: if(flags['i'])
104: interact();
105: else
106: exitcode = 1;
107: }
108:
109: rpterrs()
110: { int i, j, k, cnts[32];
111: struct dinode *dp;
112: if(erptr > 30 && !flags['v']) {
113: pmesg("%d errors\n", erptr);
114: for(i = 0; i < 32; i++)
115: cnts[i] = 0;
116: for(i = 0; i < erptr; i++)
117: cnts[erlist[i].type]++;
118: for(i = 0; i < 32; i++)
119: if(cnts[i])
120: pmesg("%s\t%d\n", errnm(i), cnts[i]);
121: return;
122: }
123: for(i = 0; i < erptr; i++)
124: switch(erlist[i].type) {
125: default:
126: pmesg("%s %d %d\n", errnm(erlist[i].type),
127: erlist[i].a, erlist[i].b);
128: continue;
129: case Efakeroot:
130: pmesg("own parent %s\n", prino(erlist[i].a));
131: continue;
132: case Edup:
133: j = erlist[i].b;
134: k = bmap[erlist[i].a].ino;
135: pmesg("dup block %d %s %s\n", erlist[i].a, prino(j), prino(k));
136: continue;
137: case Elinkcnt:
138: j = erlist[i].a;
139: dp = (struct dinode *)(buf + 2*bsize + (j-1)*sizeof(*dp));
140: pmesg("Elinkcnt(%s) refs %d(parent %s)\n", prino(j), imap[j].nrefs,
141: prino(imap[j].parent));
142: continue;
143: case Ebadparent:
144: j = erlist[i].a;
145: k = erlist[i].b;
146: pmesg("Ebadparent: (%s) not in (%s)\n", prino(j), prino(k));
147: continue;
148: case Ebadname:
149: j = erlist[i].a;
150: k = erlist[i].b;
151: pmesg("Ebadname (%s) (in %s)\n", prino(j), prino(k));
152: continue;
153: }
154: }
155:
156: fixfree()
157: { int i, j, *p;
158: sblk.s_ninode = sblk.s_tfree = 0;
159: sblk.s_tinode = tinode;
160: for(i = 2, j = 0; i < ninode && j < NICINOD; i++)
161: if(imap[i].type == Unalloc) {
162: sblk.s_inode[j++] = i;
163: sblk.s_ninode++;
164: }
165: sblk.s_lasti = sblk.s_inode[0];
166: sblk.s_nbehind = 0;
167: if(bsize < 4096) { /* stupid test, FIX */
168: fix1free();
169: return;
170: }
171: if(pblk > lblk) {
172: for(i = 0; i < BITMAP; i++)
173: sblk.U.B.S_bfree[i] = 0;
174: memset(freeb, 0, (pblk-lblk)*bsize);
175: for(j = i = 0, p = (long *) freeb; i < pblk; i++, j++) {
176: if(j >= 32) {
177: j = 0;
178: p++;
179: }
180: if(bmap[i].type == Free || bmap[i].type == Unk) {
181: sblk.s_tfree++;
182: *p |= (1 << j);
183: }
184: }
185: if(bwrite(lblk, freeb, pblk-lblk)) {
186: exitcode = 1;
187: pmesg("bit map block write failed\n");
188: }
189: }
190: else {
191: for(i = 0, p = sblk.U.B.S_bfree; i < BITMAP; i++)
192: *p++ = 0;
193: for(i = fblk, j = 0, p = sblk.U.B.S_bfree; i < pblk; i++, j++) {
194: if(j >= 32) {
195: j = 0;
196: p++;
197: }
198: if(bmap[i].type == Free || bmap[i].type == Unk) {
199: sblk.s_tfree++;
200: *p |= (1 << j);
201: }
202: }
203: }
204: sblk.U.B.S_valid = 1;
205: if(!flags['w'])
206: return;
207: if(bwrite(1, (char *)&sblk, 1))
208: fatal("super block write failed\n");
209: }
210:
211: fix1free()
212: { /* fix this someday FIX */
213: pmesg("get fsck to fix the free list!\n");
214: if(!flags['w'])
215: return;
216: if(bwrite(1, (char *)&sblk, 1))
217: fatal("super block write failed\n");
218: }
219:
220: fixweird(n)
221: { struct dinode *dp;
222: dp = (struct dinode *) (buf + (n-1)*sizeof(*dp) + 2*bsize);
223: if(dp->di_mode)
224: return(0);
225: if(dp->di_size > 0)
226: return(0);
227: if(imap[n].nrefs > 1)
228: return(0);
229: pmesg("removing weird ino %s\n", prino(n));
230: if(imap[n].nrefs == 1)
231: expunge(n);
232: else {
233: clri(n);
234: pmesg("and rerun chuck\n");
235: }
236: return(1);
237: }
238:
239: fixlinks(n)
240: { struct dinode *dp;
241: dp = (struct dinode *) (buf + (n-1)*sizeof(*dp) + 2*bsize);
242: if(imap[n].type == Unalloc) {
243: pmesg("ino %d unallocated, link count unadjusted\n", n);
244: return;
245: }
246: pmesg("%s getting %d as links\n", prino(n), imap[n].nrefs);
247: dp->di_nlink = imap[n].nrefs;
248: if(flags['w'])
249: wrti(n);
250: }
251:
252: wrti(n) /* write the block of inodes containing inode n */
253: { int i;
254: i = (n-1)/inopb + 2;
255: if(bwrite(i, buf + i*bsize, 1))
256: pmesg("write of block containing ino %d failed\n", n);
257: }
258:
259: clri(n)
260: { struct dinode *dp;
261: static struct dinode nild;
262: dp = (struct dinode *) (buf + (n-1)*sizeof(*dp) + 2*bsize);
263: switch(imap[n].type) {
264: case Dir: case Reg: case Lnk:
265: tossblocks(n);
266: }
267: *dp = nild;
268: imap[n].type = Unalloc;
269: tinode++;
270: if(flags['w'])
271: wrti(n);
272: }
273:
274: tossblocks(n)
275: { struct dinode *dp;
276: int addr[NADDR], i;
277: dp = (struct dinode *) (buf + (n-1)*sizeof(*dp) + 2*bsize);
278: l3tol(addr, dp->di_addr, NADDR);
279: for(i = 1; i < NADDR-3; i++)
280: if(addr[i]) {
281: bmap[addr[i]].type = Free;
282: tfree++;
283: }
284: if(addr[10])
285: freeind(addr[10]);
286: if(addr[11])
287: freedbl(addr[10]);
288: if(addr[12])
289: pmesg("ino %d, triply indirect block? rerun chuck to fix free list\n",
290: n);
291: }
292:
293: freeind(n)
294: { int i, *p;
295: bmap[n].type = Free;
296: if(bread(n, buf, 1))
297: fatal("freeind, could't read block %d\n", n);
298: for(i = 0, p = (int *)buf; i < bsize/sizeof(int); i++, p++)
299: if(*p) {
300: bmap[*p].type = Free;
301: tfree++;
302: }
303: }
304:
305: freedbl(n)
306: { int i, *p;
307: bmap[n].type = Free;
308: if(bread(n, buf+bsize, 1))
309: fatal("freeind2, couldn't read %d\n", n);
310: for(i = 0, p = (int *)(buf+bsize); i < bsize/sizeof(int); i++, p++)
311: if(*p)
312: freeind(n);
313: }
314:
315: interact()
316: { int i, j;
317: struct dinode *dp;
318: for(i = 0; i < erptr; i++)
319: switch(erlist[i].type) {
320: default:
321: pmesg("%s not yet doable\n", errnm(erlist[i].type));
322: continue;
323: case Enotdot:
324: pmesg("Enotdot (dot not self) %s\n", prino(erlist[i].a));
325: continue;
326: case Edotino:
327: pmesg("Edotino (dot illegal) %s\n", prino(erlist[i].a));
328: continue;
329: case Enotdotdot:
330: pmesg("Enotdotdot (dotdot illegal) %s\n", prino(erlist[i].a));
331: continue;
332: case Ebadparent:
333: pmesg("Ebadparent (dotdot not parent) %s\n", prino(erlist[i].a));
334: continue;
335: case Elinkcnt:
336: j = erlist[i].a;
337: dp = (struct dinode *) (buf + 2*bsize + (j-1)*sizeof(*dp));
338: pmesg("Elinkcnt, %s, %d links %d refs\n", prino(j), dp->di_nlink,
339: imap[j].nrefs);
340: if(imap[j].nrefs > 0 || imap[j].type == Weird)
341: switch(qry("clri, links-changed-to-refs, skip:\n")) {
342: case 's':
343: continue;
344: case 'c':
345: pmesg("clearing ino %d\n", j);
346: clri(j);
347: continue;
348: case 'l':
349: pmesg("fixing links ino %d\n", j);
350: fixlinks(j);
351: continue;
352: }
353: switch(qry("attach to /lost+found, expunge:\n")) {
354: case 'a':
355: attach(j);
356: continue;
357: case 'e':
358: expunge(j);
359: continue;
360: }
361: continue;
362: case Enullable:
363: j = erlist[i].a;
364: pmesg("Enullable ino %s\n", prino(j));
365: if(qry("clri, or skip\n") == 'c') {
366: pmesg("clearing ino %d\n", j);
367: clri(j);
368: }
369: continue;
370: case Einvalid:
371: if(qry("valid flag not set, set it?\n") == 'y') {
372: sblk.U.B.S_valid = 1;
373: if(bwrite(1, (char *) &sblk, 1))
374: pmesg("couldn't rewrite super block\n");
375: }
376: continue;
377: }
378: if(qry("fix the super block?\n") == 'y') {
379: pmesg("fixing the superblock\n");
380: fixfree();
381: }
382: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.