[parted-devel] [PATCH 1/4] libparted: Fix check for backup header location

Brian C. Lane bcl at redhat.com
Tue Apr 8 19:12:08 UTC 2014


Add a couple of helper functions for calculating the partition table
entry size (in sectors) and for guessing the end of the disk based on
the LastUsableLBA and the Partition Table Entry size.

The backup header should be either at the end of the disk, or at what
the primary header thinks is the end of the disk. Prompt to fix the
backup header if it is located any other place.

* libparted/labels/gpt.c (_ptes_sectors): New function
  (_hdr_disk_end): New function
  (gpt_read): Use new function to test for pri's idea of end of disk
---
 libparted/labels/gpt.c | 38 +++++++++++++++++++++++++++++++-------
 1 file changed, 31 insertions(+), 7 deletions(-)

diff --git a/libparted/labels/gpt.c b/libparted/labels/gpt.c
index 42b0360..c5dea2f 100644
--- a/libparted/labels/gpt.c
+++ b/libparted/labels/gpt.c
@@ -693,6 +693,29 @@ _header_is_valid (PedDisk const *disk, GuidPartitionTableHeader_t *gpt,
   return crc == PED_LE32_TO_CPU (origcrc);
 }
 
+/* Return the number of sectors that should be used by the
+ * partition entry table.
+ */
+static PedSector
+_ptes_sectors(PedDisk const *disk, GuidPartitionTableHeader_t const *gpt)
+{
+  size_t ptes_bytes = PED_LE32_TO_CPU (gpt->SizeOfPartitionEntry) *
+                      PED_LE32_TO_CPU (gpt->NumberOfPartitionEntries);
+  /* Minimum amount of space reserved is 128 128 byte entries */
+  if (ptes_bytes < 128*128)
+    ptes_bytes = 128*128;
+  return ped_div_round_up (ptes_bytes, disk->dev->sector_size);
+}
+
+/* Return the header's idea of the last sector of the disk
+ * based on LastUsableLBA and the Partition Entry table.
+ */
+static PedSector
+_hdr_disk_end(PedDisk const *disk, GuidPartitionTableHeader_t const *gpt)
+{
+  return PED_LE64_TO_CPU (gpt->LastUsableLBA) + 1 + _ptes_sectors(disk, gpt);
+}
+
 static int
 _parse_header (PedDisk *disk, const GuidPartitionTableHeader_t *gpt,
                int *update_needed)
@@ -985,13 +1008,14 @@ gpt_read (PedDisk *disk)
     {
       /* Both are valid.  */
 #ifndef DISCOVER_ONLY
-      PedSector gpt_disk_end = PED_LE64_TO_CPU (primary_gpt->LastUsableLBA) + 1;
-      gpt_disk_end += ((PedSector) (PED_LE32_TO_CPU (primary_gpt->NumberOfPartitionEntries)) *
-                       (PedSector) (PED_LE32_TO_CPU (primary_gpt->SizeOfPartitionEntry)) /
-                       disk->dev->sector_size);
-
+      /* The backup header must be at the end of the disk, or at what the primary
+       * header thinks is the end of the disk.
+       */
       gpt_disk_data->AlternateLBA = PED_LE64_TO_CPU (primary_gpt->AlternateLBA);
-      if (PED_LE64_TO_CPU (primary_gpt->AlternateLBA) != gpt_disk_end)
+      PedSector pri_disk_end = _hdr_disk_end(disk, primary_gpt);
+
+      if (gpt_disk_data->AlternateLBA != disk->dev->length -1 &&
+          gpt_disk_data->AlternateLBA != pri_disk_end)
         {
           if (ped_exception_throw
                   (PED_EXCEPTION_ERROR,
@@ -1002,7 +1026,7 @@ gpt_read (PedDisk *disk)
             {
               ptt_clear_sectors (disk->dev,
                                  PED_LE64_TO_CPU (primary_gpt->AlternateLBA), 1);
-              gpt_disk_data->AlternateLBA = gpt_disk_end;
+              gpt_disk_data->AlternateLBA = disk->dev->length -1;
               write_back = 1;
             }
         }
-- 
1.9.0




More information about the parted-devel mailing list