diff options
author | bde <bde@FreeBSD.org> | 1995-02-21 08:38:24 +0000 |
---|---|---|
committer | bde <bde@FreeBSD.org> | 1995-02-21 08:38:24 +0000 |
commit | 01efbfed9f8108d99314d7e4d28585ef4512d976 (patch) | |
tree | 39b3a5aff4fba56514e372d2e88da12dbcc5e271 /sys/kern/subr_diskslice.c | |
parent | e63a89f186fa5d1cf7e84783b10666fb3517eed0 (diff) | |
download | FreeBSD-src-01efbfed9f8108d99314d7e4d28585ef4512d976.zip FreeBSD-src-01efbfed9f8108d99314d7e4d28585ef4512d976.tar.gz |
Discard junk from partition tables when reading the tables for applications
the same as when initializing the in-core copies. Adjust checksums in
labels after adjusting labels. This finishes fudging the on-disk label to
make it coherent with the in-core label.
Handle EIO during initialization better.
Initialize the compatibility slice to the whole disk If there are no real
slices.
Don't warn about adjusting offsets in the label to make the 'c' partition
start at 0. The 'c' offset is now always absolute on-disk and 0 in-core
so an adjustment is usually required.
Don't confuse LABEL_PART with RAW_PART so much.
Check for partitions being within slices differently.
Diffstat (limited to 'sys/kern/subr_diskslice.c')
-rw-r--r-- | sys/kern/subr_diskslice.c | 114 |
1 files changed, 71 insertions, 43 deletions
diff --git a/sys/kern/subr_diskslice.c b/sys/kern/subr_diskslice.c index 50a7923..0914215 100644 --- a/sys/kern/subr_diskslice.c +++ b/sys/kern/subr_diskslice.c @@ -43,7 +43,7 @@ * 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: subr_diskslice.c,v 1.4 1995/02/16 15:19:00 bde Exp $ + * $Id: subr_diskslice.c,v 1.5 1995/02/18 22:10:44 bde Exp $ */ #include <sys/param.h> @@ -85,13 +85,38 @@ adjust_label(lp, offset) struct disklabel *lp; u_long offset; { + u_long end; int part; struct partition *pp; + u_long start; - pp = &lp->d_partitions[0]; - for (part = 0; part < lp->d_npartitions; part++, pp++) - if (pp->p_offset != 0 || pp->p_size != 0) - pp->p_offset += offset; + if (lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC + || dkcksum(lp) != 0) { + printf("adjust_label failed: bad magic or checksum\n"); + return; + } + pp = &lp->d_partitions[RAW_PART]; + start = pp->p_offset; + end = start + pp->p_size; + if (start > end || start + offset > end + offset) { + printf( + "adjust_label failed: invalid raw partition or offset\n"); + return; + } + pp -= RAW_PART; + for (part = 0; part < lp->d_npartitions; part++, pp++) { + if (pp->p_offset != 0 || pp->p_size != 0) { + /* XXX silently discard junk. */ + if (pp->p_offset < start + || pp->p_offset + pp->p_size > end + || pp->p_offset + pp->p_size < pp->p_offset) + bzero(pp, sizeof *pp); + else + pp->p_offset += offset; + } + } + lp->d_checksum = 0; + lp->d_checksum = dkcksum(lp); } /* @@ -460,25 +485,32 @@ dsopen(dname, dev, mode, sspp, lp, strat, setgeom) * XXX reinitialize the slice table unless there is an open device * on the unit. This should only be done if the media has changed. */ - need_init = !dsisopen(*sspp); - if (*sspp != NULL && need_init) + ssp = *sspp; + need_init = !dsisopen(ssp); + if (ssp != NULL && need_init) dsgone(sspp); if (need_init) { printf("dsinit\n"); error = dsinit(dname, dev, strat, lp, sspp); - if (error != 0) + if (error != 0) { + dsgone(sspp); return (error); + } lp->d_npartitions = RAW_PART + 1; lp->d_partitions[RAW_PART].p_size = lp->d_secperunit; + ssp = *sspp; + if (ssp->dss_nslices == BASE_SLICE) + ssp->dss_slices[COMPATIBILITY_SLICE].ds_size + = lp->d_secperunit; if (setgeom != NULL) { error = setgeom(lp); - if (error != 0) - /* XXX clean up? */ + if (error != 0) { + dsgone(sspp); return (error); + } } } - ssp = *sspp; slice = dkslice(dev); if (slice >= ssp->dss_nslices) return (ENXIO); @@ -564,60 +596,56 @@ fixlabel(dname, unit, slice, sp, lp) struct diskslice *sp; struct disklabel *lp; { - bool_t adjust; + u_long end; int part; struct partition *pp; + u_long start; bool_t warned; - pp = &lp->d_partitions[LABEL_PART]; - if (pp->p_offset != 0 && pp->p_offset != sp->ds_offset) { + pp = &lp->d_partitions[RAW_PART]; + if (pp->p_offset != sp->ds_offset) { printf( -"%s%ds%d: rejecting BSD label: label partition start != 0 and != slice start\n", +"%s%ds%d: rejecting BSD label: raw partition start != slice start\n", dname, unit, slice); slice_info(dname, unit, slice, sp); - partition_info(dname, unit, slice, LABEL_PART, pp); + partition_info(dname, unit, slice, RAW_PART, pp); return ("invalid partition table"); } if (pp->p_size != sp->ds_size) { - printf("%s%ds%d: label partition size != slice size\n", + printf("%s%ds%d: raw partition size != slice size\n", dname, unit, slice); slice_info(dname, unit, slice, sp); - partition_info(dname, unit, slice, LABEL_PART, pp); + partition_info(dname, unit, slice, RAW_PART, pp); if (pp->p_size > sp->ds_size) { - printf("%s%ds%d: truncating label partition\n", + printf("%s%ds%d: truncating raw partition\n", dname, unit, slice); pp->p_size = sp->ds_size; } } - adjust = FALSE; + start = sp->ds_offset; + end = start + sp->ds_size; + pp -= RAW_PART; 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 (part = 0; part < lp->d_npartitions; part++, 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( + if (pp->p_offset != 0 || pp->p_size != 0) { + if (pp->p_offset < start + || pp->p_offset + pp->p_size > end + || 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, part, pp); - bzero(pp, sizeof *pp); + dname, unit, slice); + if (!warned) { + slice_info(dname, unit, slice, sp); + warned = TRUE; + } + partition_info(dname, unit, slice, part, pp); + bzero(pp, sizeof *pp); + } else + pp->p_offset -= sp->ds_offset; } } + lp->d_checksum = 0; + lp->d_checksum = dkcksum(lp); /* XXX TODO: fix general params in *lp? */ |