summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarel Zak2013-10-23 10:27:39 +0200
committerKarel Zak2013-10-23 10:46:10 +0200
commitd2d9efa103a744363bd000e075435341c5256c8a (patch)
tree02cff10bfeb8c87dd67ae4c43591bc1e7bc67504
parentdocs: update TODO, wipe check for fdisk already implemented (diff)
downloadkernel-qcow2-util-linux-d2d9efa103a744363bd000e075435341c5256c8a.tar.gz
kernel-qcow2-util-linux-d2d9efa103a744363bd000e075435341c5256c8a.tar.xz
kernel-qcow2-util-linux-d2d9efa103a744363bd000e075435341c5256c8a.zip
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>
-rw-r--r--libfdisk/src/gpt.c44
1 files changed, 32 insertions, 12 deletions
diff --git a/libfdisk/src/gpt.c b/libfdisk/src/gpt.c
index 6e7b74d9f..3a256e6dc 100644
--- a/libfdisk/src/gpt.c
+++ b/libfdisk/src/gpt.c
@@ -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);