diff options
-rw-r--r-- | sys/i386/isa/diskslice_machdep.c | 84 | ||||
-rw-r--r-- | sys/kern/subr_diskmbr.c | 84 | ||||
-rw-r--r-- | sys/kern/subr_diskslice.c | 134 |
3 files changed, 212 insertions, 90 deletions
diff --git a/sys/i386/isa/diskslice_machdep.c b/sys/i386/isa/diskslice_machdep.c index 2d43fb3..3c35445 100644 --- a/sys/i386/isa/diskslice_machdep.c +++ b/sys/i386/isa/diskslice_machdep.c @@ -35,7 +35,7 @@ * * 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$ + * $Id: diskslice_machdep.c,v 1.3 1995/01/23 02:31:53 phk Exp $ */ #include <stddef.h> @@ -59,6 +59,7 @@ dsinit(dname, dev, strat, lp, sspp) struct dos_partition *dp; struct dos_partition *dp0; int error; + int max_ncyls; int max_nsectors; int max_ntracks; u_long secpercyl; @@ -67,22 +68,19 @@ dsinit(dname, dev, strat, lp, sspp) struct diskslices *ssp; /* - * Free old slices "struct", if any, and allocate a dummy new one. + * Allocate a dummy slices "struct" and initialize it to contain + * only an empty compatibility slice (pointing to itself) and a + * whole disk slice (which may be a dummy if the label is a dummy). + * If there is an error, then these slices become the only slices. */ - if (*sspp != NULL) - free(*sspp, M_DEVBUF); - ssp = malloc(offsetof(struct diskslices, dss_slices) + sizeof(*sp), - M_DEVBUF, M_WAITOK); + ssp = malloc(offsetof(struct diskslices, dss_slices) + + BASE_SLICE * sizeof *sp, M_DEVBUF, M_WAITOK); *sspp = ssp; - - /* - * Initialize dummy slice. If there is an error, this becomes the - * only slice, and no more restrictive than the (dummy) label. - */ + ssp->dss_first_bsd_slice = COMPATIBILITY_SLICE; + ssp->dss_nslices = BASE_SLICE; sp = &ssp->dss_slices[0]; - bzero(sp, sizeof *sp); - sp->ds_size = lp->d_secperunit; - ssp->dss_nslices = 1; + bzero(sp, BASE_SLICE * sizeof *sp); + sp[WHOLE_DISK_SLICE].ds_size = lp->d_secperunit; /* Read master boot record. */ bp = geteblk((int)lp->d_secsize); @@ -109,6 +107,7 @@ dsinit(dname, dev, strat, lp, sspp) * Perhaps skip entries with 0 size. * Perhaps only look at entries of type DOSPTYP_386BSD. */ + max_ncyls = 0; max_nsectors = 0; max_ntracks = 0; dp0 = (struct dos_partition *)(cp + DOSPARTOFF); @@ -116,6 +115,9 @@ dsinit(dname, dev, strat, lp, sspp) int nsectors; int ntracks; + max_ncyls = DPCYL(dp->dp_ecyl, dp->dp_esect); + if (max_ncyls < max_ncyls) + max_ncyls = max_ncyls; nsectors = DPSECT(dp->dp_esect); if (max_nsectors < nsectors) max_nsectors = nsectors; @@ -129,7 +131,7 @@ dsinit(dname, dev, strat, lp, sspp) * TODO: * As above. * Check for overlaps. - * Check or adjust against d_ncylinders and d_secperunit. + * Check against d_secperunit if the latter is reliable. */ error = 0; secpercyl = max_nsectors * max_ntracks; @@ -169,39 +171,61 @@ dsinit(dname, dev, strat, lp, sspp) /* * We're not handling extended partitions yet, so there are always - * 1 + NDOSPART slices. + * BASE_SLICE + NDOSPART slices. */ - if (dkslice(dev) >= 1 + NDOSPART) { + if (dkslice(dev) >= BASE_SLICE + NDOSPART) { error = ENXIO; goto done; } /* * Accept the DOS partition table. - * Free dummy slices "struct" and allocate a real new one. + * First adjust the label (we have been careful not to change it + * before we can guarantee success). + */ + if (secpercyl != 0) { + u_long secperunit; + + lp->d_nsectors = max_nsectors; + lp->d_ntracks = max_ntracks; + lp->d_secpercyl = secpercyl; + secperunit = secpercyl * max_ncyls; + if (lp->d_secperunit < secperunit) + lp->d_secperunit = secperunit; + } + + /* + * Free the dummy slices "struct" and allocate a real new one. + * Initialize special slices as above. */ free(ssp, M_DEVBUF); ssp = malloc(offsetof(struct diskslices, dss_slices) - + (1 + NDOSPART) * sizeof(*sp), M_DEVBUF, M_WAITOK); + + (BASE_SLICE + NDOSPART) * sizeof *sp, + M_DEVBUF, M_WAITOK); *sspp = ssp; + ssp->dss_first_bsd_slice = COMPATIBILITY_SLICE; + ssp->dss_nslices = BASE_SLICE + NDOSPART; sp = &ssp->dss_slices[0]; - bzero(sp, (1 + NDOSPART) * sizeof *sp); - sp->ds_size = lp->d_secperunit; - sp++; + bzero(sp, (BASE_SLICE + NDOSPART) * sizeof *sp); + sp[WHOLE_DISK_SLICE].ds_size = lp->d_secperunit; + + /* Initialize normal slices. */ + sp += BASE_SLICE; for (dp = dp0, slice = 1; slice <= NDOSPART; dp++, slice++, sp++) { + if (dp->dp_typ == DOSPTYP_386BSD + && ssp->dss_first_bsd_slice == COMPATIBILITY_SLICE) { + ssp->dss_first_bsd_slice = BASE_SLICE + slice - 1; + ssp->dss_slices[COMPATIBILITY_SLICE].ds_offset + = dp->dp_start; + ssp->dss_slices[COMPATIBILITY_SLICE].ds_size + = dp->dp_size; + } sp->ds_offset = dp->dp_start; sp->ds_size = dp->dp_size; - } - ssp->dss_nslices = 1 + NDOSPART; - if (max_nsectors != 0) { - lp->d_nsectors = max_nsectors; - lp->d_ntracks = max_ntracks; - lp->d_secpercyl = secpercyl; - } #if 0 - lp->d_secperunit = what?; lp->d_subtype |= (lp->d_subtype & 3) + (slice - 1) | DSTYPE_INDOSPART; #endif + } done: bp->b_flags = B_INVAL | B_AGE; diff --git a/sys/kern/subr_diskmbr.c b/sys/kern/subr_diskmbr.c index 2d43fb3..3c35445 100644 --- a/sys/kern/subr_diskmbr.c +++ b/sys/kern/subr_diskmbr.c @@ -35,7 +35,7 @@ * * 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$ + * $Id: diskslice_machdep.c,v 1.3 1995/01/23 02:31:53 phk Exp $ */ #include <stddef.h> @@ -59,6 +59,7 @@ dsinit(dname, dev, strat, lp, sspp) struct dos_partition *dp; struct dos_partition *dp0; int error; + int max_ncyls; int max_nsectors; int max_ntracks; u_long secpercyl; @@ -67,22 +68,19 @@ dsinit(dname, dev, strat, lp, sspp) struct diskslices *ssp; /* - * Free old slices "struct", if any, and allocate a dummy new one. + * Allocate a dummy slices "struct" and initialize it to contain + * only an empty compatibility slice (pointing to itself) and a + * whole disk slice (which may be a dummy if the label is a dummy). + * If there is an error, then these slices become the only slices. */ - if (*sspp != NULL) - free(*sspp, M_DEVBUF); - ssp = malloc(offsetof(struct diskslices, dss_slices) + sizeof(*sp), - M_DEVBUF, M_WAITOK); + ssp = malloc(offsetof(struct diskslices, dss_slices) + + BASE_SLICE * sizeof *sp, M_DEVBUF, M_WAITOK); *sspp = ssp; - - /* - * Initialize dummy slice. If there is an error, this becomes the - * only slice, and no more restrictive than the (dummy) label. - */ + ssp->dss_first_bsd_slice = COMPATIBILITY_SLICE; + ssp->dss_nslices = BASE_SLICE; sp = &ssp->dss_slices[0]; - bzero(sp, sizeof *sp); - sp->ds_size = lp->d_secperunit; - ssp->dss_nslices = 1; + bzero(sp, BASE_SLICE * sizeof *sp); + sp[WHOLE_DISK_SLICE].ds_size = lp->d_secperunit; /* Read master boot record. */ bp = geteblk((int)lp->d_secsize); @@ -109,6 +107,7 @@ dsinit(dname, dev, strat, lp, sspp) * Perhaps skip entries with 0 size. * Perhaps only look at entries of type DOSPTYP_386BSD. */ + max_ncyls = 0; max_nsectors = 0; max_ntracks = 0; dp0 = (struct dos_partition *)(cp + DOSPARTOFF); @@ -116,6 +115,9 @@ dsinit(dname, dev, strat, lp, sspp) int nsectors; int ntracks; + max_ncyls = DPCYL(dp->dp_ecyl, dp->dp_esect); + if (max_ncyls < max_ncyls) + max_ncyls = max_ncyls; nsectors = DPSECT(dp->dp_esect); if (max_nsectors < nsectors) max_nsectors = nsectors; @@ -129,7 +131,7 @@ dsinit(dname, dev, strat, lp, sspp) * TODO: * As above. * Check for overlaps. - * Check or adjust against d_ncylinders and d_secperunit. + * Check against d_secperunit if the latter is reliable. */ error = 0; secpercyl = max_nsectors * max_ntracks; @@ -169,39 +171,61 @@ dsinit(dname, dev, strat, lp, sspp) /* * We're not handling extended partitions yet, so there are always - * 1 + NDOSPART slices. + * BASE_SLICE + NDOSPART slices. */ - if (dkslice(dev) >= 1 + NDOSPART) { + if (dkslice(dev) >= BASE_SLICE + NDOSPART) { error = ENXIO; goto done; } /* * Accept the DOS partition table. - * Free dummy slices "struct" and allocate a real new one. + * First adjust the label (we have been careful not to change it + * before we can guarantee success). + */ + if (secpercyl != 0) { + u_long secperunit; + + lp->d_nsectors = max_nsectors; + lp->d_ntracks = max_ntracks; + lp->d_secpercyl = secpercyl; + secperunit = secpercyl * max_ncyls; + if (lp->d_secperunit < secperunit) + lp->d_secperunit = secperunit; + } + + /* + * Free the dummy slices "struct" and allocate a real new one. + * Initialize special slices as above. */ free(ssp, M_DEVBUF); ssp = malloc(offsetof(struct diskslices, dss_slices) - + (1 + NDOSPART) * sizeof(*sp), M_DEVBUF, M_WAITOK); + + (BASE_SLICE + NDOSPART) * sizeof *sp, + M_DEVBUF, M_WAITOK); *sspp = ssp; + ssp->dss_first_bsd_slice = COMPATIBILITY_SLICE; + ssp->dss_nslices = BASE_SLICE + NDOSPART; sp = &ssp->dss_slices[0]; - bzero(sp, (1 + NDOSPART) * sizeof *sp); - sp->ds_size = lp->d_secperunit; - sp++; + bzero(sp, (BASE_SLICE + NDOSPART) * sizeof *sp); + sp[WHOLE_DISK_SLICE].ds_size = lp->d_secperunit; + + /* Initialize normal slices. */ + sp += BASE_SLICE; for (dp = dp0, slice = 1; slice <= NDOSPART; dp++, slice++, sp++) { + if (dp->dp_typ == DOSPTYP_386BSD + && ssp->dss_first_bsd_slice == COMPATIBILITY_SLICE) { + ssp->dss_first_bsd_slice = BASE_SLICE + slice - 1; + ssp->dss_slices[COMPATIBILITY_SLICE].ds_offset + = dp->dp_start; + ssp->dss_slices[COMPATIBILITY_SLICE].ds_size + = dp->dp_size; + } sp->ds_offset = dp->dp_start; sp->ds_size = dp->dp_size; - } - ssp->dss_nslices = 1 + NDOSPART; - if (max_nsectors != 0) { - lp->d_nsectors = max_nsectors; - lp->d_ntracks = max_ntracks; - lp->d_secpercyl = secpercyl; - } #if 0 - lp->d_secperunit = what?; lp->d_subtype |= (lp->d_subtype & 3) + (slice - 1) | DSTYPE_INDOSPART; #endif + } done: bp->b_flags = B_INVAL | B_AGE; diff --git a/sys/kern/subr_diskslice.c b/sys/kern/subr_diskslice.c index 7191ff7..7dde87c 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$ + * $Id: subr_diskslice.c,v 1.3 1995/01/31 04:33:41 phk Exp $ */ #include <sys/param.h> @@ -70,6 +70,12 @@ 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)); +static void set_ds_bad __P((struct diskslices *ssp, int slice, + struct dkbad_intern *btp)); +static void set_ds_label __P((struct diskslices *ssp, int slice, + struct disklabel *lp)); +static void set_ds_wlabel __P((struct diskslices *ssp, int slice, + int wlabel)); /* * Determine the size of the transfer, and make sure it is @@ -104,7 +110,7 @@ dscheck(bp, ssp) maxsz = sp->ds_size; } else { labelsect = lp->d_partitions[LABEL_PART].p_offset; -if (labelsect != 0) Debugger(""); +if (labelsect != 0) Debugger("labelsect != 0 in dscheck()"); pp = &lp->d_partitions[dkpart(bp->b_dev)]; blkno = pp->p_offset + bp->b_blkno; maxsz = pp->p_size; @@ -113,7 +119,7 @@ if (labelsect != 0) Debugger(""); newblkno = transbad144(sp->ds_bad, blkno); if (newblkno != blkno) - printf("bad block %lu -> %lu\n", + printf("should map bad block %lu -> %lu\n", blkno, newblkno); } } @@ -202,13 +208,14 @@ dsgone(sspp) sp = &ssp->dss_slices[slice]; if (sp->ds_bad != NULL) { free(sp->ds_bad, M_DEVBUF); - sp->ds_bad = NULL; + set_ds_bad(ssp, slice, (struct dkbad_intern *)NULL); } if (sp->ds_label != NULL) { free(sp->ds_label, M_DEVBUF); - sp->ds_label = NULL; + set_ds_label(ssp, slice, (struct disklabel *)NULL); } } + free(ssp, M_DEVBUF); *sspp = NULL; } @@ -229,9 +236,11 @@ dsioctl(dev, cmd, data, flags, ssp, strat, setgeom) int error; struct disklabel *lp; int old_wlabel; + int slice; struct diskslice *sp; - sp = &ssp->dss_slices[dkslice(dev)]; + slice = dkslice(dev); + sp = &ssp->dss_slices[slice]; lp = sp->ds_label; switch (cmd) { @@ -258,16 +267,20 @@ dsioctl(dev, cmd, data, flags, ssp, strat, setgeom) return (0); case DIOCSBAD: + if (slice == WHOLE_DISK_SLICE) + return (ENODEV); 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); + set_ds_bad(ssp, slice, internbad144((struct dkbad *)data, lp)); return (0); case DIOCSDINFO: + if (slice == WHOLE_DISK_SLICE) + return (ENODEV); if (!(flags & FWRITE)) return (EBADF); lp = malloc(sizeof *lp, M_DEVBUF, M_WAITOK); @@ -284,7 +297,7 @@ dsioctl(dev, cmd, data, flags, ssp, strat, setgeom) } if (sp->ds_label != NULL) free(sp->ds_label, M_DEVBUF); - sp->ds_label = lp; + set_ds_label(ssp, slice, lp); return (0); case DIOCWDINFO: @@ -297,15 +310,17 @@ dsioctl(dev, cmd, data, flags, ssp, strat, setgeom) * partition 0 in case that is used instead of dkpart(dev). */ old_wlabel = sp->ds_wlabel; - sp->ds_wlabel = TRUE; + set_ds_wlabel(ssp, slice, TRUE); error = correct_writedisklabel(dev, strat, sp->ds_label); - sp->ds_wlabel = old_wlabel; + set_ds_wlabel(ssp, slice, old_wlabel); return (error); case DIOCWLABEL: + if (slice == WHOLE_DISK_SLICE) + return (ENODEV); if (!(flags & FWRITE)) return (EBADF); - sp->ds_wlabel = (*(int *)data != 0); + set_ds_wlabel(ssp, slice, *(int *)data != 0); return (0); default: @@ -313,6 +328,21 @@ dsioctl(dev, cmd, data, flags, ssp, strat, setgeom) } } +int +dsisopen(ssp) + struct diskslices *ssp; +{ + int slice; + struct diskslice *sp; + + if (ssp == NULL) + return (0); + for (slice = 0; slice < ssp->dss_nslices; slice++) + if (ssp->dss_slices[slice].ds_openmask) + return (1); + return (0); +} + /* * 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 @@ -338,26 +368,20 @@ dsopen(dname, dev, mode, sspp, lp, strat, setgeom) 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) - dsgone(sspp); - } + /* + * 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) + dsgone(sspp); if (need_init) { printf("dsinit\n"); error = dsinit(dname, dev, strat, lp, sspp); if (error != 0) return (error); + lp->d_npartitions = RAW_PART + 1; + lp->d_partitions[RAW_PART].p_size = lp->d_secperunit; if (setgeom != NULL) { error = setgeom(lp); if (error != 0) @@ -365,6 +389,7 @@ dsopen(dname, dev, mode, sspp, lp, strat, setgeom) return (error); } } + ssp = *sspp; slice = dkslice(dev); if (slice >= ssp->dss_nslices) @@ -372,12 +397,14 @@ dsopen(dname, dev, mode, sspp, lp, strat, setgeom) sp = &ssp->dss_slices[slice]; part = dkpart(dev); unit = dkunit(dev); - if (slice != WHOLE_DISK_SLICE && sp->ds_label == NULL) { + if (sp->ds_label == NULL) { struct disklabel *lp1; lp1 = malloc(sizeof *lp1, M_DEVBUF, M_WAITOK); *lp1 = *lp; lp = lp1; + if (slice == WHOLE_DISK_SLICE) + goto set; printf("readdisklabel\n"); msg = correct_readdisklabel(dkmodpart(dev, RAW_PART), strat, lp); #if 0 /* XXX */ @@ -410,7 +437,7 @@ dsopen(dname, dev, mode, sspp, lp, strat, setgeom) goto out; return (EINVAL); /* XXX needs translation */ } - sp->ds_bad = internbad144(btp, lp); + set_ds_bad(ssp, slice, internbad144(btp, lp)); free(btp, M_DEVBUF); if (sp->ds_bad == NULL) { free(lp, M_DEVBUF); @@ -419,8 +446,9 @@ dsopen(dname, dev, mode, sspp, lp, strat, setgeom) return (EINVAL); /* XXX needs translation */ } } - sp->ds_label = lp; - sp->ds_wlabel = TRUE; +set: + set_ds_label(ssp, slice, lp); + set_ds_wlabel(ssp, slice, FALSE); } if (part != RAW_PART && (sp->ds_label == NULL || part >= sp->ds_label->d_npartitions)) @@ -520,6 +548,13 @@ partition_info(dname, unit, slice, part, pp) pp->p_offset, pp->p_offset + pp->p_size - 1, pp->p_size); } +/* + * Most changes to ds_bad, ds_label and ds_wlabel are made using the + * following functions to ensure coherency of the compatibility slice + * with the first BSD slice. The openmask fields are _not_ shared and + * the other fields (ds_offset and ds_size) aren't changed after they + * are initialized. + */ static void slice_info(dname, unit, slice, sp) char *dname; @@ -531,3 +566,42 @@ slice_info(dname, unit, slice, sp) dname, unit, slice, sp->ds_offset, sp->ds_offset + sp->ds_size - 1, sp->ds_size); } + +static void +set_ds_bad(ssp, slice, btp) + struct diskslices *ssp; + int slice; + struct dkbad_intern *btp; +{ + ssp->dss_slices[slice].ds_bad = btp; + if (slice == COMPATIBILITY_SLICE) + ssp->dss_slices[ssp->dss_first_bsd_slice].ds_bad = btp; + else if (slice == ssp->dss_first_bsd_slice) + ssp->dss_slices[COMPATIBILITY_SLICE].ds_bad = btp; +} + +static void +set_ds_label(ssp, slice, lp) + struct diskslices *ssp; + int slice; + struct disklabel *lp; +{ + ssp->dss_slices[slice].ds_label = lp; + if (slice == COMPATIBILITY_SLICE) + ssp->dss_slices[ssp->dss_first_bsd_slice].ds_label = lp; + else if (slice == ssp->dss_first_bsd_slice) + ssp->dss_slices[COMPATIBILITY_SLICE].ds_label = lp; +} + +static void +set_ds_wlabel(ssp, slice, wlabel) + struct diskslices *ssp; + int slice; + int wlabel; +{ + ssp->dss_slices[slice].ds_wlabel = wlabel; + if (slice == COMPATIBILITY_SLICE) + ssp->dss_slices[ssp->dss_first_bsd_slice].ds_wlabel = wlabel; + else if (slice == ssp->dss_first_bsd_slice) + ssp->dss_slices[COMPATIBILITY_SLICE].ds_wlabel = wlabel; +} |