|
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.
|
