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