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

Yar Tikhiy yar at freebsd.org
Mon May 19 11:30:11 PDT 2003


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

From: Yar Tikhiy <yar at freebsd.org>
To: Bruce Evans <bde at zeta.org.au>
Cc: FreeBSD-gnats-submit at freebsd.org, freebsd-bugs at freebsd.org,
	joerg at freebsd.org
Subject: Re: kern/52338: fd(4) floppy disk driver & non-blocking I/O
Date: Mon, 19 May 2003 22:23:57 +0400

 On Sun, May 18, 2003 at 12:39:03AM +1000, Bruce Evans wrote:
 > 
 > 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).
 
 What do you think about the following straightforward patch to fd.c?
 It catches all spots where BIO_ERROR is set, but bio_resid isn't.
 In fd.c, bio_resid is never set in advance, so the simplest approach
 should work.
 
 OTOH, I wonder if bio_resid could be set equal to bio_bcount at the
 beginning of fdstrategy() and changed only if needed.  Does this have
 any obscure implications?
 
 And my other thought is:  What if physio() sets bio_resid equal to
 bio_bcount before calling DEV_STRATEGY()?  Currently, physio()
 leaves bio_resid unset.  An obvious drawback of this approach is
 that it would encourage poor coding in drivers, though.
 
 -- 
 Yar
 
 --- fd.c.dist	Fri Apr 11 15:39:24 2003
 +++ fd.c	Mon May 19 21:48:11 2003
 @@ -1668,8 +1668,9 @@ fdstrategy(struct bio *bp)
  		      (u_long)major(bp->bio_dev), (u_long)minor(bp->bio_dev));
  	fdc = fd->fdc;
  	if (fd->type == FDT_NONE || fd->ft == 0) {
 -		bp->bio_error = ENXIO;
 +		bp->bio_error = fd->type == FDT_NONE ? ENXIO : EAGAIN;
  		bp->bio_flags |= BIO_ERROR;
 +		bp->bio_resid = bp->bio_bcount;
  		goto bad;
  	}
  	fdblk = 128 << (fd->ft->secsize);
 @@ -1677,6 +1678,7 @@ fdstrategy(struct bio *bp)
  		if (fd->flags & FD_NONBLOCK) {
  			bp->bio_error = EAGAIN;
  			bp->bio_flags |= BIO_ERROR;
 +			bp->bio_resid = bp->bio_bcount;
  			goto bad;
  		}
  		if (bp->bio_blkno < 0) {
 @@ -1685,11 +1687,13 @@ fdstrategy(struct bio *bp)
  			       fdu, (u_long)bp->bio_blkno, bp->bio_bcount);
  			bp->bio_error = EINVAL;
  			bp->bio_flags |= BIO_ERROR;
 +			bp->bio_resid = bp->bio_bcount;
  			goto bad;
  		}
  		if ((bp->bio_bcount % fdblk) != 0) {
  			bp->bio_error = EINVAL;
  			bp->bio_flags |= BIO_ERROR;
 +			bp->bio_resid = bp->bio_bcount;
  			goto bad;
  		}
  	}
 @@ -1704,15 +1708,15 @@ fdstrategy(struct bio *bp)
  		 */
  		bp->bio_error = EINVAL;
  		bp->bio_flags |= BIO_ERROR;
 +		bp->bio_resid = bp->bio_bcount;
  		goto bad;
  	}
  	blknum = bp->bio_blkno * DEV_BSIZE / fdblk;
   	nblocks = fd->ft->size;
  	if (blknum + bp->bio_bcount / fdblk > nblocks) {
  		if (blknum >= nblocks) {
 -			if (bp->bio_cmd == BIO_READ)
 -				bp->bio_resid = bp->bio_bcount;
 -			else {
 +			bp->bio_resid = bp->bio_bcount;
 +			if (bp->bio_cmd != BIO_READ) {
  				bp->bio_error = ENOSPC;
  				bp->bio_flags |= BIO_ERROR;
  			}
 =================================================================


More information about the freebsd-bugs mailing list