|
|
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.