summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_disklabel.c
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1994-10-27 20:45:13 +0000
committerjkh <jkh@FreeBSD.org>1994-10-27 20:45:13 +0000
commit1ca2f392e18c355a8108c5c84aa5e4705aedc786 (patch)
tree0f822c63937b648594897abc7f741b0a112e7844 /sys/kern/subr_disklabel.c
parent6cc6dda103dfdc45f437f7bccf591034663fd883 (diff)
downloadFreeBSD-src-1ca2f392e18c355a8108c5c84aa5e4705aedc786.zip
FreeBSD-src-1ca2f392e18c355a8108c5c84aa5e4705aedc786.tar.gz
Julian Elischer's disklabel fixes.
Diffstat (limited to 'sys/kern/subr_disklabel.c')
-rw-r--r--sys/kern/subr_disklabel.c232
1 files changed, 146 insertions, 86 deletions
diff --git a/sys/kern/subr_disklabel.c b/sys/kern/subr_disklabel.c
index f116269..4849146 100644
--- a/sys/kern/subr_disklabel.c
+++ b/sys/kern/subr_disklabel.c
@@ -36,17 +36,17 @@
* SUCH DAMAGE.
*
* @(#)ufs_disksubr.c 8.5 (Berkeley) 1/21/94
- * $Id: ufs_disksubr.c,v 1.4 1994/10/08 06:57:23 phk Exp $
+ * $Id: ufs_disksubr.c,v 1.5 1994/10/17 02:31:33 phk Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
+#include <sys/dkbad.h>
#include <sys/disklabel.h>
#include <sys/syslog.h>
#include <sys/dkbad.h>
-int dkcksum __P((struct disklabel *));
/*
* Seek sort for disks. We depend on the driver which calls us using b_resid
* as the current cylinder number.
@@ -154,86 +154,53 @@ insert: bp->b_actf = bq->b_actf;
* anything required in the strategy routine (e.g., sector size) must be
* filled in before calling us. Returns NULL on success and an error
* string on failure.
+ * If Machine Specific Partitions (MSP) are not found, then it will proceed
+ * as if the BSD partition starts at 0
+ * The MBR on an IBM PC is an example of an MSP.
*/
char *
readdisklabel(dev, strat, lp, dp, bdp)
dev_t dev;
- int (*strat)();
+ void (*strat)();
register struct disklabel *lp;
struct dos_partition *dp;
struct dkbad *bdp;
{
register struct buf *bp;
struct disklabel *dlp;
+ char *msgMSP = NULL;
char *msg = NULL;
- int dospartoff;
int i;
- int cyl;
+ int cyl = 0;
+ /*
+ * Set up the disklabel as in case there is no MSP.
+ * We set the BSD part, but don't need to set the
+ * RAW part, because readMSPtolabel() will reset that
+ * itself. On return however, if there was no MSP,
+ * then we will be looking into OUR part to find the label
+ * and we will want that to start at 0, and have at least SOME length.
+ */
if (lp->d_secperunit == 0)
lp->d_secperunit = 0x1fffffff;
- lp->d_npartitions = 1;
- if (lp->d_partitions[0].p_size == 0)
- lp->d_partitions[0].p_size = 0x1fffffff;
- lp->d_partitions[0].p_offset = 0;
-
- bp = geteblk((int)lp->d_secsize);
- /* do dos partitions in the process of getting disklabel? */
- dospartoff = 0;
- cyl = LABELSECTOR / lp->d_secpercyl;
- if (dp) {
- /* read master boot record */
- bp->b_dev = dev;
- bp->b_blkno = DOSBBSECTOR;
- bp->b_bcount = lp->d_secsize;
- bp->b_flags = B_BUSY | B_READ;
- bp->b_cylinder = DOSBBSECTOR / lp->d_secpercyl;
- (*strat)(bp);
-
- /* if successful, wander through dos partition table */
- if (biowait(bp)) {
- msg = "dos partition I/O error";
- goto done;
- } else {
- /* XXX how do we check veracity/bounds of this? */
- bcopy(bp->b_un.b_addr + DOSPARTOFF, dp,
- NDOSPART * sizeof(*dp));
- for (i = 0; i < NDOSPART; i++, dp++)
- /* is this ours? */
- if (dp->dp_size &&
- dp->dp_typ == DOSPTYP_386BSD
- && dospartoff == 0) {
+ lp->d_npartitions = OURPART + 1;
+ if (lp->d_partitions[OURPART].p_size == 0)
+ lp->d_partitions[OURPART].p_size = 0x100; /*enough for a label*/
+ lp->d_partitions[OURPART].p_offset = 0;
- /* need sector address for SCSI/IDE,
- cylinder for ESDI/ST506/RLL */
- dospartoff = dp->dp_start;
- cyl = DPCYL(dp->dp_scyl, dp->dp_ssect);
-
- /* update disklabel with details */
- lp->d_partitions[0].p_size =
- dp->dp_size;
- lp->d_partitions[0].p_offset =
- dp->dp_start;
- lp->d_ntracks = dp->dp_ehd + 1;
- lp->d_nsectors = DPSECT(dp->dp_esect);
-#ifdef CC_WALL
-/* The next statement looks bogus... i runs int 0..3 ??? */
- lp->d_subtype |= ((lp->d_subtype & 3)
- + i) | DSTYPE_INDOSPART;
-#else /* CC_WALL */
- lp->d_subtype |= (lp->d_subtype & 3)
- + i | DSTYPE_INDOSPART;
-#endif /* CC_WALL */
- lp->d_secpercyl = lp->d_ntracks *
- lp->d_nsectors;
- }
- }
-
- }
+ /*
+ * Dig out the Dos MSP.. If we get it, all remaining transfers
+ * will be relative to the base of the BSD part.
+ */
+ msgMSP = readMSPtolabel(dev, strat, lp, dp, &cyl );
- /* next, dig out disk label */
- bp->b_blkno = dospartoff + LABELSECTOR;
- bp->b_dev = dev;
+ /*
+ * next, dig out disk label, relative to either the base of the
+ * BSD part, or block 0, depending on if an MSP was found.
+ */
+ bp = geteblk((int)lp->d_secsize);
+ bp->b_blkno = LABELSECTOR;
+ bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), OURPART));
bp->b_bcount = lp->d_secsize;
bp->b_flags = B_BUSY | B_READ;
bp->b_cylinder = cyl;
@@ -256,8 +223,19 @@ readdisklabel(dev, strat, lp, dp, bdp)
break;
}
}
- if (msg)
+
+ if (msg && msgMSP) {
+ msg = msgMSP;
goto done;
+ }
+
+ /*
+ * Since we had one of the two labels, either one made up from the
+ * MSP, one found in the FreeBSD-MSP-partitions sector 2, or even
+ * one in sector 2 absolute on the disk, there is not really an error.
+ */
+
+ msg = NULL;
/* obtain bad sector table if requested and present */
if (bdp && (lp->d_flags & D_BADSECT)) {
@@ -312,11 +290,20 @@ setdisklabel(olp, nlp, openmask)
register i;
register struct partition *opp, *npp;
+ /*
+ * Check it is actually a disklabel we are looking at.
+ */
if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC ||
dkcksum(nlp) != 0)
return (EINVAL);
+ /*
+ * For each partition that we think is open,
+ */
while ((i = ffs((long)openmask)) != 0) {
i--;
+ /*
+ * Check it is not changing....
+ */
openmask &= ~(1 << i);
if (nlp->d_npartitions <= i)
return (EBUSY);
@@ -327,6 +314,8 @@ setdisklabel(olp, nlp, openmask)
/*
* Copy internally-set partition information
* if new label doesn't include it. XXX
+ * (If we are using it then we had better stay the same type)
+ * This is possibly dubious, as someone else noted (XXX)
*/
if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) {
npp->p_fstype = opp->p_fstype;
@@ -341,38 +330,100 @@ setdisklabel(olp, nlp, openmask)
return (0);
}
-/* encoding of disk minor numbers, should be elsewhere... */
-#define dkunit(dev) (minor(dev) >> 3)
-#define dkpart(dev) (minor(dev) & 07)
-#define dkminor(unit, part) (((unit) << 3) | (part))
-
/*
* Write disk label back to device after modification.
+ * For FreeBSD 2.0(x86) this routine will refuse to install a label if
+ * there is no DOS MSP. (this can be changed)
+ *
+ * Assumptions for THIS VERSION:
+ * The given disklabel pointer is actually that which is controlling this
+ * Device, so that by fiddling it, readMSPtolabel() can ensure that
+ * it can read from the MSP if it exists,
+ * This assumption will cease as soon as ther is a better way of ensuring
+ * that a read is done to the whole raw device.
+ * MSP defines a BSD part, label is in block 1 (2nd block) of this
*/
int
writedisklabel(dev, strat, lp)
dev_t dev;
- int (*strat)();
+ void (*strat)();
register struct disklabel *lp;
{
- struct buf *bp;
+ struct buf *bp = NULL;
struct disklabel *dlp;
- int labelpart;
int error = 0;
+ struct disklabel label;
+ char *msg;
+ int BSDstart,BSDlen;
+ int cyl; /* dummy arg for readMSPtolabel() */
- labelpart = dkpart(dev);
- /* XXX this is wrong. But leaving it in is worse. */
-#ifndef __FREEBSD__
- if (lp->d_partitions[labelpart].p_offset != 0) {
- if (lp->d_partitions[0].p_offset != 0)
- return (EXDEV); /* not quite right */
- labelpart = 0;
+ /*
+ * Save the label (better be the real one)
+ * because we are going to play funny games with the disklabel
+ * controlling this device..
+ */
+ bcopy(lp,&label,sizeof(label));
+ /*
+ * Unlike the read, we will trust the parameters given to us
+ * about the disk, in the new disklabel but will simply
+ * force OURPART to start at block 0 as a default in case there is NO
+ * MSP.
+ * readMSPtolabel() will reset it to start at the start of the BSD
+ * part if it exists
+ * At this time this is an error contition but I've left support for it
+ */
+ lp->d_npartitions = OURPART + 1;
+ if (lp->d_partitions[OURPART].p_size == 0)
+ lp->d_partitions[OURPART].p_size = 0x1fffffff;
+ lp->d_partitions[OURPART].p_offset = 0;
+
+ msg = readMSPtolabel(dev, strat, lp, 0, &cyl );
+ /*
+ * If we want to be able to install without an Machine Specific
+ * Partitioning , then
+ * the failure of readMSPtolabel() should be made non fatal.
+ */
+ if(msg) {
+ printf("writedisklabel:%s\n",msg);
+ error = ENXIO;
+ goto done;
}
-#endif
+ /*
+ * If we had MSP (no message) but there
+ * was no BSD part in it
+ * then balk.. they should use fdisk to make one first or smash it..
+ * This may just be me being paranoid, but it's my choice for now..
+ * note we test for !msg, because the test above might be changed
+ * as a valid option..
+ */
+ if((!msg) && (!(lp->d_subtype & DSTYPE_INDOSPART))) {
+ printf("writedisklabel: MSP with no BSD part\n");
+ }
+
+ /*
+ * get all the other bits back from the good new disklabel
+ * (the user wouldn't try confuse us would he?)
+ * With the exception of the OURPART which now points to the
+ * BSD partition.
+ */
+ BSDstart = lp->d_partitions[OURPART].p_offset;
+ BSDlen = lp->d_partitions[OURPART].p_size;
+ bcopy(&label,lp,sizeof(label));
+ lp->d_partitions[OURPART].p_offset = BSDstart;
+ lp->d_partitions[OURPART].p_size = BSDlen;
+
bp = geteblk((int)lp->d_secsize);
- bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), labelpart));
+ bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), OURPART));
bp->b_blkno = LABELSECTOR;
bp->b_bcount = lp->d_secsize;
+#ifdef STUPID
+ /*
+ * We read the label first to see if it's there,
+ * in which case we will put ours at the same offset into the block..
+ * (I think this is stupid [Julian])
+ * Note that you can't write a label out over a corrupted label!
+ * (also stupid.. how do you write the first one? by raw writes?)
+ */
bp->b_flags = B_READ;
(*strat)(bp);
error = biowait(bp);
@@ -384,7 +435,7 @@ writedisklabel(dev, strat, lp)
dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
dkcksum(dlp) == 0) {
- *dlp = *lp;
+ bcopy(&label,dlp,sizeof(label));
bp->b_flags = B_WRITE;
(*strat)(bp);
error = biowait(bp);
@@ -392,15 +443,24 @@ writedisklabel(dev, strat, lp)
}
}
error = ESRCH;
+#else /* Stupid */
+ dlp = (struct disklabel *)bp->b_data;
+ bcopy(&label,dlp,sizeof(label));
+ bp->b_flags = B_WRITE;
+ (*strat)(bp);
+ error = biowait(bp);
+#endif /* Stupid */
done:
- brelse(bp);
+ bcopy(&label,lp,sizeof(label)); /* start using the new label again */
+ if(bp)
+ brelse(bp);
return (error);
}
/*
* Compute checksum for disk label.
*/
-int
+u_int
dkcksum(lp)
register struct disklabel *lp;
{
OpenPOWER on IntegriCloud