kern/52338: fd(4) floppy disk driver & non-blocking I/O

Bruce Evans bde at
Sat May 17 07:40:08 PDT 2003

The following reply was made to PR kern/52338; it has been noted by GNATS.

From: Bruce Evans <bde at>
To: Yar Tikhiy <yar at>
Cc: FreeBSD-gnats-submit at, freebsd-bugs at,
	joerg at
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.

More information about the freebsd-bugs mailing list