Subject: kern/2675: [dM] 8 partitions is awfully few
To: None <gnats-bugs@NetBSD.ORG>
From: der Mouse <mouse@Collatz.McRCIM.McGill.EDU>
List: netbsd-bugs
Date: 08/05/1996 15:53:38
>Number: 2675
>Category: kern
>Synopsis: [dM] 8 partitions is awfully few
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Mon Aug 5 16:20:03 1996
>Last-Modified:
>Originator: der Mouse
>Organization:
Dis-
>Release: -current sup (= 1.2 release branch) of 29 Jul 1996
>Environment:
Any SPARC (I use an IPC)
>Description:
Especially with the advent of modern disks with sizes up around
4G and 9G and the like, 8 partitions per disk seems awfully
few.
>How-To-Repeat:
Try to split up a big disk. Find yourself constrained by the
seven-partition limit (eight including c). Sigh.
>Fix:
Here's what I've done. It seems to work reasonably well. I've
tucked the "other" eight partitions in the spare space in the
disklabel between the ASCII label string and the RPM value,
with a magic number and a checksum. If either magic or
checksum is wrong, the "extended" eight partitions are all 0
offset 0 size.
The disksubr.c patch includes a fix to bounds_check_with_label;
I think I saw a commit message indicating this - or something
like it - went into the main branch, but it hasn't yet showed
up in the sups. I'm including it here on the theory that
anyone who is into fiddling with disk labeling to the point of
sixteen partitions probably also wants this fix. :-)
I'm not sure I've done all that's necessary to MAKEDEV; I'd
appreciate any remarks from those who know.
--- OLD/etc/etc.sparc/MAKEDEV Thu Jan 1 00:00:00 1970
+++ NEW/etc/etc.sparc/MAKEDEV Thu Jan 1 00:00:00 1970
@@ -167,27 +167,42 @@
vnd*) name=vnd; blk=8; chr=110;;
esac
case $unit in
- 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|\
- 17|18|19|20|21|22|23|24|25|26|27|28|29|30|31)
- rm -f ${name}${unit}[a-h] r${name}${unit}[a-h]
- mknod ${name}${unit}c b $blk `expr $unit '*' 8 + 2`
- mknod r${name}${unit}c c $chr `expr $unit '*' 8 + 2`
- mknod ${name}${unit}a b $blk `expr $unit '*' 8 + 0`
- mknod ${name}${unit}b b $blk `expr $unit '*' 8 + 1`
- mknod ${name}${unit}d b $blk `expr $unit '*' 8 + 3`
- mknod ${name}${unit}e b $blk `expr $unit '*' 8 + 4`
- mknod ${name}${unit}f b $blk `expr $unit '*' 8 + 5`
- mknod ${name}${unit}g b $blk `expr $unit '*' 8 + 6`
- mknod ${name}${unit}h b $blk `expr $unit '*' 8 + 7`
- mknod r${name}${unit}a c $chr `expr $unit '*' 8 + 0`
- mknod r${name}${unit}b c $chr `expr $unit '*' 8 + 1`
- mknod r${name}${unit}d c $chr `expr $unit '*' 8 + 3`
- mknod r${name}${unit}e c $chr `expr $unit '*' 8 + 4`
- mknod r${name}${unit}f c $chr `expr $unit '*' 8 + 5`
- mknod r${name}${unit}g c $chr `expr $unit '*' 8 + 6`
- mknod r${name}${unit}h c $chr `expr $unit '*' 8 + 7`
- chgrp operator ${name}${unit}[a-h] r${name}${unit}[a-h]
- chmod 640 ${name}${unit}[a-h] r${name}${unit}[a-h]
+ 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15)
+ rm -f ${name}${unit}[a-p] r${name}${unit}[a-p]
+ mknod ${name}${unit}c b $blk `expr $unit '*' 16 + 2`
+ mknod r${name}${unit}c c $chr `expr $unit '*' 16 + 2`
+ mknod ${name}${unit}a b $blk `expr $unit '*' 16 + 0`
+ mknod ${name}${unit}b b $blk `expr $unit '*' 16 + 1`
+ mknod ${name}${unit}d b $blk `expr $unit '*' 16 + 3`
+ mknod ${name}${unit}e b $blk `expr $unit '*' 16 + 4`
+ mknod ${name}${unit}f b $blk `expr $unit '*' 16 + 5`
+ mknod ${name}${unit}g b $blk `expr $unit '*' 16 + 6`
+ mknod ${name}${unit}h b $blk `expr $unit '*' 16 + 7`
+ mknod ${name}${unit}i b $blk `expr $unit '*' 16 + 8`
+ mknod ${name}${unit}j b $blk `expr $unit '*' 16 + 9`
+ mknod ${name}${unit}k b $blk `expr $unit '*' 16 + 10`
+ mknod ${name}${unit}l b $blk `expr $unit '*' 16 + 11`
+ mknod ${name}${unit}m b $blk `expr $unit '*' 16 + 12`
+ mknod ${name}${unit}n b $blk `expr $unit '*' 16 + 13`
+ mknod ${name}${unit}o b $blk `expr $unit '*' 16 + 14`
+ mknod ${name}${unit}p b $blk `expr $unit '*' 16 + 15`
+ mknod r${name}${unit}a c $chr `expr $unit '*' 16 + 0`
+ mknod r${name}${unit}b c $chr `expr $unit '*' 16 + 1`
+ mknod r${name}${unit}d c $chr `expr $unit '*' 16 + 3`
+ mknod r${name}${unit}e c $chr `expr $unit '*' 16 + 4`
+ mknod r${name}${unit}f c $chr `expr $unit '*' 16 + 5`
+ mknod r${name}${unit}g c $chr `expr $unit '*' 16 + 6`
+ mknod r${name}${unit}h c $chr `expr $unit '*' 16 + 7`
+ mknod r${name}${unit}i c $chr `expr $unit '*' 16 + 8`
+ mknod r${name}${unit}j c $chr `expr $unit '*' 16 + 9`
+ mknod r${name}${unit}k c $chr `expr $unit '*' 16 + 10`
+ mknod r${name}${unit}l c $chr `expr $unit '*' 16 + 11`
+ mknod r${name}${unit}m c $chr `expr $unit '*' 16 + 12`
+ mknod r${name}${unit}n c $chr `expr $unit '*' 16 + 13`
+ mknod r${name}${unit}o c $chr `expr $unit '*' 16 + 14`
+ mknod r${name}${unit}p c $chr `expr $unit '*' 16 + 15`
+ chgrp operator ${name}${unit}[a-p] r${name}${unit}[a-p]
+ chmod 640 ${name}${unit}[a-p] r${name}${unit}[a-p]
;;
*)
echo bad unit for disk in: $i
--- OLD/sys/arch/sparc/include/disklabel.h Thu Jan 1 00:00:00 1970
+++ NEW/sys/arch/sparc/include/disklabel.h Thu Jan 1 00:00:00 1970
@@ -35,7 +35,7 @@
#define LABELSECTOR 0 /* sector containing label */
#define LABELOFFSET 64 /* offset of label in sector */
-#define MAXPARTITIONS 8 /* number of partitions */
+#define MAXPARTITIONS 16 /* number of partitions */
#define RAW_PART 2 /* raw partition: xx?c */
struct cpu_disklabel {
--- OLD/sys/arch/sparc/include/sun_disklabel.h Thu Jan 1 00:00:00 1970
+++ NEW/sys/arch/sparc/include/sun_disklabel.h Thu Jan 1 00:00:00 1970
@@ -88,7 +88,17 @@
struct sun_disklabel { /* total size = 512 bytes */
char sl_text[128];
- char sl_xxx1[292];
+#if MAXPARTITIONS > 8
+#define SUNXPART (MAXPARTITIONS-8)
+ u_long sl_xpsum; /* additive cksum, [sl_xpmag,sl_xxx1) */
+ u_long sl_xpmag; /* "extended" magic number */
+#define SL_XPMAG (0x199d1fe2+SUNXPART)
+ struct sun_dkpart sl_xpart[SUNXPART]; /* "extended" partitions, i through p */
+ char sl_xxx1[292-8-(8*SUNXPART)]; /* [292] including sl_x* */
+#else
+#define SUNXPART 0
+ char sl_xxx1[292];
+#endif
u_short sl_rpm; /* rotational speed */
u_short sl_pcylinders; /* number of physical cyls */
u_short sl_sparespercyl; /* spare sectors per cylinder */
--- OLD/sys/arch/sparc/sparc/disksubr.c Thu Jan 1 00:00:00 1970
+++ NEW/sys/arch/sparc/sparc/disksubr.c Thu Jan 1 00:00:00 1970
@@ -285,14 +285,16 @@
#define dkpart(dev) (minor(dev) & 7)
struct partition *p = lp->d_partitions + dkpart(bp->b_dev);
- int labelsect = lp->d_partitions[0].p_offset;
int maxsz = p->p_size;
int sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
/* overwriting disk label ? */
/* XXX should also protect bootstrap in first 8K */
- if (bp->b_blkno + p->p_offset <= LABELSECTOR + labelsect &&
- (bp->b_flags & B_READ) == 0 && wlabel == 0) {
+ /* XXX this assumes everything <=LABELSECTOR is label! */
+ /* But since LABELSECTOR is 0, that's ok for now. */
+ if ( (bp->b_blkno + p->p_offset <= LABELSECTOR) &&
+ ((bp->b_flags & B_READ) == 0) &&
+ (wlabel == 0) ) {
bp->b_error = EROFS;
goto bad;
}
@@ -330,7 +332,7 @@
/* What partition types to assume for Sun disklabels: */
static u_char
-sun_fstypes[8] = {
+sun_fstypes[16] = {
FS_BSDFFS, /* a */
FS_SWAP, /* b */
FS_OTHER, /* c - whole disk */
@@ -339,8 +341,31 @@
FS_BSDFFS, /* f */
FS_BSDFFS, /* g */
FS_BSDFFS, /* h */
+ FS_BSDFFS, /* i */
+ FS_BSDFFS, /* j */
+ FS_BSDFFS, /* k */
+ FS_BSDFFS, /* l */
+ FS_BSDFFS, /* m */
+ FS_BSDFFS, /* n */
+ FS_BSDFFS, /* o */
+ FS_BSDFFS, /* p */
};
+/* Given a struct sun_disklabel, assume it has an extended partition
+ table and compute the correct value for sl_xpsum. */
+static u_long sun_extended_sum(struct sun_disklabel *sl)
+{
+ u_long lsum;
+ u_long *xp;
+ u_long *ep;
+
+ xp = (u_long *) &sl->sl_xpmag;
+ ep = (u_long *) &sl->sl_xxx1[0];
+ lsum = 0;
+ for (;xp<ep;xp++) lsum += *xp;
+ return(lsum);
+}
+
/*
* Given a SunOS disk label, set lp to a BSD disk label.
* Returns NULL on success, else an error string.
@@ -388,7 +413,7 @@
lp->d_rpm = sl->sl_rpm;
lp->d_interleave = sl->sl_interleave;
- lp->d_npartitions = 8;
+ lp->d_npartitions = MAXPARTITIONS;
/* These are as defined in <ufs/ffs/fs.h> */
lp->d_bbsize = 8192; /* XXX */
lp->d_sbsize = 8192; /* XXX */
@@ -414,6 +439,43 @@
}
}
+#if SUNXPART > 0
+
+ /* Clear "extended" partition info, tentatively */
+ for (i=0;i<SUNXPART;i++) {
+ npp = &lp->d_partitions[i+8];
+ npp->p_offset = 0;
+ npp->p_size = 0;
+ npp->p_fstype = FS_UNUSED;
+ }
+
+ /* Check to see if there's an "extended" partition table */
+ if (sl->sl_xpmag == SL_XPMAG) { /* probably... */
+ if (sun_extended_sum(sl) == sl->sl_xpsum) { /* ...yes! */
+ /* There is. Copy over the "extended" partitions.
+ This code parallels the loop for partitions a-h. */
+ /* XXX Abstract the common code? */
+ for (i=0;i<SUNXPART;i++) {
+ spp = &sl->sl_xpart[i];
+ npp = &lp->d_partitions[i+8];
+ npp->p_offset = spp->sdkp_cyloffset * secpercyl;
+ npp->p_size = spp->sdkp_nsectors;
+ if (npp->p_size == 0) {
+ npp->p_fstype = FS_UNUSED;
+ } else {
+ npp->p_fstype = sun_fstypes[i+8];
+ if (npp->p_fstype == FS_BSDFFS) {
+ npp->p_fsize = 1024;
+ npp->p_frag = 8;
+ npp->p_cpg = 16;
+ }
+ }
+ }
+ }
+ }
+
+#endif /* if SUNXPART > 0 */
+
lp->d_checksum = 0;
lp->d_checksum = dkcksum(lp);
return (NULL);
@@ -463,6 +525,39 @@
spp->sdkp_nsectors = npp->p_size;
}
sl->sl_magic = SUN_DKMAGIC;
+
+#if SUNXPART > 0
+
+ /* The reason we load the extended table stuff only conditionally
+ is so that a label that doesn't need it will have NULs there, like
+ a "traditional" Sun label. Since Suns seem to ignore everything
+ between sl_text and sl_rpm, this probably doesn't matter, but it
+ certainly doesn't hurt anything and it's easy to do. */
+
+ /* Do we need to load the extended table? */
+ for (i=0;i<SUNXPART;i++) {
+ if (lp->d_partitions[i+8].p_offset || lp->d_partitions[i+8].p_size) break;
+ }
+ if (i < SUNXPART) { /* we do */
+ sl->sl_xpmag = SL_XPMAG;
+ for (i=0;i<SUNXPART;i++) {
+ spp = &sl->sl_xpart[i];
+ npp = &lp->d_partitions[i+8];
+ if (npp->p_offset % secpercyl) return(EINVAL);
+ sl->sl_xpart[i].sdkp_cyloffset = npp->p_offset / secpercyl;
+ sl->sl_xpart[i].sdkp_nsectors = npp->p_size;
+ }
+ sl->sl_xpsum = sun_extended_sum(sl);
+ } else {
+ sl->sl_xpmag = 0;
+ for (i=0;i<SUNXPART;i++) {
+ sl->sl_xpart[i].sdkp_cyloffset = 0;
+ sl->sl_xpart[i].sdkp_nsectors = 0;
+ }
+ sl->sl_xpsum = 0;
+ }
+
+#endif /* if SUNXPART > 0 */
/* Correct the XOR check. */
sp1 = (u_short *)sl;
der Mouse
mouse@collatz.mcrcim.mcgill.edu
01 EE 31 F6 BB 0C 34 36 00 F3 7C 5A C1 A0 67 1D
>Audit-Trail:
>Unformatted: