generic SCSI driver problem in 2.2.x(till 14pre11)

Soohoon Lee (soohoon.lee@alpha-processor.com)
Mon, 6 Dec 1999 14:00:41 -0500


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, but is that
intended behaviour?).

Soohoon.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/