summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_dkbad.c
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>1994-12-12 00:20:34 +0000
committerbde <bde@FreeBSD.org>1994-12-12 00:20:34 +0000
commitdd76f9af02622d9347c51336425ad4e6dce911fc (patch)
tree375982913ca3e2bd0f6e35559076e797fc9c0ef3 /sys/kern/subr_dkbad.c
parentfd51fdacb58a497e43b785003bd005be84c1e926 (diff)
downloadFreeBSD-src-dd76f9af02622d9347c51336425ad4e6dce911fc.zip
FreeBSD-src-dd76f9af02622d9347c51336425ad4e6dce911fc.tar.gz
subr_diskslice.c implements everything related to slices and labels except
reading and writing the slice tables and labels. subr_dkbad.c implements everything related to bad sector remapping using the bad144 format.
Diffstat (limited to 'sys/kern/subr_dkbad.c')
-rw-r--r--sys/kern/subr_dkbad.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/sys/kern/subr_dkbad.c b/sys/kern/subr_dkbad.c
new file mode 100644
index 0000000..e685abf
--- /dev/null
+++ b/sys/kern/subr_dkbad.c
@@ -0,0 +1,158 @@
+/*-
+ * Copyright (c) 1994 Bruce D. Evans.
+ * All rights reserved.
+ *
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)wd.c 7.2 (Berkeley) 5/9/91
+ * from: wd.c,v 1.55 1994/10/22 01:57:12 phk Exp $
+ * from: @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91
+ * from: ufs_disksubr.c,v 1.8 1994/06/07 01:21:39 phk Exp $
+ * $Id:
+ */
+
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/disklabel.h>
+#include <sys/dkbad.h>
+#include <sys/malloc.h>
+
+/*
+ * Internalize the bad sector table.
+ * TODO:
+ * o Fix types.
+ * Type long should be daddr_t since we compare with blkno's.
+ * Sentinel -1 should be ((daddr_t)-1).
+ * o Can remove explicit test for sentinel if it is a positive
+ * (unsigned or not) value larger than all possible blkno's.
+ * o Check that the table is sorted.
+ * o Use faster searches.
+ * o Use the internal table in wddump().
+ * o Don't duplicate so much code.
+ * o Do all bad block handing in a driver-independent file.
+ * o Remove limit of 126 spare sectors.
+ */
+struct dkbad_intern *
+internbad144(btp, lp)
+ struct dkbad *btp;
+ struct disklabel *lp;
+{
+ struct dkbad_intern *bip;
+ int i;
+
+ bip = malloc(sizeof *bip, M_DEVBUF, M_WAITOK);
+ /*
+ * Spare sectors are allocated beginning with the last sector of
+ * the second last track of the disk (the last track is used for
+ * the bad sector list).
+ */
+ bip->bi_maxspare = lp->d_secperunit - lp->d_nsectors - 1;
+ bip->bi_nbad = DKBAD_MAXBAD;
+ i = 0;
+ for (; i < DKBAD_MAXBAD && btp->bt_bad[i].bt_cyl != DKBAD_NOCYL; i++)
+ bip->bi_bad[i] = btp->bt_bad[i].bt_cyl * lp->d_secpercyl
+ + (btp->bt_bad[i].bt_trksec >> 8)
+ * lp->d_nsectors
+ + (btp->bt_bad[i].bt_trksec & 0x00ff);
+ bip->bi_bad[i] = -1;
+ return (bip);
+}
+
+char *
+readbad144(dev, strat, lp, bdp)
+ dev_t dev;
+ d_strategy_t *strat;
+ struct disklabel *lp;
+ struct dkbad *bdp;
+{
+ struct buf *bp;
+ struct dkbad *db;
+ int i;
+ char *msg;
+
+ bp = geteblk((int)lp->d_secsize);
+ i = 0;
+ do {
+ /* Read a bad sector table. */
+ bp->b_dev = dev;
+ bp->b_blkno = lp->d_secperunit - lp->d_nsectors + i;
+ if (lp->d_secsize > DEV_BSIZE)
+ bp->b_blkno *= lp->d_secsize / DEV_BSIZE;
+ else
+ bp->b_blkno /= DEV_BSIZE / lp->d_secsize;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ (*strat)(bp);
+
+ /* If successful, validate, otherwise try another. */
+ if (biowait(bp) == 0) {
+ db = (struct dkbad *)(bp->b_un.b_addr);
+ if (db->bt_mbz == 0 && db->bt_flag == DKBAD_MAGIC) {
+ msg = NULL;
+ *bdp = *db;
+ break;
+ }
+ msg = "bad sector table corrupted";
+ } else
+ msg = "bad sector table I/O error";
+ } while ((bp->b_flags & B_ERROR) && (i += 2) < 10 &&
+ i < lp->d_nsectors);
+ bp->b_flags = B_INVAL | B_AGE;
+ brelse(bp);
+ return (msg);
+}
+
+daddr_t
+transbad144(bip, blkno)
+ struct dkbad_intern *bip;
+ daddr_t blkno;
+{
+ int i;
+
+ /*
+ * List is sorted, so the search can terminate when it is past our
+ * sector.
+ */
+ for (i = 0; bip->bi_bad[i] != -1 && bip->bi_bad[i] <= blkno; i++)
+ if (bip->bi_bad[i] == blkno)
+ /*
+ * Spare sectors are allocated in decreasing order.
+ */
+ return (bip->bi_maxspare - i);
+ return (blkno);
+}
OpenPOWER on IntegriCloud