Subject: Re: can NetBSD/alpha mount NetBSD/i386 filesystems?
To: None <port-alpha@netbsd.org>
From: Miles Nordin <carton@Ivy.NET>
List: port-alpha
Date: 10/13/2004 17:40:40
--Multipart_Wed_Oct_13_17:40:40_2004-1
Content-Type: text/plain; charset=US-ASCII

>>>>> "rcd" == Roland C Dowdeswell <elric@imrryr.org> writes:

   rcd> `disklabel -r' will find the other disklabel

unless the label is in the wrong endyness.  so I guess for i386/alpha
it should work.  

I've been using the attached kludge for a while.  I haven't used it in
years, but I think you do something like

# sleep 90 < /dev/rsd0c&
# disklabel -l sd0
# mount /dev/sd0a /mnt

the patch scans for other-endyness labels, and allows -l to load a
foreign disklabel into the kernel without writing anything to the disk
like -r does.  but I haven't used it in years.  

I think it's not good because it doesn't clean up the problem of
redundant disklabel readers in kernel and userland, and weird labels
on certain ports (sparc, macppc) that can only be read/written
natively.  it just helps, ``sometimes,'' ymmv.

-- 
Le fascisme est la dictature ouverte de la bourgeoisie.
		-- Georg Dimitrov

--Multipart_Wed_Oct_13_17:40:40_2004-1
Content-Type: text/plain; type=patch; charset=US-ASCII
Content-Disposition: attachment; filename="t0.diff"
Content-Transfer-Encoding: 7bit

Index: disklabel.c
===================================================================
RCS file: /scratch/cvsroot/netbsd/src/sbin/disklabel/disklabel.c,v
retrieving revision 1.1.1.6
retrieving revision 1.9
diff -u -r1.1.1.6 -r1.9
--- disklabel.c	28 May 2004 07:12:20 -0000	1.1.1.6
+++ disklabel.c	29 May 2004 16:58:52 -0000	1.9
@@ -55,6 +55,8 @@
 #define DKTYPENAMES
 #define FSTYPENAMES
 #include <sys/disklabel.h>
+#include <sys/types.h>
+#include <machine/bswap.h>
 #include <sys/bootblock.h>
 
 #include <ufs/ufs/dinode.h>
@@ -70,6 +72,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <util.h>
+#include <strings.h>
 
 #include <disktab.h>
 
@@ -119,16 +122,17 @@
 #endif	/* NUMBOOT > 0 */
 
 static enum	{
-	UNSPEC, EDIT, READ, RESTORE, SETWRITABLE, WRITE, WRITEBOOT, INTERACT
+	UNSPEC, EDIT, READ, LOAD, RESTORE, SETWRITABLE, WRITE, WRITEBOOT, INTERACT
 } op = UNSPEC;
 
 static	int	Fflag;
 static	int	rflag;
 static	int	tflag;
 	int	Cflag;
+static  int     lflag;
 static	int	Iflag;
 
-#define COMMON_OPTIONS	"BCFINRWb:ef:irs:tw"
+#define COMMON_OPTIONS	"BCFINRWb:ef:ilrs:tw"
 
 #ifdef DEBUG
 static int	debug;
@@ -159,6 +163,7 @@
 			    struct disklabel *);
 static void		 l_perror(const char *);
 static struct disklabel	*readlabel(int);
+static struct disklabel *bswapdisklabel __P((struct disklabel *));
 static struct disklabel	*makebootarea(char *, struct disklabel *, int);
 static int		 edit(struct disklabel *, int);
 static int		 editit(void);
@@ -244,6 +249,9 @@
 		case 'r':
 			++rflag;
 			break;
+		case 'l':
+			++lflag;
+			break;
 		case 'w':
 			if (op != UNSPEC)
 				usage();
@@ -267,13 +275,35 @@
 		if (op == UNSPEC)
 			op = WRITEBOOT;
 	} else {
-		if (op == UNSPEC)
-			op = READ;
-	}
 #else	/* NUMBOOT <= 0 */
-	if (op == UNSPEC)
-		op = READ;
+	if (1) {
 #endif	/* NUMBOOT <= 0 */
+		if (lflag) {
+			if (op == UNSPEC) {
+				op = LOAD;
+				++rflag;
+			} else {
+				if (op != WRITE && op != EDIT && op != INTERACT && op != RESTORE)
+					usage();
+				/*
+				 * rflag and lflag will actually work fine 
+				 * together in EDIT mode--the label is read 
+				 * in raw mode, and then loaded into the 
+				 * kernel without writing it to disk.  but 
+				 * 'disklabel -l; disklabel -el' is equivalent 
+				 * as long as no partitions are open, and 
+				 * treating -l and -r as mutually exclusive 
+				 * brings the user closer to an intuitive 
+				 * understanding of their meanings.
+				 */
+				if (rflag)
+					usage();
+			}
+		} else {
+			if (op == UNSPEC)
+				op = READ;
+		}
+	}
 
 	if (argc < 1)
 		usage();
@@ -345,6 +375,18 @@
 		error = checklabel(lp);
 		break;
 
+	case LOAD:
+		if (argc != 1)
+			usage();
+		lp = readlabel(f);
+		if (checklabel(lp) && ~DE_WARN)
+			error = writelabel(f, bootarea, lp);
+		else {
+			error = 1;
+			warnx("label not loaded.");
+		}
+		break;
+
 	case RESTORE:
 		if (argc < 2 || argc > 3)
 			usage();
@@ -372,8 +414,10 @@
 		*lp = lab;
 		if (checklabel(lp) == 0)
 			error = writelabel(f, bootarea, lp);
-		else
+		else {
 			error = 1;
+			warnx("label not written.");
+		}
 		break;
 
 	case WRITEBOOT:
@@ -389,8 +433,10 @@
 		*lp = tlab;
 		if (checklabel(lp) == 0)
 			error = writelabel(f, bootarea, lp);
-		else
+		else {
 			error = 1;
+			warnx("label not written.");
+		}
 		break;
 	}
 #endif	/* NUMBOOT > 0 */
@@ -481,7 +527,15 @@
 	lp->d_magic = DISKMAGIC;
 	lp->d_magic2 = DISKMAGIC;
 	lp->d_checksum = 0;
-	lp->d_checksum = dkcksum(lp);
+	lp->d_checksum = dkcksum(lp, lp->d_npartitions);
+
+	if (lflag) {
+		if (ioctl(f, DIOCSDINFO, lp) < 0) {
+			perror("ioctl DIOCSDINFO");
+			return (1);
+		}
+		return 0;
+	}
 
 	if (Fflag || rflag || Iflag)
 	{
@@ -879,7 +933,7 @@
 static struct disklabel *
 readlabel(int f)
 {
-	struct disklabel *lp;
+	struct disklabel *lp, *bslp;
 
 	if (Fflag || rflag || Iflag) {
 		const char *msg;
@@ -909,10 +963,19 @@
 			if (lp->d_magic == DISKMAGIC &&
 			    lp->d_magic2 == DISKMAGIC) {
 				if (lp->d_npartitions <= MAXPARTITIONS &&
-				    dkcksum(lp) == 0)
+				    dkcksum(lp, lp->d_npartitions) == 0)
 					return (lp);
 				msg = "disk label corrupted";
 			}
+			if (lp->d_magic == bswap32(DISKMAGIC) &&
+			    lp->d_magic2 == bswap32(DISKMAGIC)) {
+				if (bswap16(lp->d_npartitions) <= MAXPARTITIONS &&
+				    dkcksum(lp, bswap16(lp->d_npartitions)) == 0) {
+					bslp = bswapdisklabel(lp);
+					return (bslp);
+				}
+				msg = "disk label corrupted";
+			}
 		}
 		if (msg != NULL && !Iflag)
 			errx(1, "%s", msg);
@@ -933,6 +996,74 @@
 }
 
 /*
+ * byte-swap all the individual fields inside a disklabel.
+ * returns a pointer to the freshly-malloc'd disklabel.
+ * call with lp->d_npartitions as a sane (foreign-endiness) number, because 
+ *  bswapdisklabel will allocate enough memory to hold more than MAXPARTITIONS
+ */
+static struct disklabel *
+bswapdisklabel(lp)
+	struct disklabel *lp;
+{
+	struct disklabel *bslp;
+	int i;
+	struct partition *part, *bspart, *partend;
+	size_t sz;
+
+	/* sys/disklabel.h:  ``actually may be more'' */
+	sz = sizeof(*lp) + sizeof(struct partition) * (bswap16(lp->d_npartitions) - MAXPARTITIONS);
+	bslp = (struct disklabel *)malloc(sz < sizeof(*lp) ? sizeof(*lp) : sz);
+	/*
+	 * bcopy without swapping, so we don't have to bother with strings.
+	 * the variable-lengthyness expressed in the ? construct above is bzero'ed in the partition loop.
+	 */
+	bcopy(lp, bslp, sz);
+
+	bslp->d_magic = bswap32(lp->d_magic);
+	bslp->d_type = bswap16(lp->d_type);
+	bslp->d_subtype = bswap16(lp->d_subtype);
+	bslp->d_secsize = bswap32(lp->d_secsize);
+	bslp->d_nsectors = bswap32(lp->d_nsectors);
+	bslp->d_ntracks = bswap32(lp->d_ntracks);
+	bslp->d_ncylinders = bswap32(lp->d_ncylinders);
+	bslp->d_secpercyl = bswap32(lp->d_secpercyl);
+	bslp->d_secperunit = bswap32(lp->d_secperunit);
+	bslp->d_sparespertrack = bswap16(lp->d_sparespertrack);
+	bslp->d_sparespercyl = bswap16(lp->d_sparespercyl);
+	bslp->d_acylinders = bswap32(lp->d_acylinders);
+	bslp->d_rpm = bswap16(lp->d_rpm);
+	bslp->d_interleave = bswap16(lp->d_interleave);
+	bslp->d_trackskew = bswap16(lp->d_trackskew);
+	bslp->d_cylskew = bswap16(lp->d_cylskew);
+	bslp->d_headswitch = bswap32(lp->d_headswitch);
+	bslp->d_trkseek = bswap32(lp->d_trkseek);
+	bslp->d_flags = bswap32(lp->d_flags);
+	for (i = 0; i < NDDATA; i++)
+		bslp->d_drivedata[i] = bswap32(lp->d_drivedata[i]);
+	for (i = 0; i < NSPARE; i++)
+		bslp->d_spare[i] = bswap32(lp->d_spare[i]);
+	bslp->d_magic2 = bswap32(lp->d_magic2);
+	bslp->d_checksum = 0; /* hopeless.  but, checksumming is endian-independent so endian-ignorant routines elsewhere can fill this in. */
+	bslp->d_npartitions = bswap16(lp->d_npartitions);
+	bslp->d_bbsize = bswap32(lp->d_bbsize);
+	bslp->d_sbsize = bswap32(lp->d_sbsize);
+
+	bzero(bslp->d_partitions, sizeof(struct partition) * MAXPARTITIONS);
+	for (part = lp->d_partitions, bspart = bslp->d_partitions, partend = bslp->d_partitions + sizeof(struct partition) * bslp->d_npartitions; bspart < partend; bspart++, part++) {
+		bspart->p_size = bswap32(part->p_size);
+		bspart->p_offset = bswap32(part->p_offset);
+		bspart->p_fsize = bswap32(part->p_fsize);
+		/* p_fstype and p_frag don't need bswap, but we bzero'ed 'em */
+		bspart->p_fstype = part->p_fstype;
+		bspart->p_frag = part->p_frag;
+		bspart->p_cpg = bswap16(part->p_cpg);
+	}
+
+	return(bslp);
+}
+
+
+/*
  * Construct a bootarea (d_bbsize bytes) in the specified buffer ``boot''
  * Returns a pointer to the disklabel portion of the bootarea.
  */
@@ -1720,19 +1851,19 @@
 	errors = 0;
 	if (lp->d_secsize == 0) {
 		warnx("sector size %d", lp->d_secsize);
-		return (1);
+		return (DE_ERROR);
 	}
 	if (lp->d_nsectors == 0) {
 		warnx("sectors/track %d", lp->d_nsectors);
-		return (1);
+		return (DE_ERROR);
 	}
 	if (lp->d_ntracks == 0) {
 		warnx("tracks/cylinder %d", lp->d_ntracks);
-		return (1);
+		return (DE_ERROR);
 	}
 	if  (lp->d_ncylinders == 0) {
 		warnx("cylinders/unit %d", lp->d_ncylinders);
-		errors++;
+		return (DE_ERROR);
 	}
 	if (lp->d_rpm == 0)
 		warnx("warning, revolutions/minute %d", lp->d_rpm);
@@ -1743,7 +1874,7 @@
 #ifdef __i386__notyet__
 	if (dosdp && lp->d_secperunit > dosdp->mbrp_start + dosdp->mbrp_size) {
 		warnx("exceeds DOS partition size");
-		errors++;
+		errors |= DE_WARN;
 		lp->d_secperunit = dosdp->mbrp_start + dosdp->mbrp_size;
 	}
 	/* XXX should also check geometry against BIOS's idea */
@@ -1753,12 +1884,12 @@
 #endif	/* __arm32__notyet__ */
 	if (lp->d_bbsize == 0) {
 		warnx("boot block size %d", lp->d_bbsize);
-		errors++;
+		errors |= DE_WARN;
 	} else if (lp->d_bbsize % lp->d_secsize)
 		warnx("warning, boot block size %% sector-size != 0");
 	if (lp->d_sbsize == 0) {
 		warnx("super block size %d", lp->d_sbsize);
-		errors++;
+		errors |= DE_WARN;
 	} else if (lp->d_sbsize % lp->d_secsize)
 		warnx("warning, super block size %% sector-size != 0");
 	if (lp->d_npartitions > MAXPARTITIONS)
@@ -1775,18 +1906,18 @@
 			warnx("warning, partition %c:"
 			      " offset %% cylinder-size != 0",
 			    part);
-			errors++;
+			errors |= DE_WARN;
 		}
 #endif	/* STRICT_CYLINDER_ALIGNMENT */
 		if (pp->p_offset > lp->d_secperunit) {
 			warnx("partition %c: offset past end of unit", part);
-			errors++;
+			errors |= DE_ERROR;
 		}
 		if (pp->p_offset + pp->p_size > lp->d_secperunit) {
 			warnx("partition %c: partition extends"
 			      " past end of unit",
 			    part);
-			errors++;
+			errors |= DE_ERROR;
 		}
 	}
 	for (; i < MAXPARTITIONS; i++) {
@@ -1852,18 +1983,20 @@
 	} usages[] = {
 	{ "[-rt] [-C] [-F] disk",
 	    "(to read label)" },
-	{ "-w [-r] [-F] [-f disktab] disk type [ packid ]",
+	{ "-l disk",
+	    "(to read label and load it into the kernel)" },
+	{ "-w [-r|-l] [-F] [-f disktab] disk type [ packid ]",
 #if NUMBOOT > 0
 	    "(to write label with existing boot program)"
 #else
 	    "(to write label)"
 #endif
 	},
-	{ "-e [-r] [-I] [-C] [-F] disk",
+	{ "-e [-r|-l] [-I] [-C] [-F] disk",
 	    "(to edit label)" },
-	{ "-i [-I] [-r] [-F] disk",
+	{ "-i [-I] [-r|-l] [-F] disk",
 	    "(to create a label interactively)" },
-	{ "-R [-r] [-F] disk protofile",
+	{ "-R [-r|-l] [-F] disk protofile",
 #if NUMBOOT > 0
 	    "(to restore label with existing boot program)"
 #else
Index: dkcksum.c
===================================================================
RCS file: /scratch/cvsroot/netbsd/src/sbin/disklabel/dkcksum.c,v
retrieving revision 1.1.1.2
retrieving revision 1.3
diff -u -r1.1.1.2 -r1.3
--- dkcksum.c	12 Dec 2003 11:29:04 -0000	1.1.1.2
+++ dkcksum.c	12 Dec 2003 20:30:02 -0000	1.3
@@ -43,14 +43,14 @@
 #include "dkcksum.h"
 
 u_short
-dkcksum(struct disklabel *lp)
+dkcksum(struct disklabel *lp, u_int16_t npart)
 {
 	u_short	*start, *end;
 	u_short	 sum;
 
 	sum = 0;
 	start = (u_short *)lp;
-	end = (u_short *)&lp->d_partitions[lp->d_npartitions];
+	end = (u_short *)&lp->d_partitions[npart];
 	while (start < end)
 		sum ^= *start++;
 	return (sum);
Index: dkcksum.h
===================================================================
RCS file: /scratch/cvsroot/netbsd/src/sbin/disklabel/dkcksum.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- dkcksum.h	4 Mar 2002 18:38:33 -0000	1.1.1.1
+++ dkcksum.h	8 Mar 2002 23:58:21 -0000	1.2
@@ -1,3 +1,3 @@
 /*	$NetBSD: dkcksum.h,v 1.3 2000/12/24 05:59:11 lukem Exp $	*/
 
-u_short	dkcksum(struct disklabel *);
+u_short dkcksum __P((struct disklabel *, u_int16_t));
Index: extern.h
===================================================================
RCS file: /scratch/cvsroot/netbsd/src/sbin/disklabel/extern.h,v
retrieving revision 1.1.1.2
retrieving revision 1.3
diff -u -r1.1.1.2 -r1.3
--- extern.h	19 Apr 2002 18:31:56 -0000	1.1.1.2
+++ extern.h	24 Apr 2002 23:26:03 -0000	1.3
@@ -29,6 +29,10 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+/* error codes for checklabel */
+#define DE_WARN		(1 << 0)
+#define DE_ERROR	(1 << 1)
+
 int	writelabel(int, char *, struct disklabel *);
 int	checklabel(struct disklabel *);
 void	showinfo(FILE *, struct disklabel *, const char *);

--Multipart_Wed_Oct_13_17:40:40_2004-1--