From ed0da47a02390b289c84b8d8bdda2caa48d1bf6a Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 22 Apr 1998 19:27:54 +0000 Subject: Bad144 support for the slice system (!) Submitted by: luoqi@watermarkgroup.com (Luoqi Chen) I'm amazed by this. Slice has only been checked in for 2 days.. --- sys/dev/slice/disklabel.c | 129 ++++++++++++++++++++++++++++++++++++------- sys/dev/slice/mbr.c | 33 ++++++++++- sys/dev/slice/slice_device.c | 4 +- 3 files changed, 143 insertions(+), 23 deletions(-) (limited to 'sys/dev') diff --git a/sys/dev/slice/disklabel.c b/sys/dev/slice/disklabel.c index 513d11f..ff8c6f6 100644 --- a/sys/dev/slice/disklabel.c +++ b/sys/dev/slice/disklabel.c @@ -23,9 +23,9 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: disklabel.c,v 1.1 1998/04/19 23:31:03 julian Exp $ + * $Id: disklabel.c,v 1.2 1998/04/22 10:25:09 julian Exp $ */ - +#define BAD144 #include #include @@ -35,6 +35,9 @@ #include #include #include +#ifdef BAD144 +#include +#endif #include #include @@ -57,6 +60,9 @@ struct private_data { struct private_data *pd; u_int32_t offset; /* all disklabel supports */ } subdevs[MAXPARTITIONS]; +#ifdef BAD144 + struct dkbad_intern *bad; +#endif }; static sl_h_constructor_t dkl_constructor; /* constructor (from device) */ @@ -232,7 +238,78 @@ quit: return (error); } +#ifdef BAD144 +static int +dkl_internbad144(struct private_data *pd, struct dkbad *btp, int flag) +{ + struct disklabel *lp = &pd->disklabel; + struct dkbad_intern *bip = pd->bad; + int i; + + if (bip == NULL) { + bip = malloc(sizeof *bip, M_DEVBUF, flag); + if (bip == NULL) + return (ENOMEM); + pd->bad = bip; + } + /* + * 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; + for (i=0; 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; +#if 1 + for (i = 0; i < DKBAD_MAXBAD && bip->bi_bad[i] != -1; i++) + printf(" %8d => %8d\n", bip->bi_bad[i], + bip->bi_maxspare - i); +#endif + return (0); +} + +static int +dkl_readbad144(struct private_data *pd) +{ + sl_p slice = pd->slice_down; + struct disklabel *lp = &pd->disklabel; + struct dkbad *db; + struct buf *bp; + int blkno, i, error; + + for (i = 0; i < min(10, lp->d_nsectors); i += 2) { + blkno = lp->d_secperunit - lp->d_nsectors + i; + if (lp->d_secsize > slice->limits.blksize) + blkno *= lp->d_secsize / slice->limits.blksize; + else + blkno /= slice->limits.blksize / lp->d_secsize; + error = slice_readblock(slice, blkno, &bp); + if (error) + return (error); + bp->b_flags |= B_INVAL | B_AGE; + db = (struct dkbad *)bp->b_data; + if (db->bt_mbz == 0 && db->bt_flag == DKBAD_MAGIC) { + printf(" bad144 table found at block %d\n", blkno); + error = dkl_internbad144(pd, db, M_NOWAIT); + brelse(bp); + return (error); + } + brelse(bp); + } + return (EINVAL); +} +static __inline daddr_t +dkl_transbad144(struct private_data *pd, daddr_t blkno) +{ + return transbad144(pd->bad, blkno); +} +#endif /*- * look at a slice and figure out if we should be interested in it. (Is it @@ -357,6 +434,14 @@ dkl_constructor(sl_p slice) return (error); } } +#ifdef BAD144 + if (pd->disklabel.d_flags & D_BADSECT) { + if ((error = dkl_readbad144(pd))) { + free(pd, M_DEVBUF); + return (error); + } + } +#endif slice->refs++; slice->handler_up = &slicetype; slice->private_up = pd; @@ -560,6 +645,10 @@ dkl_revoke(void *private) slice->handler_up = NULL; slice->private_up = NULL; slicetype.refs--; +#ifdef BAD144 + if (pd->bad) + free(pd->bad, M_DEVBUF); +#endif free(pd, M_DEVBUF); sl_unref(slice); return (0); @@ -583,24 +672,6 @@ RR; sliceio(slice, bp, SLW_ABOVE); } -/* - * shift the appropriate IO by the offset for that slice. - */ -static void -mbr_IOreq(void *private, struct buf * bp) -{ - register struct private_data *pd; - struct subdev *sdp; - register struct slice *slice; - -RR; - sdp = private; - pd = sdp->pd; - slice = pd->slice_down; - bp->b_pblkno += sdp->offset; /* add the offset for that slice */ - sliceio(slice, bp, SLW_ABOVE); -} - static int dkl_open(void *private, int flags, int mode, struct proc * p) { @@ -730,6 +801,13 @@ dkl_ioctl(void *private, int cmd, caddr_t addr, int flag, struct proc * p) ((struct partinfo *)addr)->part = lp->d_partitions + sdp->part; return (0); +#ifdef BAD144 + case DIOCSBAD: + if (!(flag & FWRITE)) + return (EBADF); + return (dkl_internbad144(pd, (struct dkbad *)addr, M_WAITOK)); +#endif + /* These don't really make sense. keep the headers for a reminder */ case DIOCSDINFO: case DIOCSYNCSLICEINFO: @@ -750,6 +828,17 @@ dkl_upconfig(struct slice *slice, int cmd, caddr_t addr, int flag, struct proc * case SLCIOCRESET: return (0); + case SLCIOCTRANSBAD: + { + struct private_data *pd; + daddr_t blkno; + + pd = slice->private_up; + if (pd->bad) + *(daddr_t*)addr = dkl_transbad144(pd, *(daddr_t*)addr); + return (0); + } + /* These don't really make sense. keep the headers for a reminder */ default: return (ENOIOCTL); diff --git a/sys/dev/slice/mbr.c b/sys/dev/slice/mbr.c index 29e8b01..5558775 100644 --- a/sys/dev/slice/mbr.c +++ b/sys/dev/slice/mbr.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: mbr.c,v 1.1 1998/04/19 23:31:05 julian Exp $ + * $Id: mbr.c,v 1.2 1998/04/22 10:25:09 julian Exp $ */ #include @@ -825,11 +825,42 @@ static int mbr_upconfig(struct slice *slice, int cmd, caddr_t addr, int flag, struct proc * p) { + int error; + RR; switch (cmd) { case SLCIOCRESET: return (0); + case SLCIOCTRANSBAD: + { + struct private_data *pd; + struct subdev *sdp; + daddr_t blkno; + int part; + + blkno = *(daddr_t *)addr; + pd = slice->private_up; + sdp = pd->subdevs; + for (part = 0; part < NDOSPART; part++, sdp++) { + if (!sdp->slice) + continue; + if (blkno < sdp->offset) + continue; + if (blkno >= sdp->offset + + sdp->limit.slicesize / sdp->limit.blksize) + continue; + blkno -= sdp->offset; + slice = sdp->slice; + error = (*slice->handler_up->upconf)(slice, cmd, + (caddr_t)&blkno, flag, p); + if (!error) + *(daddr_t *)addr = blkno + sdp->offset; + return (error); + } + return (0); + } + /* These don't really make sense. keep the headers for a reminder */ default: return (ENOIOCTL); diff --git a/sys/dev/slice/slice_device.c b/sys/dev/slice/slice_device.c index 783a862..30bb309 100644 --- a/sys/dev/slice/slice_device.c +++ b/sys/dev/slice/slice_device.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: slice_device.c,v 1.1 1998/04/19 23:31:14 julian Exp $ + * $Id: slice_device.c,v 1.2 1998/04/22 10:25:10 julian Exp $ */ #define DIAGNOSTIC 1 @@ -227,7 +227,7 @@ slcdevclose(dev_t dev, int flags, int mode, struct proc * p) { sl_p slice = minor_to_slice(minor(dev)); RR; -#ifdef DIAGNOSTIC +#ifdef DIAGNOSTICX if ((flags & (FWRITE | FREAD)) != 0) { printf("sliceclose called with non 0 flags\n"); } -- cgit v1.1