summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/subr_diskslice.c522
-rw-r--r--sys/kern/subr_dkbad.c158
2 files changed, 680 insertions, 0 deletions
diff --git a/sys/kern/subr_diskslice.c b/sys/kern/subr_diskslice.c
new file mode 100644
index 0000000..8827716
--- /dev/null
+++ b/sys/kern/subr_diskslice.c
@@ -0,0 +1,522 @@
+/*-
+ * 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/diskslice.h>
+#include <sys/dkbad.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/malloc.h>
+#include <sys/stat.h>
+#include <sys/syslog.h>
+#include <sys/systm.h>
+
+#define b_cylinder b_resid
+
+#define FALSE 0
+#define TRUE 1
+typedef u_char bool_t;
+
+static char *fixlabel __P((char *dname, int unit, int slice,
+ struct diskslice *sp, struct disklabel *lp));
+static void partition_info __P((char *dname, int unit, int slice,
+ int part, struct partition *pp));
+static void slice_info __P((char *dname, int unit, int slice,
+ struct diskslice *sp));
+
+/*
+ * Determine the size of the transfer, and make sure it is
+ * within the boundaries of the partition. Adjust transfer
+ * if needed, and signal errors or early completion.
+ *
+ * XXX TODO:
+ * o Do bad sector remapping. May need to split buffer.
+ * o Split buffers that are too big for the device.
+ * o Check for overflow.
+ * o Finish cleaning this up.
+ */
+int
+dscheck(bp, ssp)
+ struct buf *bp;
+ struct diskslices *ssp;
+{
+ daddr_t blkno;
+ daddr_t labelsect;
+ struct disklabel *lp;
+ u_long maxsz;
+ struct partition *pp;
+ struct diskslice *sp;
+ long sz;
+
+ sp = &ssp->dss_slices[dkslice(bp->b_dev)];
+ lp = sp->ds_label;
+ sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
+ if (lp == NULL) {
+ blkno = bp->b_blkno;
+ labelsect = -LABELSECTOR - 1;
+ maxsz = sp->ds_size;
+ } else {
+ labelsect = lp->d_partitions[LABEL_PART].p_offset;
+if (labelsect != 0) Debugger("");
+ pp = &lp->d_partitions[dkpart(bp->b_dev)];
+ blkno = pp->p_offset + bp->b_blkno;
+ maxsz = pp->p_size;
+ if (sp->ds_bad != NULL) {
+ daddr_t newblkno;
+
+ newblkno = transbad144(sp->ds_bad, blkno);
+ if (newblkno != blkno)
+ printf("bad block %lu -> %lu\n",
+ blkno, newblkno);
+ }
+ }
+
+ /* overwriting disk label ? */
+ /* XXX should also protect bootstrap in first 8K */
+ if (blkno <= LABELSECTOR + labelsect &&
+#if LABELSECTOR != 0
+ bp->b_blkno + sz > LABELSECTOR + labelsect &&
+#endif
+ (bp->b_flags & B_READ) == 0 && sp->ds_wlabel == 0) {
+ bp->b_error = EROFS;
+ goto bad;
+ }
+
+#if defined(DOSBBSECTOR) && defined(notyet)
+ /* overwriting master boot record? */
+ if (blkno <= DOSBBSECTOR && (bp->b_flags & B_READ) == 0 &&
+ sp->ds_wlabel == 0) {
+ bp->b_error = EROFS;
+ goto bad;
+ }
+#endif
+
+ /* beyond partition? */
+ if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
+ /* if exactly at end of disk, return an EOF */
+ if (bp->b_blkno == maxsz) {
+ bp->b_resid = bp->b_bcount;
+ return (0);
+ }
+ /* or truncate if part of it fits */
+ sz = maxsz - bp->b_blkno;
+ if (sz <= 0) {
+ bp->b_error = EINVAL;
+ goto bad;
+ }
+ bp->b_bcount = sz << DEV_BSHIFT;
+ }
+
+ /* calculate cylinder for disksort to order transfers with */
+ bp->b_pblkno = blkno + sp->ds_offset;
+
+ if (lp == NULL)
+ bp->b_cylinder = 0; /* XXX all 0 would be better */
+ else
+ bp->b_cylinder = bp->b_pblkno / lp->d_secpercyl;
+ return (1);
+
+bad:
+ bp->b_flags |= B_ERROR;
+ return (-1);
+}
+
+void
+dsclose(dev, mode, ssp)
+ dev_t dev;
+ int mode;
+ struct diskslices *ssp;
+{
+ u_char mask;
+ struct diskslice *sp;
+
+ sp = &ssp->dss_slices[dkslice(dev)];
+ mask = 1 << dkpart(dev);
+ switch (mode) {
+ case S_IFBLK:
+ sp->ds_bopenmask &= ~mask;
+ break;
+ case S_IFCHR:
+ sp->ds_copenmask &= ~mask;
+ break;
+ }
+ sp->ds_openmask = sp->ds_bopenmask | sp->ds_copenmask;
+}
+
+/*
+ * For the "write" commands (DIOCSBAD, DIOCSDINFO and DIOCWDINFO), this
+ * is subject to the same restriction as dsopen().
+ */
+int
+dsioctl(dev, cmd, data, flags, ssp, strat, setgeom)
+ dev_t dev;
+ int cmd;
+ caddr_t data;
+ int flags;
+ struct diskslices *ssp;
+ d_strategy_t *strat;
+ ds_setgeom_t *setgeom;
+{
+ int error;
+ struct disklabel *lp;
+ int old_wlabel;
+ struct diskslice *sp;
+
+ sp = &ssp->dss_slices[dkslice(dev)];
+ lp = sp->ds_label;
+ switch (cmd) {
+
+ case DIOCGDINFO:
+ if (lp == NULL)
+ return (EINVAL);
+ *(struct disklabel *)data = *lp;
+ return (0);
+
+#ifdef notyet
+ case DIOCGDINFOP:
+ if (lp == NULL)
+ return (EINVAL);
+ *(struct disklabel **)data = lp;
+ return (0);
+#endif
+
+ case DIOCGPART:
+ if (lp == NULL)
+ return (EINVAL);
+ ((struct partinfo *)data)->disklab = lp;
+ ((struct partinfo *)data)->part
+ = &lp->d_partitions[dkpart(dev)];
+ return (0);
+
+ case DIOCSBAD:
+ if (!(flags & FWRITE))
+ return (EBADF);
+ if (lp == NULL)
+ return (EINVAL);
+ if (sp->ds_bad != NULL)
+ free(sp->ds_bad, M_DEVBUF);
+ sp->ds_bad = internbad144((struct dkbad *)data, lp);
+ return (0);
+
+ case DIOCSDINFO:
+ if (!(flags & FWRITE))
+ return (EBADF);
+ lp = malloc(sizeof *lp, M_DEVBUF, M_WAITOK);
+ error = setdisklabel(lp, (struct disklabel *)data,
+ sp->ds_label != NULL
+ ? sp->ds_openmask : (u_long)0);
+#if 0 /* XXX */
+ if (error != 0 && setgeom != NULL)
+ error = setgeom(lp);
+#endif
+ if (error != 0) {
+ free(lp, M_DEVBUF);
+ return (error);
+ }
+ if (sp->ds_label != NULL)
+ free(sp->ds_label, M_DEVBUF);
+ sp->ds_label = lp;
+ return (0);
+
+ case DIOCWDINFO:
+ error = dsioctl(dev, DIOCSDINFO, data, flags, ssp, strat,
+ setgeom);
+ if (error != 0)
+ return (error);
+ /*
+ * XXX this used to hack on dk_openpart to fake opening
+ * partition 0 in case that is used instead of dkpart(dev).
+ */
+ old_wlabel = sp->ds_wlabel;
+ sp->ds_wlabel = TRUE;
+ error = writedisklabel(dev, strat, sp->ds_label);
+ sp->ds_wlabel = old_wlabel;
+ return (error);
+
+ case DIOCWLABEL:
+ if (!(flags & FWRITE))
+ return (EBADF);
+ sp->ds_wlabel = (*(int *)data != 0);
+ return (0);
+
+ default:
+ return (-1);
+ }
+}
+
+/*
+ * This should only be called when the unit is inactive and the strategy
+ * routine should not allow it to become active unless we call it. Our
+ * strategy routine must be special to allow activity.
+ */
+int
+dsopen(dname, dev, mode, sspp, lp, strat, setgeom)
+ char *dname;
+ dev_t dev;
+ int mode;
+ struct diskslices **sspp;
+ struct disklabel *lp;
+ d_strategy_t *strat;
+ ds_setgeom_t *setgeom;
+{
+ int error;
+ char *msg;
+ u_char mask;
+ bool_t need_init;
+ int part;
+ int slice;
+ struct diskslice *sp;
+ struct diskslices *ssp;
+ int unit;
+
+ need_init = TRUE;
+ if (*sspp != NULL) {
+ /*
+ * XXX reinitialize the slice table unless there is an open
+ * device on the unit. This should only be done if the media
+ * has changed.
+ */
+ for (slice = 0, ssp = *sspp; slice < ssp->dss_nslices; slice++)
+ if (ssp->dss_slices[slice].ds_openmask) {
+ need_init = FALSE;
+ break;
+ }
+ if (need_init)
+ for (slice = 0, ssp = *sspp; slice < ssp->dss_nslices;
+ slice++) {
+ sp = &ssp->dss_slices[slice];
+ if (sp->ds_bad != NULL) {
+ free(sp->ds_bad, M_DEVBUF);
+ sp->ds_bad = NULL;
+ }
+ if (sp->ds_label != NULL) {
+ free(sp->ds_label, M_DEVBUF);
+ sp->ds_label = NULL;
+ }
+ }
+ }
+ if (need_init) {
+ printf("dsinit\n");
+ error = dsinit(dname, dev, strat, lp, sspp);
+ if (error != 0)
+ return (error);
+ if (setgeom != NULL) {
+ error = setgeom(lp);
+ if (error != 0)
+ /* XXX clean up? */
+ return (error);
+ }
+ }
+ ssp = *sspp;
+ slice = dkslice(dev);
+ if (slice >= ssp->dss_nslices)
+ return (ENXIO);
+ sp = &ssp->dss_slices[slice];
+ part = dkpart(dev);
+ unit = dkunit(dev);
+ if (/* slice != WHOLE_DISK_SLICE && */ sp->ds_label == NULL) {
+ struct disklabel *lp1;
+
+ lp1 = malloc(sizeof *lp1, M_DEVBUF, M_WAITOK);
+ *lp1 = *lp;
+ lp = lp1;
+ printf("readdisklabel\n");
+ msg = correct_readdisklabel(dkmodpart(dev, RAW_PART), strat, lp);
+#if 0 /* XXX */
+ if (msg == NULL && setgeom != NULL && setgeom(lp) != 0)
+ msg = "setgeom failed";
+#endif
+ if (msg == NULL)
+ msg = fixlabel(dname, unit, slice, sp, lp);
+ if (msg != NULL) {
+ free(lp, M_DEVBUF);
+ log(LOG_WARNING, "%s%ds%d: cannot find label (%s)\n",
+ dname, unit, slice, msg);
+ if (part == RAW_PART)
+ goto out;
+ return (EINVAL); /* XXX needs translation */
+ }
+ if (lp->d_flags & D_BADSECT) {
+ struct dkbad *btp;
+
+ btp = malloc(sizeof *btp, M_DEVBUF, M_WAITOK);
+ printf("readbad144\n");
+ msg = readbad144(dev, strat, lp, btp);
+ if (msg != NULL) {
+ log(LOG_WARNING,
+ "%s%ds%d: cannot find bad sector table (%s)\n",
+ dname, unit, slice, msg);
+ free(btp, M_DEVBUF);
+ free(lp, M_DEVBUF);
+ if (part == RAW_PART)
+ goto out;
+ return (EINVAL); /* XXX needs translation */
+ }
+ sp->ds_bad = internbad144(btp, lp);
+ free(btp, M_DEVBUF);
+ if (sp->ds_bad == NULL) {
+ free(lp, M_DEVBUF);
+ if (part == RAW_PART)
+ goto out;
+ return (EINVAL); /* XXX needs translation */
+ }
+ }
+ sp->ds_label = lp;
+ sp->ds_wlabel = TRUE;
+ }
+ if (part != RAW_PART
+ && (sp->ds_label == NULL || part >= sp->ds_label->d_npartitions))
+ return (EINVAL); /* XXX needs translation */
+out:
+ mask = 1 << part;
+ switch (mode) {
+ case S_IFBLK:
+ sp->ds_bopenmask |= mask;
+ break;
+ case S_IFCHR:
+ sp->ds_copenmask |= mask;
+ break;
+ }
+ sp->ds_openmask = sp->ds_bopenmask | sp->ds_copenmask;
+ return (0);
+}
+
+static char *
+fixlabel(dname, unit, slice, sp, lp)
+ char *dname;
+ int unit;
+ int slice;
+ struct diskslice *sp;
+ struct disklabel *lp;
+{
+ bool_t adjust;
+ int bsdpart;
+ struct partition *pp;
+ bool_t warned;
+
+ pp = &lp->d_partitions[LABEL_PART];
+ if (pp->p_offset != 0 && pp->p_offset != sp->ds_offset) {
+ printf(
+"%s%ds%d: rejecting BSD label: label partition start != 0 and != slice start\n",
+ dname, unit, slice);
+ slice_info(dname, unit, slice, sp);
+ partition_info(dname, unit, slice, LABEL_PART, pp);
+ return ("invalid partition table");
+ }
+ if (pp->p_size != sp->ds_size) {
+ printf("%s%ds%d: label partition size != slice size\n",
+ dname, unit, slice);
+ slice_info(dname, unit, slice, sp);
+ partition_info(dname, unit, slice, LABEL_PART, pp);
+ if (pp->p_size > sp->ds_size) {
+ printf("%s%ds%d: truncating label partition\n",
+ dname, unit, slice);
+ pp->p_size = sp->ds_size;
+ }
+ }
+ adjust = FALSE;
+ warned = FALSE;
+ if (pp->p_offset != 0) {
+ printf("%s%ds%d: adjusting offsets in BSD label\n",
+ dname, unit, slice);
+ slice_info(dname, unit, slice, sp);
+ partition_info(dname, unit, slice, LABEL_PART, pp);
+ adjust = TRUE;
+ warned = TRUE;
+ }
+ pp -= LABEL_PART;
+ for (bsdpart = 0; bsdpart < lp->d_npartitions; bsdpart++, pp++) {
+ if (adjust && (pp->p_offset != 0 || pp->p_size != 0))
+ pp->p_offset -= sp->ds_offset;
+ if (pp->p_offset + pp->p_size > sp->ds_size
+ || pp->p_offset + pp->p_size < pp->p_offset) {
+ printf(
+"%s%ds%d: rejecting partition in BSD label: it isn't entirely within the slice\n",
+ dname, unit, slice);
+ if (!warned) {
+ slice_info(dname, unit, slice, sp);
+ warned = TRUE;
+ }
+ if (adjust)
+ pp->p_offset += sp->ds_offset;
+ partition_info(dname, unit, slice, bsdpart, pp);
+ bzero(pp, sizeof *pp);
+ }
+ }
+
+ /* XXX TODO: fix general params in *lp? */
+
+ return (NULL);
+}
+
+static void
+partition_info(dname, unit, slice, part, pp)
+ char *dname;
+ int unit;
+ int slice;
+ int part;
+ struct partition *pp;
+{
+ printf("%s%ds%d%c: start %lu, end %lu, size %lu\n",
+ dname, unit, slice, 'a' + part,
+ pp->p_offset, pp->p_offset + pp->p_size - 1, pp->p_size);
+}
+
+static void
+slice_info(dname, unit, slice, sp)
+ char *dname;
+ int unit;
+ int slice;
+ struct diskslice *sp;
+{
+ printf("%s%ds%d: start %lu, end %lu, size %lu\n",
+ dname, unit, slice,
+ sp->ds_offset, sp->ds_offset + sp->ds_size - 1, sp->ds_size);
+}
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