lkml.org 
[lkml]   [2005]   [Aug]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH] IDE disks show invalid geometries in /proc/ide/hd*/geometry
    The ATA specification tells large disk drives to return C/H/S data of 
    16383/16/63 regardless of their actual size (other variations on this
    return include 15 heads and/or 4092 cylinders). Unfortunately these CHS
    data confuse the existing IDE code and cause it to report invalid
    geometries in /proc when the disk runs in LBA mode.

    The invalid geometries can cause failures in the partitioning tools;
    partitioning may be impossible or illogical size limitations occur. This
    also leads to various forms of human confusion.

    I attach a patch that fixes this problem while strongly attempting to
    not break any existing side effects and await any comments.

    mark

    Signed-off-by: Mark Bellon <mbellon@mvista.com>

    diff -Naur linux-2.6.13-rc3-git9-orig/drivers/ide/ide-disk.c linux-2.6.13-rc3-git9/drivers/ide/ide-disk.c
    --- linux-2.6.13-rc3-git9-orig/drivers/ide/ide-disk.c 2005-08-01 13:48:21.000000000 -0700
    +++ linux-2.6.13-rc3-git9/drivers/ide/ide-disk.c 2005-08-02 12:14:43.000000000 -0700
    @@ -884,10 +884,17 @@
    ide_add_setting(drive, "max_failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL);
    }

    +static uint32_t do_div64_32 (__u64 n, uint32_t d)
    +{
    + do_div(n, d);
    +
    + return n;
    +}
    +
    static void idedisk_setup (ide_drive_t *drive)
    {
    struct hd_driveid *id = drive->id;
    - unsigned long long capacity;
    + __u64 capacity;
    int barrier;

    idedisk_add_settings(drive);
    @@ -949,27 +956,32 @@
    */
    capacity = idedisk_capacity (drive);
    if (!drive->forced_geom) {
    + uint32_t cylsz, cyl;

    - if (idedisk_supports_lba48(drive->id)) {
    - /* compatibility */
    - drive->bios_sect = 63;
    - drive->bios_head = 255;
    + /*
    + * In LBA mode the geometry isn't used to talk to the drive
    + * so always create a "rational" geometry from the capacity.
    + */
    + if (drive->select.b.lba) {
    + drive->bios_sect = drive->sect = 63;
    + drive->bios_head = drive->head = 255;
    +
    + cylsz = drive->bios_sect * drive->bios_head;
    + cyl = do_div64_32(capacity, cylsz);
    +
    + /* "fake out" works up to ~500 GB */
    + cyl = (cyl > 65535) ? 65535 : cyl;
    + drive->bios_cyl = drive->cyl = cyl;
    }

    if (drive->bios_sect && drive->bios_head) {
    - unsigned int cap0 = capacity; /* truncate to 32 bits */
    - unsigned int cylsz, cyl;
    + cylsz = drive->bios_sect * drive->bios_head;
    + cyl = do_div64_32(capacity, cylsz);

    - if (cap0 != capacity)
    - drive->bios_cyl = 65535;
    - else {
    - cylsz = drive->bios_sect * drive->bios_head;
    - cyl = cap0 / cylsz;
    - if (cyl > 65535)
    - cyl = 65535;
    - if (cyl > drive->bios_cyl)
    - drive->bios_cyl = cyl;
    - }
    + if (cyl > 65535)
    + cyl = 65535;
    + if (cyl > drive->bios_cyl)
    + drive->bios_cyl = cyl;
    }
    }
    printk(KERN_INFO "%s: %llu sectors (%llu MB)",
    \
     
     \ /
      Last update: 2005-08-02 23:37    [W:0.030 / U:0.996 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site