|
|
1.1 ! root 1: /* ! 2: * bad.c ! 3: * 11/6/92 ! 4: * Usage: bad option filesystem [ block ... ] ! 5: * Manipulate bad block list. ! 6: */ ! 7: ! 8: #include <stdio.h> ! 9: #include <canon.h> ! 10: #include <sys/filsys.h> ! 11: #include <sys/ino.h> ! 12: #include <sys/inode.h> ! 13: ! 14: #define USAGE "\ ! 15: Usage: bad option filesystem [ block ... ]\n\ ! 16: Options:\n\ ! 17: a Add blocks\n\ ! 18: c Clear bad-block list\n\ ! 19: d Delete blocks\n\ ! 20: l List blocks\n" ! 21: ! 22: /* Forward. */ ! 23: int addlist(); ! 24: long atol(); ! 25: char *bread(); ! 26: char *bclaim(); ! 27: char *index(); ! 28: char *realloc(); ! 29: daddr_t balloc(); ! 30: int dellist(); ! 31: ! 32: /* Globals. */ ! 33: struct filsys supb; /* Super block */ ! 34: INODE inol; /* Bad block inode */ ! 35: char bufl[1+NI][BSIZE]; /* Buffers for bread */ ! 36: daddr_t bnol[1+NI]; /* Block numbers */ ! 37: daddr_t *badl; /* Bad block list */ ! 38: int badn; /* Number of bad blocks in list */ ! 39: int badm; /* Maximum number of bad blocks */ ! 40: int filf; /* Filesystem file descriptor */ ! 41: ! 42: main(argc, argv) ! 43: char *argv[]; ! 44: { ! 45: register int i; ! 46: ! 47: if (argc < 3) ! 48: usage(); ! 49: if ((filf=open(argv[2], (argv[1][0] == 'l') ? 0 : 2)) < 0) ! 50: panic("cannot open \"%s\"", argv[2]); ! 51: badm = 64; ! 52: if ((badl=malloc(badm*sizeof(*badl))) == NULL) ! 53: panic("out of memory"); ! 54: switch (argv[1][0]) { ! 55: case 'a': ! 56: gather(); ! 57: for (i=3; i<argc; i++) ! 58: route(argv[i], addlist); ! 59: update(); ! 60: break; ! 61: case 'c': ! 62: update(); ! 63: break; ! 64: case 'd': ! 65: gather(); ! 66: for (i=3; i<argc; i++) ! 67: route(argv[i], dellist); ! 68: update(); ! 69: break; ! 70: case 'l': ! 71: gather(); ! 72: display(); ! 73: break; ! 74: default: ! 75: usage(); ! 76: } ! 77: } ! 78: ! 79: /* ! 80: * Print out usage. ! 81: */ ! 82: usage() ! 83: { ! 84: fprintf(stderr, USAGE); ! 85: exit(1); ! 86: } ! 87: ! 88: /* ! 89: * Given a string and a pointer to a function, extract a list of block ! 90: * numbers from the string and call the function with them. ! 91: */ ! 92: route(cp1, f) ! 93: register char *cp1; ! 94: int (*f)(); ! 95: { ! 96: register char *cp2; ! 97: register long b; ! 98: register long l; ! 99: ! 100: if ((cp2=index(cp1, '-')) == NULL) ! 101: (*f)(atol(cp1)); ! 102: else { ! 103: *cp2++ = '\0'; ! 104: l = atol(cp2); ! 105: for (b=atol(cp1); b<=l; b++) ! 106: (*f)(b); ! 107: } ! 108: } ! 109: ! 110: /* ! 111: * List the set of bad blocks. ! 112: */ ! 113: display() ! 114: { ! 115: register int i; ! 116: ! 117: for (i=0; i<badn; i++) ! 118: printf("%ld\n", badl[i]); ! 119: } ! 120: ! 121: /* ! 122: * Read the list of bad blocks into the bad block list. ! 123: */ ! 124: gather() ! 125: { ! 126: register int n; ! 127: register daddr_t b; ! 128: ! 129: copydm(); ! 130: for (n=0; n<ND; n++) { ! 131: if ((b=inol.i_a.i_addr[n]) != 0) ! 132: addlist(b); ! 133: } ! 134: for (n=ND; n<ND+NI; n++) { ! 135: if ((b=inol.i_a.i_addr[n]) != 0) ! 136: indlist(b, 1+n-ND); ! 137: } ! 138: } ! 139: ! 140: /* ! 141: * Given an indirect block, `b', with level of indirection, `l', add all ! 142: * allocated blocks onto the bad block list. ! 143: */ ! 144: indlist(b, l) ! 145: daddr_t b; ! 146: register unsigned l; ! 147: { ! 148: register int i; ! 149: register char *bp; ! 150: daddr_t b1; ! 151: ! 152: if (b == 0) ! 153: return; ! 154: if (l-- > 0) { ! 155: bp = bread(l, b); ! 156: for (i=0; i<NBN; i++) { ! 157: if ((b1=((daddr_t *)bp)[i]) == 0) ! 158: continue; ! 159: candaddr(b1); ! 160: if (l == 0) ! 161: addlist(b1); ! 162: else ! 163: indlist(b1, l); ! 164: } ! 165: } ! 166: } ! 167: ! 168: /* ! 169: * Add the given block onto the end of the bad block list. ! 170: */ ! 171: addlist(b) ! 172: daddr_t b; ! 173: { ! 174: register int i; ! 175: register int n; ! 176: ! 177: if (badn >= badm) { ! 178: if ( badm >= (2*badm) ) /* catch wordlength rollover */ ! 179: panic("too many bad blocks"); ! 180: badm *= 2; ! 181: if ((badl=realloc(badl, badm*sizeof(*badl))) == NULL) ! 182: panic("out of memory"); ! 183: } ! 184: for (i=0; i<badn; i++) { ! 185: if (b == badl[i]) ! 186: panic("duplicate bad block %ld", b); ! 187: if (b < badl[i]) ! 188: break; ! 189: } ! 190: for (n=badn; n>i; --n) ! 191: badl[n] = badl[n-1]; ! 192: badl[i] = b; ! 193: badn++; ! 194: } ! 195: ! 196: /* ! 197: * Delete the given bad block from the bad block list. ! 198: */ ! 199: dellist(b) ! 200: daddr_t b; ! 201: { ! 202: register int n; ! 203: ! 204: for (n=0; n<badn; n++) { ! 205: if (b == badl[n]) { ! 206: for (--badn; n<badn; n++) ! 207: badl[n] = badl[n+1]; ! 208: return; ! 209: } ! 210: } ! 211: panic("cannot find block %ld", b); ! 212: } ! 213: ! 214: /* ! 215: * Update the bad block file. ! 216: */ ! 217: update() ! 218: { ! 219: register char *bp; ! 220: register int i; ! 221: ! 222: bp = bread(0, (daddr_t)SUPERI); ! 223: strcopy(bp, (char *)&supb, sizeof(struct filsys)); ! 224: cansuper(&supb); ! 225: for (i=0; i<ND+NI; i++) ! 226: inol.i_a.i_addr[i] = 0; ! 227: for (i=0; i<badn; i++) ! 228: block(i, badl[i]); ! 229: copymd(); ! 230: bp = bread(0, (daddr_t)SUPERI); ! 231: strcopy((char *)&supb, bp, sizeof(supb)); ! 232: cansuper((struct filsys *)bp); ! 233: bwrite(bp, (daddr_t)SUPERI); ! 234: } ! 235: ! 236: /* ! 237: * Canonize the super block. ! 238: */ ! 239: cansuper(sbp) ! 240: register struct filsys *sbp; ! 241: { ! 242: register int i; ! 243: ! 244: canint(sbp->s_isize); ! 245: candaddr(sbp->s_fsize); ! 246: canshort(sbp->s_nfree); ! 247: for (i=0; i<NICFREE; i++) ! 248: candaddr(sbp->s_free[i]); ! 249: canshort(sbp->s_ninode); ! 250: for (i=0; i<NICINOD; i++) ! 251: canino(sbp->s_inode[i]); ! 252: cantime(sbp->s_time); ! 253: candaddr(sbp->s_tfree); ! 254: canino(sbp->s_tinode); ! 255: canshort(sbp->s_m); ! 256: canshort(sbp->s_n); ! 257: canlong(sbp->s_unique); ! 258: } ! 259: ! 260: /* ! 261: * Copy the bad block inode to memory performing canonization. ! 262: */ ! 263: copydm() ! 264: { ! 265: register struct dinode *dip; ! 266: register char *bp; ! 267: ! 268: bp = bread(0, (daddr_t)iblockn(BADFIN)); ! 269: dip = (struct dinode *)bp+iblocko(BADFIN); ! 270: inol.i_mode = dip->di_mode; ! 271: canshort(inol.i_mode); ! 272: inol.i_nlink = dip->di_nlink; ! 273: canshort(inol.i_nlink); ! 274: inol.i_uid = dip->di_uid; ! 275: canshort(inol.i_uid); ! 276: inol.i_gid = dip->di_gid; ! 277: canshort(inol.i_gid); ! 278: inol.i_size = dip->di_size; ! 279: cansize(inol.i_size); ! 280: l3tol(inol.i_a.i_addr, dip->di_addr, NADDR); ! 281: inol.i_atime = dip->di_atime; ! 282: cantime(inol.i_atime); ! 283: inol.i_mtime = dip->di_mtime; ! 284: cantime(inol.i_mtime); ! 285: inol.i_ctime = dip->di_ctime; ! 286: cantime(inol.i_ctime); ! 287: return (1); ! 288: } ! 289: ! 290: /* ! 291: * Copy the bad block inode to disk performing canonization. ! 292: */ ! 293: copymd() ! 294: { ! 295: register struct dinode *dip; ! 296: register char *bp; ! 297: ! 298: bp = bread(0, (daddr_t)iblockn(BADFIN)); ! 299: dip = (struct dinode *)bp+iblocko(BADFIN); ! 300: dip->di_mode = IFREG; ! 301: canshort(dip->di_mode); ! 302: dip->di_nlink = inol.i_nlink; ! 303: canshort(dip->di_nlink); ! 304: dip->di_uid = inol.i_uid; ! 305: canshort(dip->di_uid); ! 306: dip->di_gid = inol.i_gid; ! 307: canshort(dip->di_gid); ! 308: dip->di_size = ((fsize_t)badn)*BSIZE; ! 309: cansize(dip->di_size); ! 310: ltol3(dip->di_addr, inol.i_a.i_addr, NADDR); ! 311: dip->di_atime = inol.i_atime; ! 312: cantime(dip->di_atime); ! 313: dip->di_mtime = inol.i_mtime; ! 314: cantime(dip->di_mtime); ! 315: dip->di_ctime = inol.i_ctime; ! 316: cantime(dip->di_ctime); ! 317: bwrite(bp, (daddr_t)iblockn(BADFIN)); ! 318: } ! 319: ! 320: /* ! 321: * Make the physical block, `b', logical block, `n' of the bad block file. ! 322: */ ! 323: block(n, b) ! 324: register int n; ! 325: register daddr_t b; ! 326: { ! 327: register daddr_t pb; ! 328: register char *bp; ! 329: register daddr_t pbb; ! 330: register char *bpp; ! 331: ! 332: if (n < ND) { ! 333: inol.i_a.i_addr[n] = b; ! 334: return; ! 335: } ! 336: n -= ND; ! 337: if (n < NBN) { ! 338: if ((pb=inol.i_a.i_addr[ND]) != 0) ! 339: bp = bread(1, pb); ! 340: else { ! 341: inol.i_a.i_addr[ND] = pb = balloc(); ! 342: bp = bclaim(1); ! 343: } ! 344: ((daddr_t *)bp)[n] = b; ! 345: candaddr(((daddr_t *)bp)[n]); ! 346: bwrite(bp, pb); ! 347: return; ! 348: } ! 349: n -= NBN; ! 350: if (n < NBN*NBN) { ! 351: if ((pbb=inol.i_a.i_addr[ND+1]) != 0) ! 352: bpp = bread(2, pbb); ! 353: else { ! 354: inol.i_a.i_addr[ND+1] = pbb = balloc(); ! 355: bpp = bclaim(2); ! 356: } ! 357: pb = ((daddr_t *)bpp)[n/NBN]; ! 358: candaddr(pb); ! 359: if (pb != 0) ! 360: bp = bread(1, pb); ! 361: else { ! 362: ((daddr_t *)bpp)[n/NBN] = pb = balloc(); ! 363: candaddr(((daddr_t *)bpp)[n/NBN]); ! 364: bwrite(bpp, pbb); ! 365: bp = bclaim(1); ! 366: } ! 367: ((daddr_t *)bp)[n%NBN] = b; ! 368: candaddr(((daddr_t *)bp)[n%NBN]); ! 369: bwrite(bp, pb); ! 370: return; ! 371: } ! 372: panic("bad block file too large"); ! 373: } ! 374: ! 375: /* ! 376: * Allocate a block from our filesystem. ! 377: */ ! 378: daddr_t ! 379: balloc() ! 380: { ! 381: register struct fblk *fbp; ! 382: register daddr_t b; ! 383: register int i; ! 384: ! 385: next: ! 386: if (supb.s_tfree==0 || (b=supb.s_free[--supb.s_nfree])==0) ! 387: panic("out of space on filesystem"); ! 388: if (supb.s_nfree == 0) { ! 389: fbp = (struct fblk *)bread(0, b); ! 390: supb.s_nfree = fbp->df_nfree; ! 391: canshort(supb.s_nfree); ! 392: for (i=0; i<sizeof(supb.s_free); i++) { ! 393: supb.s_free[i] = fbp->df_free[i]; ! 394: candaddr(supb.s_free[i]); ! 395: } ! 396: } ! 397: --supb.s_tfree; ! 398: if (b>=supb.s_fsize || b<supb.s_isize) ! 399: panic("bad block %u (alloc)", (unsigned)b); ! 400: for (i=0; i<badn; i++) ! 401: if (b == badl[i]) ! 402: goto next; ! 403: return (b); ! 404: } ! 405: ! 406: /* ! 407: * Given a buffer number, claim the buffer. ! 408: */ ! 409: char * ! 410: bclaim(l) ! 411: { ! 412: register char *bp; ! 413: register int n; ! 414: ! 415: n = BSIZE; ! 416: bp = bufl[l]; ! 417: do { ! 418: *bp++ = 0; ! 419: } while (--n); ! 420: return (bufl[l]); ! 421: } ! 422: ! 423: /* ! 424: * Given a buffer number, read the given block into the given buffer and ! 425: * return a pointer to the buffer. ! 426: */ ! 427: char * ! 428: bread(l, b) ! 429: daddr_t b; ! 430: { ! 431: register char *bp; ! 432: ! 433: bp = bufl[l]; ! 434: if (b != bnol[l]) { ! 435: lseek(filf, (long)b*BSIZE, 0); ! 436: if (read(filf, bp, BSIZE) != BSIZE) ! 437: panic("read error on block %ld", b); ! 438: bnol[l] = b; ! 439: } ! 440: return (bp); ! 441: } ! 442: ! 443: /* ! 444: * Given a pointer to a buffer, write it out as the given block. ! 445: */ ! 446: bwrite(bp, b) ! 447: char *bp; ! 448: daddr_t b; ! 449: { ! 450: ! 451: lseek(filf, (long)b*BSIZE, 0); ! 452: if (write(filf, bp, BSIZE) != BSIZE) ! 453: panic("write error on block %ld", b); ! 454: } ! 455: ! 456: /* ! 457: * Copy `n' bytes from `bp1' to `bp2'. ! 458: */ ! 459: strcopy(bp1, bp2, n) ! 460: register char *bp1; ! 461: register char *bp2; ! 462: register unsigned n; ! 463: { ! 464: if (n == 0) ! 465: return; ! 466: do { ! 467: *bp2++ = *bp1++; ! 468: } while (--n); ! 469: } ! 470: ! 471: /* ! 472: * Print out an error message and exit. ! 473: */ ! 474: /* VARARGS */ ! 475: panic(a1) ! 476: char *a1; ! 477: { ! 478: fprintf(stderr, "bad: %r\n", &a1); ! 479: exit(1); ! 480: } ! 481: ! 482: /* end of bad.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.