Date: Sat, 17 May 2003 07:40:07 -0700 (PDT) From: Bruce Evans <bde@zeta.org.au> To: freebsd-bugs@FreeBSD.org Subject: Re: kern/52338: fd(4) floppy disk driver & non-blocking I/O Message-ID: <200305171440.h4HEe7VT002647@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/52338; it has been noted by GNATS. From: Bruce Evans <bde@zeta.org.au> To: Yar Tikhiy <yar@comp.chem.msu.su> Cc: FreeBSD-gnats-submit@freebsd.org, freebsd-bugs@freebsd.org, joerg@freebsd.org Subject: Re: kern/52338: fd(4) floppy disk driver & non-blocking I/O Date: Sun, 18 May 2003 00:39:03 +1000 (EST) On Sat, 17 May 2003, Yar Tikhiy wrote: > I'm testing a somewhat different patch: > ... > But its first part yields an unexpected result: No error from > read() is reported at all! That happens because fdstrategy() doesn't > set bp->b_resid when indicating a error on a buffer; consequently, > the corresponding uio structure gets indication in physio() that > the data has been transferred; and dofileread() will clear the error > status if any bytes have been transferred and the error status is > EAGAIN or EINTR (see kern/sys_generic.c at line 195). It should set bp->bio_resid (to bp->bio_bcount) (bio_resid and bio_bcount are the same as b_resid and b_bcount here; strategy routines only have access to a struct bio so they must use the former). Strategy routines can return an error together with a count of bytes sucessfully transferred. They do this by setting BIO_ERROR and b_error as usual for an error, and returning the number of bytes _not_ successfully transferred in bio_resid. physio() actually understands this, although the upper layers are mostly broken (they should clear the error status and return the count of bytes successfully transferred in most cases, since there is no way to return both to the application layer and POSIX and POLA specify returning the count), but as you noticed they only do this for the EAGAIN and EINTR cases. This is a very old bug. Long ago, e.g., in FreeBSD-1, b_resid was (ab)used for a temporary variable by disksort(), so it was garbage in strategy routines unless they set it, but fdstrategy() didn't set it for early errors even in FreeBSD-1. Clobbering of b_resid in disksort() made early settings of it just bogus. Now, b_resid tends to stick at 0 which gives the fail-unsafe behaviour that you saw. Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200305171440.h4HEe7VT002647>