[Parted-commits] GNU Parted Official Repository: Changes to 'master'

Jim Meyering meyering at alioth.debian.org
Sun Jan 22 22:12:20 UTC 2012


 NEWS                              |    8 +++
 libparted/labels/gpt.c            |   20 ++++-----
 tests/Makefile.am                 |    1 
 tests/t0211-gpt-rewrite-header.sh |   79 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 97 insertions(+), 11 deletions(-)

New commits:
commit 552995beccf1c7543b37584bb037e6a1f508c8a4
Author: Jim Meyering <meyering at redhat.com>
Date:   Sun Jan 22 14:56:47 2012 +0100

    tests: test for yesterday's bug fix
    
    * tests/Makefile.am (TESTS): Add it.
    * tests/t0211-gpt-rewrite-header.sh: New test.

diff --git a/tests/Makefile.am b/tests/Makefile.am
index 77a1cae..88efbdd 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -21,6 +21,7 @@ TESTS = \
   t0207-IEC-binary-notation.sh \
   t0208-mkpart-end-in-IEC.sh \
   t0210-gpt-resized-partition-entry-array.sh \
+  t0211-gpt-rewrite-header.sh \
   t0220-gpt-msftres.sh \
   t0250-gpt.sh \
   t0280-gpt-corrupt.sh \
diff --git a/tests/t0211-gpt-rewrite-header.sh b/tests/t0211-gpt-rewrite-header.sh
new file mode 100644
index 0000000..475c3db
--- /dev/null
+++ b/tests/t0211-gpt-rewrite-header.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+# exercise parted's gpt-rewriting code
+# When it encounters a GPT device with backup not at the end,
+# parted (without -s) offers to correct that by moving the backup
+# header to the end of the device.  Before parted-3.1, when it attempted
+# to do that, starting with a 9-PTE array, it would render the result invalid.
+
+# Copyright (C) 2012 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/init.sh"; path_prepend_ ../parted $srcdir
+require_perl_digest_crc_
+
+ss=$sector_size_
+
+ns=100         # Initial number of sectors.
+ns2=$((ns+64)) # Some larger number of sectors.
+dev=loop-file
+# create a file large enough to hold a GPT partition table
+dd if=/dev/null of=$dev bs=$ss seek=$ns || framework_failure
+
+# create a GPT partition table with 9 PTEs.
+parted -a min -s $dev mklabel gpt \
+    mkpart p1 34s 34s \
+    mkpart p2 35s 35s \
+    mkpart p3 36s 36s \
+    mkpart p4 37s 37s \
+    mkpart p5 38s 38s \
+    mkpart p6 39s 39s \
+    mkpart p7 40s 40s \
+    mkpart p8 41s 41s \
+    mkpart p9 42s 42s \
+  > out 2>&1 || fail=1
+# expect no output
+compare /dev/null out || fail=1
+
+# Adjust the GPT table to have only 9 PTEs.
+gpt-header-munge --sector-size=$ss --n=9 $dev || fail=1
+
+# Extend size of the device.
+dd if=/dev/null of=$dev bs=$ss seek=$ns2 || fail=1
+
+printf '%s\n' f f > in || fail=1
+
+# This would always succeed, even before.
+parted ---pretend-input-tty $dev u s p < in || fail=1
+
+printf '%s\n' \
+    'BYT;' \
+    "...:${ns2}s:file:$ss:$ss:gpt:;" \
+    '1:34s:34s:1s::p1:;' \
+    '2:35s:35s:1s::p2:;' \
+    '3:36s:36s:1s::p3:;' \
+    '4:37s:37s:1s::p4:;' \
+    '5:38s:38s:1s::p5:;' \
+    '6:39s:39s:1s::p6:;' \
+    '7:40s:40s:1s::p7:;' \
+    '8:41s:41s:1s::p8:;' \
+    '9:42s:42s:1s::p9:;' \
+  > exp || fail=1
+
+# Before parted-3.1, this would fail, reporting that both tables are corrupt.
+parted -m -s $dev u s p > out 2>&1 || fail=1
+sed '2s/^[^:]*:/...:/' out > k && mv k out
+compare exp out || fail=1
+
+Exit $fail

commit 6d69c7183ec30e245834ed04b8755e3bc938b455
Author: Jim Meyering <meyering at redhat.com>
Date:   Sat Jan 21 12:50:59 2012 +0100

    libparted: gpt: rewrite even a 9-partition-entry table properly
    
    The vast majority of GPT partition tables have 128 PTEs (partition
    table entries.  However, zfs-related ones have only 9, and when
    rewriting one (which can happen only in interactive mode), parted
    would fail to write the full PTE array whenever the PTE array size
    was not a multiple of the sector size.  This fixes the same type
    of bug as v3.0-45-gce85c51.
    * libparted/labels/gpt.c (gpt_write): When computing how many sectors
    to write for the PTE array, round up rather than truncating.  This
    matters only when n_PTEs * 128 is not a multiple of the sector size.
    For details on how to reproduce see the test or
    http://thread.gmane.org/gmane.comp.gnu.parted.bugs/10691/focus=10695
    * NEWS (Bug fixes): Mention it.

diff --git a/NEWS b/NEWS
index 7584c56..9d189dc 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,7 @@ GNU parted NEWS                                    -*- outline -*-
   parted has improved support for partitionable loopback devices
 
 ** Bug fixes
+
   The msdos partition table claimed a maximum partition count of 16
   but would allow you to go beyond that.  This resulted in the kernel
   not being informed of those partitions.  Corrected to enforce the
@@ -19,6 +20,13 @@ GNU parted NEWS                                    -*- outline -*-
   of "Error: ...unrecognised disk label" and "Error:... both GPT primary
   and backup partition tables are corrupted".
 
+  libparted: given a GPT table with a partition table array of length, say 9,
+  (usually, there are at least 128 entries) and when run in interactive mode
+  with the backup header not at the end of the device where it belongs, parted
+  would offer to fix it by moving the backup header to the end.  If you
+  accepted, parted could corrupt both headers, truncating their on-disk
+  PTE arrays.  Now, parted handles this case.
+
   libparted: gpt_disk_duplicate now copies the flags over to the new
   disk object. Previously the flags would be undefined.
 
diff --git a/libparted/labels/gpt.c b/libparted/labels/gpt.c
index c74ff51..bad9ed4 100644
--- a/libparted/labels/gpt.c
+++ b/libparted/labels/gpt.c
@@ -1236,8 +1236,9 @@ gpt_write (const PedDisk *disk)
   free (pth_raw);
   if (!write_ok)
     goto error_free_ptes;
-  if (!ped_device_write (disk->dev, ptes, 2,
-                         ptes_bytes / disk->dev->sector_size))
+  size_t ss = disk->dev->sector_size;
+  PedSector ptes_sectors = (ptes_bytes + ss - 1) / ss;
+  if (!ped_device_write (disk->dev, ptes, 2, ptes_sectors))
     goto error_free_ptes;
 
   /* Write Alternate PTH & PTEs */
@@ -1253,9 +1254,7 @@ gpt_write (const PedDisk *disk)
   if (!write_ok)
     goto error_free_ptes;
   if (!ped_device_write (disk->dev, ptes,
-                         disk->dev->length - 1 -
-                         ptes_bytes / disk->dev->sector_size,
-                         ptes_bytes / disk->dev->sector_size))
+                         disk->dev->length - 1 - ptes_sectors, ptes_sectors))
     goto error_free_ptes;
 
   free (ptes);

commit b1e4a02c3f905ca566175e3c62cfa0c2a7cb1c1a
Author: Jim Meyering <meyering at redhat.com>
Date:   Sat Jan 21 11:49:08 2012 +0100

    maint: clean-up preparing for bug fix
    
    * libparted/labels/gpt.c (gpt_write): Rename local:
    s/ptes_size/ptes_bytes/; declare as size_t, not "int".
    Move decls "down".

diff --git a/libparted/labels/gpt.c b/libparted/labels/gpt.c
index 3fdd672..c74ff51 100644
--- a/libparted/labels/gpt.c
+++ b/libparted/labels/gpt.c
@@ -1193,12 +1193,10 @@ static int
 gpt_write (const PedDisk *disk)
 {
   GPTDiskData *gpt_disk_data;
-  GuidPartitionEntry_t *ptes;
   uint32_t ptes_crc;
   uint8_t *pth_raw;
   GuidPartitionTableHeader_t *gpt;
   PedPartition *part;
-  int ptes_size;
 
   PED_ASSERT (disk != NULL);
   PED_ASSERT (disk->dev != NULL);
@@ -1206,11 +1204,12 @@ gpt_write (const PedDisk *disk)
 
   gpt_disk_data = disk->disk_specific;
 
-  ptes_size = sizeof (GuidPartitionEntry_t) * gpt_disk_data->entry_count;
-  ptes = (GuidPartitionEntry_t *) ped_malloc (ptes_size);
+  size_t ptes_bytes = (gpt_disk_data->entry_count
+			* sizeof (GuidPartitionEntry_t));
+  GuidPartitionEntry_t *ptes = malloc (ptes_bytes);
   if (!ptes)
     goto error;
-  memset (ptes, 0, ptes_size);
+  memset (ptes, 0, ptes_bytes);
   for (part = ped_disk_next_partition (disk, NULL); part;
        part = ped_disk_next_partition (disk, part))
     {
@@ -1219,7 +1218,7 @@ gpt_write (const PedDisk *disk)
       _partition_generate_part_entry (part, &ptes[part->num - 1]);
     }
 
-  ptes_crc = efi_crc32 (ptes, ptes_size);
+  ptes_crc = efi_crc32 (ptes, ptes_bytes);
 
   /* Write protective MBR */
   if (!_write_pmbr (disk->dev))
@@ -1238,7 +1237,7 @@ gpt_write (const PedDisk *disk)
   if (!write_ok)
     goto error_free_ptes;
   if (!ped_device_write (disk->dev, ptes, 2,
-                         ptes_size / disk->dev->sector_size))
+                         ptes_bytes / disk->dev->sector_size))
     goto error_free_ptes;
 
   /* Write Alternate PTH & PTEs */
@@ -1255,8 +1254,8 @@ gpt_write (const PedDisk *disk)
     goto error_free_ptes;
   if (!ped_device_write (disk->dev, ptes,
                          disk->dev->length - 1 -
-                         ptes_size / disk->dev->sector_size,
-                         ptes_size / disk->dev->sector_size))
+                         ptes_bytes / disk->dev->sector_size,
+                         ptes_bytes / disk->dev->sector_size))
     goto error_free_ptes;
 
   free (ptes);



More information about the Parted-commits mailing list