[parted-devel] [PATCH] Fix gpt end of disk handling

Phillip Susi phillsusi at gmail.com
Tue Jan 3 02:18:23 UTC 2012


From: Phillip Susi <psusi at cfl.rr.com>

There are two checks for problems with the end of disk.  The first checks
to make sure that the backup gpt is actually at the end of the disk as it
should be.  The second checks to see that the gpt's idea of where the disk
ends is correct.  The handling of the backup gpt location was wrong because
if you chose not to fix the error, then as soon as you made any changes the
backup would be written to the end of the disk anyhow, only the previous
backup would not be zeroed.

This patch fixes the write path to put the backup gpt where the gpt says
the disk ends, not where we think the disk ends.  This allows you to choose
not to fix the end of disk problem ( disk has grown ), and the backup gpt
will be written to the same place it was before, not the new end of disk.

Since the backup is always written to where the gpt says the disk ends,
the first check has been modified so that it compares the backup location
with where the gpt says the disk ends instead of where we think it ends.
Also, if you do not choose to fix the error, then we fail to read the
partition table, since continuing with the error would result in the error
being corrected anyway when the table is written.  The fix option for
correcting the size of the disk also will now zero the old backup gpt.

Signed-off-by: Phillip Susi <psusi at cfl.rr.com>
---
 libparted/labels/gpt.c |   42 +++++++++++++++++++++++++-----------------
 1 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/libparted/labels/gpt.c b/libparted/labels/gpt.c
index 9d464c6..ec578f7 100644
--- a/libparted/labels/gpt.c
+++ b/libparted/labels/gpt.c
@@ -755,6 +755,13 @@ _parse_header (PedDisk *disk, const GuidPartitionTableHeader_t *gpt,
       if (q == PED_EXCEPTION_FIX)
         {
           last_usable = last_usable_if_grown;
+          /* clear the old backup gpt header */
+          PedSector gpt_disk_end = gpt_disk_data->data_area.end + 1;
+          gpt_disk_end += ((PedSector) (gpt_disk_data->entry_count) *
+                           (PedSector) (sizeof (GuidPartitionEntry_t)) /
+                           disk->dev->sector_size);
+          ptt_clear_sectors (disk->dev,
+                             gpt_disk_end, 1);
           *update_needed = 1;
         }
       else if (q != PED_EXCEPTION_UNHANDLED)
@@ -952,30 +959,27 @@ gpt_read (PedDisk *disk)
     {
       /* Both are valid.  */
 #ifndef DISCOVER_ONLY
-      if (PED_LE64_TO_CPU (primary_gpt->AlternateLBA) < disk->dev->length - 1)
+      gpt = primary_gpt;
+      PedSector gpt_disk_end = PED_LE64_TO_CPU (gpt->LastUsableLBA) + 1;
+      gpt_disk_end += ((PedSector) (PED_LE32_TO_CPU (gpt->NumberOfPartitionEntries)) *
+                       (PedSector) (PED_LE32_TO_CPU (gpt->SizeOfPartitionEntry)) /
+                       disk->dev->sector_size);
+
+      if (PED_LE64_TO_CPU (primary_gpt->AlternateLBA) != gpt_disk_end)
         {
-          switch (ped_exception_throw
+          if (ped_exception_throw
                   (PED_EXCEPTION_ERROR,
-                   (PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL
-                    | PED_EXCEPTION_IGNORE),
+                   (PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL),
                    _("The backup GPT table is not at the end of the disk, as it "
-                     "should be.  This might mean that another operating system "
-                     "believes the disk is smaller.  Fix, by moving the backup "
-                     "to the end (and removing the old backup)?")))
-            {
-            case PED_EXCEPTION_CANCEL:
-              goto error_free_gpt;
-            case PED_EXCEPTION_FIX:
+                     "should be.  Fix, by moving the backup to the end "
+                     "(and removing the old backup)?")) == PED_EXCEPTION_FIX)
+	    {
               ptt_clear_sectors (disk->dev,
                                  PED_LE64_TO_CPU (primary_gpt->AlternateLBA), 1);
               write_back = 1;
-              break;
-            default:
-              break;
-            }
+            } else goto error_free_gpt;
         }
 #endif /* !DISCOVER_ONLY */
-      gpt = primary_gpt;
       pth_free (backup_gpt);
     }
   else if (!primary_gpt && !backup_gpt)
@@ -1150,7 +1154,11 @@ _generate_header (const PedDisk *disk, int alternate, uint32_t ptes_crc,
   else
     {
       gpt->MyLBA = PED_CPU_TO_LE64 (1);
-      gpt->AlternateLBA = PED_CPU_TO_LE64 (disk->dev->length - 1);
+      PedSector gpt_disk_end = gpt_disk_data->data_area.end + 1;
+      gpt_disk_end += ((PedSector) (gpt_disk_data->entry_count) *
+                       (PedSector) (sizeof (GuidPartitionEntry_t)) /
+                       disk->dev->sector_size);
+      gpt->AlternateLBA = PED_CPU_TO_LE64 (gpt_disk_end);
       gpt->PartitionEntryLBA = PED_CPU_TO_LE64 (2);
     }
 
-- 
1.7.5.4




More information about the parted-devel mailing list