summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_diskslice.c
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>1995-02-16 15:19:19 +0000
committerbde <bde@FreeBSD.org>1995-02-16 15:19:19 +0000
commit4e75b5962cb8132048272b1b7c4f3f11b158f40c (patch)
treebec48c07ddb7f0865796e61ebc793545078c01a5 /sys/kern/subr_diskslice.c
parent83aff90f5e42f9f2a8cd80d917f144fa72f1d937 (diff)
downloadFreeBSD-src-4e75b5962cb8132048272b1b7c4f3f11b158f40c.zip
FreeBSD-src-4e75b5962cb8132048272b1b7c4f3f11b158f40c.tar.gz
Add compatibility cruft.
Slice 0 is now for the first BSD slice. The first BSD slice is the first DOSpartition with id 0xa5 or the whole disk if their are no DOSpartitions (except the latter is not yet implemented). Existing partitions on it work the same as in 2.0 except the 'd' partition is no longer special and partitions are relative to the skice. Slice 1 is now for the whole disk and gets a read-only label describing the disk. Previously, slice 0 was for the whole disk and there was no label on it. Slices 2-31 are for DOSpartitions. Slice 0 is an alias for one of these if there is a BSD slice. Previously, slices 1-31 were for DOSpartitions. diskslice_machdep.c: Expand whole disk slice to include all DOSpartitions. More work is required for >1024 cylinders and to rewrite the label iff the driver is unsure about the geometry. subr_diskslice.c: New function dsisopen() to help handle media changes.
Diffstat (limited to 'sys/kern/subr_diskslice.c')
-rw-r--r--sys/kern/subr_diskslice.c134
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;
+}
OpenPOWER on IntegriCloud