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

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