[parted-devel] [PATCH] libparted: only IEC units are treated as exact

Petr Uzel petr.uzel at suse.cz
Thu Jul 21 14:46:46 UTC 2016


If the user specifies start/end of the partition as a unit,
whose size happens to be power of two, we treat that as
exact address with exact placement.

Recently, commit 01900e056ec25083 added an exception for
percent units.

This logic however can fail also for cylinders, e.g. on DASD FBA disks,
which report CHS=(*, 128, 16) geometry, hence once cylinder is 1 MiB.
With cylinders as units, exact placement is not what the user wants.

Instead of adding cylinders to the blacklist, let's instead
whitelist units which should trigger exact placement.

* libparted/unit.c (is_power_of_2): Remove now unused function.
(ped_unit_parse_custom): Specify which units trigger exact placement.
* NEWS (Bug Fixes): Mention this.
---
 NEWS             |  4 ++++
 libparted/unit.c | 33 +++++++++++++++++----------------
 2 files changed, 21 insertions(+), 16 deletions(-)

diff --git a/NEWS b/NEWS
index a92825c..198b35d 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,10 @@ GNU parted NEWS                                    -*- outline -*-
 
   libparted-fs-resize: Prevent crash resizing FAT16 file systems.
 
+  If the user specifies start/end of the partition as cylinders
+  and a cylinder has a size which is power of 2, then such address
+  does not trigger exact placement.
+
 * Noteworthy changes in release 3.2 (2014-07-28) [stable]
 
 ** New Features
diff --git a/libparted/unit.c b/libparted/unit.c
index dddb5db..e47e868 100644
--- a/libparted/unit.c
+++ b/libparted/unit.c
@@ -481,12 +481,6 @@ parse_unit_suffix (const char* suffix, PedUnit suggested_unit)
 	return suggested_unit;
 }
 
-static bool
-is_power_of_2 (long long n)
-{
-  return (n & (n - 1)) == 0;
-}
-
 /**
  * If \p str contains a valid description of a location on \p dev, then
  * \p *sector is modified to describe the location and a geometry is created
@@ -540,16 +534,23 @@ ped_unit_parse_custom (const char* str, const PedDevice* dev, PedUnit unit,
         }
 
 	unit_size = ped_unit_get_size (dev, unit);
-	radius = (ped_div_round_up (unit_size, dev->sector_size) / 2) - 1;
-	if (radius < 0)
-		radius = 0;
-	/* If the user specifies units in a power of 2, e.g., 4MiB, as in
-	       parted -s -- $dev mklabel gpt mkpart P-NAME 4MiB -34s
-	   do not use 4MiB as the range.  Rather, presume that they
-	   are specifying precisely the starting or ending number,
-	   and treat "4MiB" just as we would treat "4194304B".  */
-	if (is_power_of_2 (unit_size) && unit != PED_UNIT_PERCENT)
-		radius = 0;
+	switch (unit) {
+		/* If the user specifies the address using IEC units e.g., 4MiB, as in
+		   parted -s -- $dev mklabel gpt mkpart P-NAME 4MiB -34s
+		   do not use size of the unit as the range.  Rather, presume that they
+		   are specifying precisely the starting or ending number,
+		   and treat "4MiB" just as we would treat "4194304B".  */
+		case PED_UNIT_KIBIBYTE:
+		case PED_UNIT_MEBIBYTE:
+		case PED_UNIT_GIBIBYTE:
+		case PED_UNIT_TEBIBYTE:
+			radius = 0;
+			break;
+		default:
+			radius = (ped_div_round_up (unit_size, dev->sector_size) / 2) - 1;
+			if (radius < 0)
+				radius = 0;
+	}
 
 	*sector = num * unit_size / dev->sector_size;
 	/* negative numbers count from the end */
-- 
2.6.6




More information about the parted-devel mailing list