FreeBSD/Linux Kernel Cross Reference
sys/kern/subr_dkbad.c
1 /*-
2 * Copyright (c) 1994 Bruce D. Evans.
3 * All rights reserved.
4 *
5 * Copyright (c) 1990 The Regents of the University of California.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * William Jolitz.
10 *
11 * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
12 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by the University of
25 * California, Berkeley and its contributors.
26 * 4. Neither the name of the University nor the names of its contributors
27 * may be used to endorse or promote products derived from this software
28 * without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * SUCH DAMAGE.
41 *
42 * from: @(#)wd.c 7.2 (Berkeley) 5/9/91
43 * from: wd.c,v 1.55 1994/10/22 01:57:12 phk Exp $
44 * from: @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91
45 * from: ufs_disksubr.c,v 1.8 1994/06/07 01:21:39 phk Exp $
46 * $FreeBSD: src/sys/kern/subr_dkbad.c,v 1.4.2.2 1999/09/05 08:15:12 peter Exp $
47 */
48
49 #include <sys/param.h>
50 #include <sys/buf.h>
51 #include <sys/conf.h>
52 #include <sys/disklabel.h>
53 #include <sys/dkbad.h>
54 #include <sys/malloc.h>
55
56 /*
57 * Internalize the bad sector table.
58 * TODO:
59 * o Fix types.
60 * Type long should be daddr_t since we compare with blkno's.
61 * Sentinel -1 should be ((daddr_t)-1).
62 * o Can remove explicit test for sentinel if it is a positive
63 * (unsigned or not) value larger than all possible blkno's.
64 * o Check that the table is sorted.
65 * o Use faster searches.
66 * o Use the internal table in wddump().
67 * o Don't duplicate so much code.
68 * o Do all bad block handing in a driver-independent file.
69 * o Remove limit of 126 spare sectors.
70 */
71 struct dkbad_intern *
72 internbad144(btp, lp)
73 struct dkbad *btp;
74 struct disklabel *lp;
75 {
76 struct dkbad_intern *bip;
77 int i;
78
79 bip = malloc(sizeof *bip, M_DEVBUF, M_WAITOK);
80 /*
81 * Spare sectors are allocated beginning with the last sector of
82 * the second last track of the disk (the last track is used for
83 * the bad sector list).
84 */
85 bip->bi_maxspare = lp->d_secperunit - lp->d_nsectors - 1;
86 bip->bi_nbad = DKBAD_MAXBAD;
87 i = 0;
88 for (; i < DKBAD_MAXBAD && btp->bt_bad[i].bt_cyl != DKBAD_NOCYL; i++)
89 bip->bi_bad[i] = btp->bt_bad[i].bt_cyl * lp->d_secpercyl
90 + (btp->bt_bad[i].bt_trksec >> 8)
91 * lp->d_nsectors
92 + (btp->bt_bad[i].bt_trksec & 0x00ff);
93 bip->bi_bad[i] = -1;
94 return (bip);
95 }
96
97 char *
98 readbad144(dev, strat, lp, bdp)
99 dev_t dev;
100 d_strategy_t *strat;
101 struct disklabel *lp;
102 struct dkbad *bdp;
103 {
104 struct buf *bp;
105 struct dkbad *db;
106 int i;
107 char *msg;
108
109 bp = geteblk((int)lp->d_secsize);
110 i = 0;
111 do {
112 /* Read a bad sector table. */
113 bp->b_dev = dev;
114 bp->b_blkno = lp->d_secperunit - lp->d_nsectors + i;
115 if (lp->d_secsize > DEV_BSIZE)
116 bp->b_blkno *= lp->d_secsize / DEV_BSIZE;
117 else
118 bp->b_blkno /= DEV_BSIZE / lp->d_secsize;
119 bp->b_bcount = lp->d_secsize;
120 bp->b_flags |= B_BUSY | B_READ;
121 bp->b_flags &= ~B_ERROR;
122 (*strat)(bp);
123
124 /* If successful, validate, otherwise try another. */
125 if (biowait(bp) == 0) {
126 db = (struct dkbad *)(bp->b_un.b_addr);
127 if (db->bt_mbz == 0 && db->bt_flag == DKBAD_MAGIC) {
128 msg = NULL;
129 *bdp = *db;
130 break;
131 }
132 msg = "bad sector table corrupted";
133 } else
134 msg = "bad sector table I/O error";
135 } while ((bp->b_flags & B_ERROR) && (i += 2) < 10 &&
136 i < lp->d_nsectors);
137 bp->b_flags |= B_INVAL | B_AGE;
138 brelse(bp);
139 return (msg);
140 }
141
142 daddr_t
143 transbad144(bip, blkno)
144 struct dkbad_intern *bip;
145 daddr_t blkno;
146 {
147 int i;
148
149 /*
150 * List is sorted, so the search can terminate when it is past our
151 * sector.
152 */
153 for (i = 0; bip->bi_bad[i] != -1 && bip->bi_bad[i] <= blkno; i++)
154 if (bip->bi_bad[i] == blkno)
155 /*
156 * Spare sectors are allocated in decreasing order.
157 */
158 return (bip->bi_maxspare - i);
159 return (blkno);
160 }
Cache object: 2de2c9afafb1d3b6ee1563a0240ac0db
|