Subject: Re: NetBSD/alpha/i386 disklabel
To: Ray Phillips <r.phillips@jkmrc.uq.edu.au>
From: Roland Dowdeswell <elric@imrryr.org>
List: port-i386
Date: 05/21/2002 02:10:16
On 1021956201 seconds since the Beginning of the UNIX epoch
Ray Phillips wrote:
>

>It seems the disklabels created by NetBSD/alpha and NetBSD/i386 
>aren't compatible?  I tried two experiments:

I had this problem recently when my AS200's powersupply died.  To
make a long story short the disks were in San Francisco and had to
be plugged into a peecee but originated from an Alpha.  I looked around
a bit (perhaps too much) in the source and found that:

in src/sys/alpha/alpha/disksubr.c:readdisklablel()

	it looks for the disklabel at LABELSECTOR which is
	defined in src/sys/alpha/include/disklabel.h

		#define LABELSECTOR	0

in src/sys/i386/i386/disksubr.c:readdisklabel()

	the story is a little more complicated, but it tries to
	find an MBR (presumably failing), and then looks for the
	label at (dospartoff + LABELSECTOR) which is defined in
	src/sys/i386/include/disklabel.h


		#define LABELSECTOR	1

Unfortunately, I can't remember off the top of my head what I did,
but I am pretty sure that I just used disklabel(8) in some incarnation
to read the alpha label off the disk and then piped it to another
disklabel(8) to put it in core.

Have you tried reading the label with -r applied?  disklabel(8)
may be able to get the label directly, even when the kernel cannot.
It `looks' like `disklabel -r sd0' should be able to read an alpha
partition table, since it does not appear to skip the first sector..
But, YMMV, since I can't run the experiment, I just had a quick look
at the source.  C.f. src/sbin/disklabel/disklabel.c:readlabel():

		sectoffsec = 0;

#ifdef USE_MBR  
                if (dosdp)
                        sectoffset = (off_t)dosdp->mbrp_start * DEV_BSIZE;
#endif  /* USE_MBR */

This doesn't look like it'll be true since dosdp is initialised by:

        dosdp = readmbr(f);

(around line 296), and readmbr should return 0 since it will not
find anything there of use.

Continuing in readlabel():

                if (lseek(f, sectoffset, SEEK_SET) < 0 ||
                    read(f, bootarea, BBSIZE) != BBSIZE)
                        err(4, "%s", specname);

sectoffset is probably still 0 here and hence that'll read the first
BBSIZE bytes from the disk.  Then:

                msg = "no disklabel";
                for (lp = (struct disklabel *)bootarea;
                    lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp));
                    lp = (struct disklabel *)((char *)lp + sizeof(long))) {
                        if (lp->d_magic == DISKMAGIC &&
                            lp->d_magic2 == DISKMAGIC) {
                                if (lp->d_npartitions <= MAXPARTITIONS &&
                                    dkcksum(lp) == 0)
                                        return (lp);
                                msg = "disk label corrupted";
                        }
                }

It scans through until it finds something that matches the magic.

If that doesn't work, you can play with dd(1)---but there is probably
a better way, in fact, I seem to recall using something a little
more elegant than dd(1).  If you need to fall back to that, it is
just a one sector copy.  :-)

Once you get the disklabel lossage under control, everything works
perfectly.

 == Roland Dowdeswell                      http://www.Imrryr.ORG/~elric/  ==
 == The Unofficial NetBSD Web Pages        http://www.Imrryr.ORG/NetBSD/  ==
 == The NetBSD Project                            http://www.NetBSD.ORG/  ==