Blame SOURCES/0031-Use-BLKSSZGET-to-get-device-sector-size-in-_device_p.patch

003ee8
From 61dd3d4c5eb782eb43caa95342e63727db3f8281 Mon Sep 17 00:00:00 2001
003ee8
From: David Cantrell <dcantrell@redhat.com>
003ee8
Date: Thu, 17 Mar 2016 09:24:55 -0400
003ee8
Subject: [PATCH] Use BLKSSZGET to get device sector size in
003ee8
 _device_probe_geometry()
003ee8
003ee8
Seen on certain newer devices (such as >32G SDHC memory cards), the
003ee8
HDIO_GETGEO ioctl does not return useful information.  The libparted
003ee8
code records hardware and bios reported geometry information, but all of
003ee8
that is largely unusable these days.  The information is used in the
003ee8
PedConstraint code for aligning partitions.  The sector count is most
003ee8
useful.  Rather than only trying HDIO_GETGIO, first initialize the
003ee8
bios_geom fields to 0 and then use BLKSSZGET to capture the sector size.
003ee8
If that fails, try HDIO_GETGEO.  And if that fails, raise a warning and
003ee8
fall back on the library's default sector size macro.
003ee8
003ee8
This problem showed up on Raspberry Pi devices where users were
003ee8
attempting to grow a partition to fill the SDHC card.  Using the
003ee8
optimal_aligned_constraint returned invalid geometry information
003ee8
(98703359 instead of 124735488 sectors).  The issue was reported here:
003ee8
003ee8
    https://github.com/fedberry/fedberry/issues/8
003ee8
003ee8
And to the pyparted project:
003ee8
003ee8
    https://github.com/rhinstaller/pyparted/issues/25
003ee8
003ee8
I've applied this patch locally to parted, rebuilt, and reinstalled it
003ee8
and it is working correctly for the problem SDHC cards.
003ee8
003ee8
Signed-off-by: Brian C. Lane <bcl@redhat.com>
003ee8
---
003ee8
 libparted/arch/linux.c | 40 +++++++++++++++++++++++++---------------
003ee8
 1 file changed, 25 insertions(+), 15 deletions(-)
003ee8
003ee8
diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c
003ee8
index 1198f52..326b956 100644
003ee8
--- a/libparted/arch/linux.c
003ee8
+++ b/libparted/arch/linux.c
003ee8
@@ -852,6 +852,7 @@ _device_probe_geometry (PedDevice* dev)
003ee8
         LinuxSpecific*          arch_specific = LINUX_SPECIFIC (dev);
003ee8
         struct stat             dev_stat;
003ee8
         struct hd_geometry      geometry;
003ee8
+        int                     sector_size = 0;
003ee8
 
003ee8
         if (!_device_stat (dev, &dev_stat))
003ee8
                 return 0;
003ee8
@@ -863,26 +864,35 @@ _device_probe_geometry (PedDevice* dev)
003ee8
         if (!dev->length)
003ee8
                 return 0;
003ee8
 
003ee8
-        /* The GETGEO ioctl is no longer useful (as of linux 2.6.x).  We could
003ee8
-         * still use it in 2.4.x, but this is contentious.  Perhaps we should
003ee8
-         * move to EDD. */
003ee8
-        dev->bios_geom.sectors = 63;
003ee8
-        dev->bios_geom.heads = 255;
003ee8
-        dev->bios_geom.cylinders
003ee8
-                = dev->length / (63 * 255);
003ee8
+        /* initialize the bios_geom values to something */
003ee8
+        dev->bios_geom.sectors = 0;
003ee8
+        dev->bios_geom.heads = 0;
003ee8
+        dev->bios_geom.cylinders = 0;
003ee8
 
003ee8
-        /* FIXME: what should we put here?  (TODO: discuss on linux-kernel) */
003ee8
-        if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geometry)
003ee8
+        if (!ioctl (arch_specific->fd, BLKSSZGET, &sector_size)) {
003ee8
+                /* get the sector count first */
003ee8
+                dev->bios_geom.sectors = 1 + (sector_size / PED_SECTOR_SIZE_DEFAULT);
003ee8
+                dev->bios_geom.heads = 255;
003ee8
+        } else if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geometry)
003ee8
                         && geometry.sectors && geometry.heads) {
003ee8
-                dev->hw_geom.sectors = geometry.sectors;
003ee8
-                dev->hw_geom.heads = geometry.heads;
003ee8
-                dev->hw_geom.cylinders
003ee8
-                        = dev->length / (dev->hw_geom.heads
003ee8
-                                         * dev->hw_geom.sectors);
003ee8
+                /* if BLKSSZGET failed, try the deprecated HDIO_GETGEO */
003ee8
+                dev->bios_geom.sectors = geometry.sectors;
003ee8
+                dev->bios_geom.heads = geometry.heads;
003ee8
         } else {
003ee8
-                dev->hw_geom = dev->bios_geom;
003ee8
+                ped_exception_throw (
003ee8
+                        PED_EXCEPTION_WARNING,
003ee8
+                        PED_EXCEPTION_OK,
003ee8
+                        _("Could not determine sector size for %s: %s.\n"
003ee8
+                          "Using the default sector size (%lld)."),
003ee8
+                        dev->path, strerror (errno), PED_SECTOR_SIZE_DEFAULT);
003ee8
+                dev->bios_geom.sectors = 2;
003ee8
+                dev->bios_geom.heads = 255;
003ee8
         }
003ee8
 
003ee8
+        dev->bios_geom.cylinders
003ee8
+                = dev->length / (dev->bios_geom.heads
003ee8
+                                 * dev->bios_geom.sectors);
003ee8
+        dev->hw_geom = dev->bios_geom;
003ee8
         return 1;
003ee8
 }
003ee8
 
003ee8
-- 
003ee8
2.5.0
003ee8