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