|
|
1.1 ! root 1: /*% cc -O -o rarepl % ! 2: * ! 3: * replace a bad sector on an RA disk ! 4: */ ! 5: ! 6: #include <stdio.h> ! 7: #include <sys/param.h> ! 8: #include <sys/udaioc.h> ! 9: #include "rct.h" ! 10: ! 11: struct ud_unit ud_unit; ! 12: int primblk; /* ugh */ ! 13: int notprim; /* never primary replacement */ ! 14: ! 15: #define BADRBN (-1L) ! 16: ! 17: main(argc, argv) ! 18: int argc; ! 19: char **argv; ! 20: { ! 21: int fd; ! 22: int errs = 0; ! 23: ! 24: if (argc < 3) { ! 25: fprintf(stderr, "usage: %s dev lbn ...\n", argv[0]); ! 26: exit(1); ! 27: } ! 28: if ((fd = open(argv[1], 2)) < 0) { ! 29: perror(argv[1]); ! 30: exit(1); ! 31: } ! 32: online(fd); ! 33: if (ioctl(fd, UIOCHAR, &ud_unit) < 0) { ! 34: perror("unit info"); ! 35: exit(1); ! 36: } ! 37: argc--; ! 38: argv++; ! 39: while (--argc > 0) ! 40: errs += repl(fd, atol(*++argv)); ! 41: exit(errs); ! 42: } ! 43: ! 44: /* ! 45: * read a block from the disk, ! 46: * just to make the driver bring it online ! 47: */ ! 48: ! 49: online(fd) ! 50: int fd; ! 51: { ! 52: char buf[RBNSEC]; ! 53: ! 54: read(fd, buf, RBNSEC); /* ignore error; might be bad sector */ ! 55: } ! 56: ! 57: /* ! 58: * replace a block ! 59: */ ! 60: ! 61: repl(fd, bad) ! 62: int fd; ! 63: daddr_t bad; ! 64: { ! 65: struct ud_repl r; ! 66: char block[RBNSEC]; ! 67: struct rbd rct[RBNPB]; ! 68: daddr_t rctb; ! 69: int rctoff; ! 70: daddr_t rbn; ! 71: daddr_t pickrbn(); ! 72: ! 73: if (bad >= ud_unit.radsize) { ! 74: fprintf(stderr, "%ld: out of range\n", bad); ! 75: return (1); ! 76: } ! 77: clrbuf(block); ! 78: lseek(fd, (off_t)(bad * RBNSEC), 0); ! 79: read(fd, block, RBNSEC); /* ignore error on purpose */ ! 80: if ((rbn = pickrbn(fd, bad)) == BADRBN) { ! 81: fprintf(stderr, "can't find replacement for %ld\n", bad); ! 82: return (1); ! 83: } ! 84: rctb = (rbn / RBNPB) + RCTTAB; ! 85: rctoff = rbn % RBNPB; ! 86: if (rdrct(fd, rctb, (char *)rct) == 0) ! 87: return (1); ! 88: if (rct[rctoff].rb_code) { ! 89: fprintf(stderr, "rbn %ld in use or bad\n", rbn); ! 90: return (1); ! 91: } ! 92: rct[rctoff].rb_code = primblk ? RALLOC : RALLOC | RALT; ! 93: rct[rctoff].rb_lbn = bad; ! 94: if (wrrct(fd, rctb, (char *)rct) == 0) ! 95: return (1); ! 96: r.lbn = bad; ! 97: r.replbn = rbn; ! 98: r.prim = primblk; ! 99: if (ioctl(fd, UIOREPL, &r) < 0) { ! 100: perror("replace ioctl"); ! 101: return (1); ! 102: } ! 103: lseek(fd, (off_t)(bad * RBNSEC), 0); ! 104: if (write(fd, block, RBNSEC) != RBNSEC) { ! 105: perror("write back"); ! 106: return (1); ! 107: } ! 108: return (0); ! 109: } ! 110: ! 111: /* ! 112: * find a replacement block ! 113: * remember in primblk whether it's the primary replacement ! 114: */ ! 115: ! 116: daddr_t ! 117: pickrbn(fd, lbn) ! 118: int fd; ! 119: daddr_t lbn; ! 120: { ! 121: struct rbd rct[RBNPB]; ! 122: daddr_t bno, rbn, prbn; ! 123: daddr_t low, high; ! 124: register int i; ! 125: daddr_t size; ! 126: daddr_t rctmax(), primrbn(); ! 127: ! 128: size = rctmax(); ! 129: prbn = primrbn(lbn); ! 130: low = high = BADRBN; ! 131: for (bno = RCTTAB, rbn = 0L; bno < size; bno++) { ! 132: if (rdrct(fd, bno, (char *)rct) == 0) { ! 133: rbn += RBNPB; ! 134: continue; ! 135: } ! 136: for (i = 0; i < RBNPB; i++, rbn++) { ! 137: if (rct[i].rb_code == RFREE) { ! 138: if (rbn < prbn) ! 139: low = rbn; ! 140: else if (high == BADRBN) ! 141: high = rbn; ! 142: } ! 143: else if (rct[i].rb_lbn == lbn ! 144: && rct[i].rb_code != RNULL ! 145: && rct[i].rb_code != RBAD) { ! 146: rct[i].rb_code = RBAD; ! 147: wrrct(fd, bno, (char *)rct); ! 148: } ! 149: } ! 150: } ! 151: if (low == BADRBN && high == BADRBN) ! 152: return (BADRBN); ! 153: else if (low == BADRBN) ! 154: rbn = high; ! 155: else if (high == BADRBN) ! 156: rbn = low; ! 157: else if (prbn - low < high - prbn) ! 158: rbn = low; ! 159: else ! 160: rbn = high; ! 161: if (notprim) ! 162: primblk = 0; ! 163: else ! 164: primblk = (rbn == prbn); ! 165: return (rbn); ! 166: } ! 167: ! 168: daddr_t ! 169: rctmax() ! 170: { ! 171: register daddr_t nrbns; ! 172: ! 173: nrbns = (ud_unit.radsize / ud_unit.tracksz) * ud_unit.rbns; ! 174: nrbns = ((nrbns+RBNPB-1) / RBNPB) + RCTTAB; ! 175: if (nrbns >= ud_unit.rctsize) { ! 176: notprim = 1; ! 177: return ((daddr_t)ud_unit.rctsize); ! 178: } ! 179: return (nrbns); ! 180: } ! 181: ! 182: /* ! 183: * figure out the primary RBN ! 184: * if notprim == 0, we understand what to do ! 185: * otherwise it's not really the primary RBN (and we won't tell the ! 186: * controller so), but make a guess about a preferred RBN anyway ! 187: */ ! 188: daddr_t ! 189: primrbn(lbn) ! 190: daddr_t lbn; ! 191: { ! 192: daddr_t q, csize; ! 193: ! 194: if (notprim == 0) ! 195: return ((lbn/ud_unit.tracksz) * ud_unit.rbns); ! 196: /* ! 197: * try for one in the same cylinder, ! 198: * or multiple thereof ! 199: */ ! 200: q = (ud_unit.rctsize - RCTTAB)*RBNPB; /* max possible rbns */ ! 201: q /= ud_unit.rbns; /* max rbn quantum */ ! 202: q = ud_unit.radsize/q; /* max LBNs per RBN */ ! 203: csize = ud_unit.tracksz*ud_unit.groupsz*ud_unit.cylsz; ! 204: q = (q + csize - 1)/csize; /* cylinders per RBN */ ! 205: q *= csize; /* probably real LBNs per RBN */ ! 206: return ((lbn + csize - 1)/q); ! 207: } ! 208: ! 209: rdrct(fd, bno, buf) ! 210: int fd; ! 211: daddr_t bno; ! 212: char *buf; ! 213: { ! 214: struct ud_rctbuf b; ! 215: ! 216: b.buf = buf; ! 217: b.lbn = bno; ! 218: if (ioctl(fd, UIORRCT, &b) < 0) { ! 219: perror("rrct"); ! 220: fprintf(stderr, "can't read block %ld of rct\n", bno); ! 221: return (0); ! 222: } ! 223: return (1); ! 224: } ! 225: ! 226: wrrct(fd, bno, buf) ! 227: int fd; ! 228: daddr_t bno; ! 229: char *buf; ! 230: { ! 231: struct ud_rctbuf b; ! 232: ! 233: b.buf = buf; ! 234: b.lbn = bno; ! 235: if (ioctl(fd, UIOWRCT, &b) < 0) { ! 236: perror("wrct"); ! 237: fprintf(stderr, "can't write block %ld of rct\n", bno); ! 238: return (0); ! 239: } ! 240: return (1); ! 241: } ! 242: ! 243: clrbuf(b) ! 244: register char *b; ! 245: { ! 246: register int i; ! 247: ! 248: for (i = 0; i < RBNSEC; i++) ! 249: *b++ = 0; ! 250: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.