[9fans] i/o error reading large sata disk - Plan9

This is a discussion on [9fans] i/o error reading large sata disk - Plan9 ; I went to set up a file server the other day - installed w/ fossil+venti and the install went fine but after booting up it wasn't long before venti started spamming i/o errors. Now I'm using second hand disks, so ...

+ Reply to Thread
Results 1 to 4 of 4

Thread: [9fans] i/o error reading large sata disk

  1. [9fans] i/o error reading large sata disk

    I went to set up a file server the other day - installed w/
    fossil+venti and the install went fine but after booting up it wasn't
    long before venti started spamming i/o errors. Now I'm using second
    hand disks, so I figure the one I installed to might be stuffed and
    boot to the livecd to verify. I partition the disk in half and dd from
    one partition to the other, and sure enough it gets an io error on
    record 16777212 (w/ 8192 blocksize).
    16777212 is awful close to 2^24, but I can't make any sense of why
    that would be a limit. If you take the 8192 into account you're around
    byte 2^37 which makes even less sense, so I shrug it off as a bad disk
    and test the second disk... which gets a read error in the exact same
    spot.
    So, now I'm suspicious
    I can reproduce it quickly with:

    term% cat /dev/sdE0/ctl
    inquiry ST3300831AS
    config 0C5A capabilities 2F00 dma 00550020 dmactl 00000000 rwm 16
    rwmctl 0 lba48always off
    geometry 586072368 512 16383 16 63
    part data 0 586072368
    part plan9 63 293025600
    part plan9.1 293041665 586067265
    term% dd -if /dev/sdE0/plan9 -of /dev/sdE0/plan9.1 -bs 8192 -iseek 16777211
    read: i/o error
    1+0 records in
    1+0 records out

    Using blocks of 512 bytes I can narrow it down to the 268435393th
    block on the plan9 partition, which is the block that starts at byte
    2^37 (in terms of absolute disk position). I can access blocks before
    and after it fine, it's just this one... sector? Same story with the
    second disk.

    The SATA controller details from pci -v:
    3.5.0: disk 01.80.00 1095/3114 10 0:0000bc01 16 1:0000b401 16
    2:0000b001 16 3:0000ac01 16 4:0000a801 16 5:feafec00 1024
    Silicon Image, Inc. Sil 3114 SATALink/SATARaid Controller

    Anyone think they know what's going on?
    -sqweek


  2. Re: [9fans] i/o error reading large sata disk

    > term% cat /dev/sdE0/ctl
    > inquiry ST3300831AS
    > config 0C5A capabilities 2F00 dma 00550020 dmactl 00000000 rwm 16
    > rwmctl 0 lba48always off
    > geometry 586072368 512 16383 16 63
    > part data 0 586072368
    > part plan9 63 293025600
    > part plan9.1 293041665 586067265
    > term% dd -if /dev/sdE0/plan9 -of /dev/sdE0/plan9.1 -bs 8192 -iseek 16777211
    > read: i/o error


    i think i see the problem. we're off by one bit.

    in your case, i calculate h = 0xf. but since the head shares bits
    with the device, there just isn't enough room for a head > 7. i think you
    can fix this problem by

    (a) setting lba48always on
    ; echo llba48always on>/dev/sd??/ctl
    if this doesn't work, then i'm wrong.

    (b) (the proper fix). apply this change to sdata

    /n/sources/plan9//sys/src/9/pc/sdata.c:1344,1350 - sdata.c:1344,1350
    };

    static int
    - atageniostart(Drive* drive, vlong lba)
    + atageniostart(Drive* drive, uvlong lba)
    {
    Ctlr *ctlr;
    uchar cmd;
    /n/sources/plan9//sys/src/9/pc/sdata.c:1351,1357 - sdata.c:1351,1357
    int as, c, cmdport, ctlport, h, len, s, use48;

    use48 = 0;
    - if((drive->flags&Lba48always) || (lba>>28) || drive->count > 256){
    + if((drive->flags&Lba48always) || (lba>>27) || drive->count > 256){
    if(!(drive->flags & Lba48))
    return -1;
    use48 = 1;
    /n/sources/plan9//sys/src/9/pc/sdata.c:1359,1365 - sdata.c:1359,1365
    }
    else if(drive->dev & Lba){
    c = (lba>>8) & 0xFFFF;
    - h = (lba>>24) & 0x0F;
    + h = (lba>>24) & 7; /* tautology */
    s = lba & 0xFF;
    }

    there's also a problem with disk > 2GB. but that's not your problem.

    - erik



  3. Re: [9fans] i/o error reading large sata disk

    On Sun, Apr 6, 2008 at 11:58 AM, erik quanstrom wrote:
    > (a) setting lba48always on
    > ; echo llba48always on>/dev/sd??/ctl
    > if this doesn't work, then i'm wrong.


    Thanks erik, that does the trick. Didn't get around to trying the
    patch yet, I'll be in touch.
    -sqweek


  4. Re: [9fans] i/o error reading large sata disk

    > > read: i/o error
    >
    > i think i see the problem. we're off by one bit.
    >

    [...]
    > /n/sources/plan9//sys/src/9/pc/sdata.c:1344,1350 - sdata.c:1344,1350
    > };
    >
    > static int
    > - atageniostart(Drive* drive, vlong lba)
    > + atageniostart(Drive* drive, uvlong lba)
    > {
    > Ctlr *ctlr;
    > uchar cmd;
    > /n/sources/plan9//sys/src/9/pc/sdata.c:1351,1357 - sdata.c:1351,1357
    > int as, c, cmdport, ctlport, h, len, s, use48;
    >
    > use48 = 0;
    > - if((drive->flags&Lba48always) || (lba>>28) || drive->count > 256){
    > + if((drive->flags&Lba48always) || (lba>>27) || drive->count > 256){
    > if(!(drive->flags & Lba48))
    > return -1;
    > use48 = 1;


    while this does fix the problem, it's sloppy. the problem is actually
    that ata reports device sizes as number of sectors+1. it also does not follow
    the tradition used for sector counts, where 0 sector count = all-ones+1 = 256.
    this is because removable media drives with no media (eg cdroms) give size = 0.
    therefore if under any ata addressing scheme, the all-ones sector is not accessable.
    credit to sam hopkins for pointing this out.

    /n/sources/plan9//sys/src/9/pc/sdata.c:1344,1350 - sdata.c:1344,1350
    };

    + enum{
    + Last28 = (1<<28) - 1 - 1,
    + };
    +
    static int
    - atageniostart(Drive* drive, vlong lba)
    + atageniostart(Drive* drive, uvlong lba)
    {
    Ctlr *ctlr;
    uchar cmd;
    /n/sources/plan9//sys/src/9/pc/sdata.c:1351,1357 - sdata.c:1355,1361
    int as, c, cmdport, ctlport, h, len, s, use48;

    use48 = 0;
    - if((drive->flags&Lba48always) || (lba>>28) || drive->count > 256){
    + if((drive->flags&Lba48always) || lba > Last28 || drive->count > 256){
    if(!(drive->flags & Lba48))
    return -1;
    use48 = 1;


    - erik


+ Reply to Thread