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

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