diff options
Diffstat (limited to 'sys/kern/subr_diskslice.c')
-rw-r--r-- | sys/kern/subr_diskslice.c | 134 |
1 files changed, 104 insertions, 30 deletions
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; +} |