[7609] in linux-scsi channel archive
Generic SCSI driver bug report
daemon@ATHENA.MIT.EDU (Soohoon Lee)
Fri Dec 3 12:41:25 1999
Message-ID: <037f01bf3dab$3f7f1be0$a53ce9c0@alphaprocessor.com>
From: "Soohoon Lee" <soohoon.lee@alpha-processor.com>
To: <drew@colorado.edu>, <eric@aib.com>,
<linux-scsi@vger.rutgers.edu>
Cc: "Hanwoo Cho" <Hanwoo.Cho@alpha-processor.com>,
<rich.payne@alpha-processor.com>,
"Ruth Shelley" <ruth@alpha-processor.com>,
"Software" <Software@alpha-processor.com>
Date: Fri, 3 Dec 1999 11:27:10 -0500
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="----=_NextPart_000_037C_01BF3D81.569E6580"
This is a multi-part message in MIME format.
------=_NextPart_000_037C_01BF3D81.569E6580
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
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 =3D NULL;
bh->b_end_io(bh, uptodate);
sectors -=3D bh->b_size >> 9;
if ((bh =3D req->bh) !=3D NULL) {
..................
} while(sectors && bh);
bh->b_end_io() wakes up waiting processes.=20
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 =3D NULL;
sectors -=3D bh->b_size >> 9;
bh->b_end_io(bh, uptodate);
if ((bh =3D req->bh) !=3D NULL) {
..................
} while(sectors && bh);
=20
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.
------=_NextPart_000_037C_01BF3D81.569E6580
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META content=3D"text/html; charset=3Diso-8859-1" =
http-equiv=3DContent-Type>
<META content=3D"MSHTML 5.00.2614.3401" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV> </DIV>
<DIV><FONT face=3DArial size=3D2>Hi</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>I'm having data corruption problem with =
Symbios=20
SCSI.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>Sometimes one sector size data is=20
disapeared.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>And after long =
investigation,</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>I've found that there's race condition =
in=20
drivers/scsi/scsi.h:end_scsi_request()</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=3DArial size=3D2> do =
{<BR>...........</FONT></DIV>
<DIV><FONT face=3DArial=20
size=3D2> &nbs=
p;=20
bh->b_reqnext =3D NULL;</FONT></DIV>
<DIV><FONT face=3DArial size=3D2><BR></FONT><FONT face=3DArial=20
size=3D2> &nbs=
p;=20
bh->b_end_io(bh,=20
uptodate);<BR>  =
; =20
sectors -=3D bh->b_size >> 9;</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=3DArial=20
size=3D2> &nbs=
p; if=20
((bh =3D req->bh) !=3D NULL) {<BR>..................</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> } while(sectors =
&&=20
bh);</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>bh->b_end_io() wakes up waiting =
processes.=20
</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>In MP platform, second CPU =
can wake up the=20
process immediately and the process</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>can do something against bh =
</FONT><FONT=20
face=3DArial size=3D2>before </FONT><FONT face=3DArial size=3D2>the next =
line is=20
executed.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>So if bh is freed and have all zeros in =
its=20
fields then bh->b_size is 0 and it makes the</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>next line's calculation =
wrong.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>And the wrong calculation leads to one =
more loop=20
and it ends unfinished request.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>And it makes one sector size hole at=20
somewhere.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>So fix would be this.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>swap the two lines.</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=3DArial size=3D2>
<DIV><FONT face=3DArial size=3D2> do =
{<BR>...........</FONT></DIV>
<DIV><FONT face=3DArial=20
size=3D2> &nbs=
p;=20
bh->b_reqnext =3D NULL;</FONT></DIV>
<DIV><FONT face=3DArial size=3D2><BR></FONT><FONT face=3DArial=20
size=3D2> &nbs=
p;=20
sectors -=3D bh->b_size >> 9;</FONT></DIV>
<DIV><FONT face=3DArial=20
size=3D2> &nbs=
p;=20
bh->b_end_io(bh, uptodate);<BR></FONT></DIV>
<DIV><FONT face=3DArial=20
size=3D2> &nbs=
p; if=20
((bh =3D req->bh) !=3D NULL) {<BR>..................</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> } while(sectors =
&&=20
bh);</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV></FONT></DIV>
<DIV><FONT face=3DArial size=3D2>And question.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>It looks like scsi subsystem=20
always reads/writes in 512bytes.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>they don't coalesce the requests. I =
know=20
ll_rw_block() try to do that.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>but when the request reaches to sd.c or =
bottom=20
driver, it's 512bytes.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>I put a printk in bottom driver's s/g =
function to=20
print request size if it's not 512 bytes.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>It reads 2 blocks(1024bytes) =
only near reading=20
partition tables.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>Isn't it bad for performance? Does =
tagged queueing=20
or something resolve</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>the problem? I saw the transactions =
with PCI=20
analyzer, indeed</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>they are transferred without=20
pause(Actually transaction is paused to read s/g list</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>between 512bytes burst but it's=20
ignorable).</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=3DArial size=3D2>Soohoon.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> </DIV></FONT></BODY></HTML>
------=_NextPart_000_037C_01BF3D81.569E6580--
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.rutgers.edu