Hi
I'm having data corruption problem with Symbios SCSI.
Sometimes one sector size data is disapeared.
And after long investigation,
I've found that there's race condition in drivers/scsi/scsi.h:end_scsi_request()
 
    do {
...........
            bh->b_reqnext = NULL;

            bh->b_end_io(bh, uptodate);
            sectors -= bh->b_size >> 9;
 
            if ((bh = req->bh) != NULL) {
..................
    } while(sectors && bh);
 
bh->b_end_io() wakes up waiting processes.
In MP platform, second CPU can wake up the process immediately and the process
can do something against bh before the next line is executed.
So if bh is freed and have all zeros in its fields then bh->b_size is 0 and it makes the
next line's calculation wrong.
And the wrong calculation leads to one more loop and it ends unfinished request.
And it makes one sector size hole at somewhere.
 
So fix would be this.
swap the two lines.
 
    do {
...........
            bh->b_reqnext = NULL;

            sectors -= bh->b_size >> 9;
            bh->b_end_io(bh, uptodate);
            if ((bh = req->bh) != NULL) {
..................
    } while(sectors && bh);
 
And question.
It looks like scsi subsystem always reads/writes in 512bytes.
they don't coalesce the requests. I know ll_rw_block() try to do that.
but when the request reaches to sd.c or bottom driver, it's 512bytes.
I put a printk in bottom driver's s/g function to print request size if it's not 512 bytes.
It reads 2 blocks(1024bytes) only near reading partition tables.
Isn't it bad for performance? Does tagged queueing or something resolve
the problem? I saw the transactions with PCI analyzer, indeed
they are transferred without pause(Actually transaction is paused to read s/g list
between 512bytes burst but it's ignorable).
 
Soohoon.
 

Reply via email to