NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: bin/54900 (gpt(8) can not show MBR partitions on non 512 byte/sector disks)

Synopsis: gpt(8) can not show MBR partitions on non 512 byte/sector disks

State-Changed-From-To: open->analyzed
State-Changed-When: Tue, 28 Jan 2020 16:08:17 +0000

It turns out that the sector size is a red herring here, while I have
not set up a test case to demonstrate the same symptoms with a (normal)
512 byte sector size, I have no doubt that it could be done.

The primary issue here is that gpt(8) goes ahead and looks for the
GPT tables even when it has found an MBR that is not a PMBR.  To me
that makes no sense at all.

The disc which provoked this report (image supplied by martin@) had
once been GPT formatted.   The old GPT tables (with the magic "EFI Part"
string at the beginning of the 2nd sector, and a correct checksum for
the GPT header, and partition table) still exist in the image, they had
not been clobbered by changing to an MBR (which of course only alters
sector 0) nor by the partition, or its filesystem, created subsequently
which was placed after where the old GPT partition table ended.  The old
GPT partitions had had their space reused however.

The code in gpt/gpt.c does:

        if (map_init(gpt, devsz) == -1)
                goto close;     

        index = 1;      
        if (gpt_mbr(gpt, 0LL, &index, 0U) == -1)
                goto close;
        if ((found = gpt_gpt(gpt, 1LL, 1)) == -1)
                goto close;
        if (gpt_gpt(gpt, devsz - 1LL, found) == -1) 
                goto close;     

Which init's gpt(8)'s drive map, then looks for an MBR (which succeeds,
and includes the MBR header, and the partitions found [1 of them in this
case] in the drive map).

It then looks for GPT headers (which doesn't summarily fail as it
normally woould on an MBR partitioned drive -- nb: "fail" here is
not a -1 return, that indicates a detected error, but a 0 return,
which as the code suggests, means !found -- but instead starts to
add the partitions it finds into the map that already contains the MBR
partitions.   In this case the GPT header itself is "fine", and is added,
the GPT table is "fine", and is also added, then the GPT partitions are
scanned and (intended to be) added.   This is where it barfs, the first
of the (ancient) GPT partitions overlaps with the (more recent) MBR
partition, and the resulting overlap leads to the not very meaningful:

	gpt: /dev/rsd3: map entry doesn't fit media:
		new start + new size < start + size (a + 36 < a + 1ff6)

(line wrapped manually for this message).   "new" is the free space
available in the drive map, (start)A + (size)36 = 40 (hex) which is
64 (dec), which is where the (sole allocated) MBR partition starts.
1FF6 (2K each in this case) sectors won't fit.

At this point we get the "goto close" (the middle one) above, which
deletes everything achieved so far, returns NULL, and main() exits
rather than doing anything (we never get to even starting the "show"
code - it makes no difference which (valid) gpt sub-command was selected).

I am going to leave the fix for this for one of the gpt(8) experts, but
my recommendation would be to make the code above something like:

        if (map_init(gpt, devsz) == -1)
                goto close;     

        index = 1;      
        if (gpt_mbr(gpt, 0LL, &index, 0U) == -1)
                goto close;
	if (map_find(gpt, MAP_TYPE_MBR) == NULL) {
		if ((found = gpt_gpt(gpt, 1LL, 1)) == -1)
			goto close;
		if (gpt_gpt(gpt, devsz - 1LL, found) == -1) 
			goto close;     

so that if an MBR was located by gpt_mbr() we don't also look for
GPT tables.   An alternative would be to look for a MAP_TYPE_PMBR
and only do the gpt_gpt() if there was a PMBR, but I'm not certain
that every GPT user will always include a PMBR, even on systems
where MBRs have never been used for anything (eg: sun3).

I'm not sure how one would mandate this (except possibly by documenting
the need) but I'd also suggest obliterating at least the primary GPT
header (sector 1 normally) whenever converting (by any method at all)
what was once a GPT formatted drive into something else.

Home | Main Index | Thread Index | Old Index