libfdisk: (gpt) recover from corrupted primary/backup PT

We already have all code to support this feature, unfortunately
it was not used in gpt_probe_label()...

References: https://bugzilla.redhat.com/show_bug.cgi?id=1022217
Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2013-10-23 10:27:39 +02:00
parent 49807b316a
commit d2d9efa103
1 changed files with 32 additions and 12 deletions

View File

@ -1094,6 +1094,8 @@ static int gpt_probe_label(struct fdisk_context *cxt)
gpt = self_label(cxt);
/* TODO: it would be nice to support scenario when GPT headers are OK,
* but PMBR is corrupt */
mbr_type = valid_pmbr(cxt);
if (!mbr_type)
goto failed;
@ -1104,21 +1106,39 @@ static int gpt_probe_label(struct fdisk_context *cxt)
/* primary header */
gpt->pheader = gpt_read_header(cxt, GPT_PRIMARY_PARTITION_TABLE_LBA,
&gpt->ents);
/* backup header */
gpt->bheader = gpt_read_header(cxt, last_lba(cxt),
gpt->pheader ? NULL : &gpt->ents);
/*
* TODO: If the primary GPT is corrupt, we must check the last LBA of the
* device to see if it has a valid GPT Header and point to a valid GPT
* Partition Entry Array.
* If it points to a valid GPT Partition Entry Array, then software should
* restore the primary GPT if allowed by platform policy settings.
*
* For now we just abort GPT probing!
*/
if (!gpt->pheader || !gpt->ents)
if (!gpt->pheader && !gpt->bheader)
goto failed;
/* OK, probing passed, now initialize backup header and fdisk variables. */
gpt->bheader = gpt_read_header(cxt, last_lba(cxt), NULL);
/* primary OK, backup corrupted -- recovery */
if (gpt->pheader && !gpt->bheader) {
fdisk_warnx(cxt, _("The backup GPT table is corrupt, but the "
"primary appears OK, so that will be used."));
gpt->bheader = calloc(1, sizeof(*gpt->bheader));
if (!gpt->bheader) {
fdisk_warn(cxt, _("failed to allocate GPT header"));
goto failed;
}
gpt_mknew_header_from_bkp(cxt, gpt->bheader,
last_lba(cxt), gpt->pheader);
gpt_recompute_crc(gpt->bheader, gpt->ents);
/* primary corrupted, backup OK -- recovery */
} else if (!gpt->pheader && gpt->bheader) {
fdisk_warnx(cxt, _("The primary GPT table is corrupt, but the "
"backup appears OK, so that will be used."));
gpt->pheader = calloc(1, sizeof(*gpt->bheader));
if (!gpt->pheader) {
fdisk_warn(cxt, _("failed to allocate GPT header"));
goto failed;
}
gpt_mknew_header_from_bkp(cxt, gpt->pheader,
GPT_PRIMARY_PARTITION_TABLE_LBA, gpt->bheader);
gpt_recompute_crc(gpt->pheader, gpt->ents);
}
cxt->label->nparts_max = le32_to_cpu(gpt->pheader->npartition_entries);
cxt->label->nparts_cur = partitions_in_use(gpt->pheader, gpt->ents);