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