summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/i386/isa/diskslice_machdep.c84
-rw-r--r--sys/kern/subr_diskmbr.c84
-rw-r--r--sys/kern/subr_diskslice.c134
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;
+}
OpenPOWER on IntegriCloud