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: