mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-13 10:02:38 +00:00
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.
This commit is contained in:
parent
e82f07e12e
commit
d1f35d579f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=5059
522
sys/kern/subr_diskslice.c
Normal file
522
sys/kern/subr_diskslice.c
Normal file
@ -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);
|
||||
}
|
158
sys/kern/subr_dkbad.c
Normal file
158
sys/kern/subr_dkbad.c
Normal file
@ -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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user