kern/52338: fd(4) floppy disk driver & non-blocking I/O
Yar Tikhiy
yar at comp.chem.msu.su
Sat May 17 02:11:04 PDT 2003
[I'm adding joerg@, who has hacked fdc(4) a lot, to CC: ]
[so he can participate in this discussion. ]
I'm testing a somewhat different patch:
==============================================================================
--- fd.c.orig Fri Apr 11 15:39:24 2003
+++ fd.c Sat May 17 13:05:32 2003
@@ -1667,11 +1667,16 @@
panic("fdstrategy: buf for nonexistent device (%#lx, %#lx)",
(u_long)major(bp->bio_dev), (u_long)minor(bp->bio_dev));
fdc = fd->fdc;
- if (fd->type == FDT_NONE || fd->ft == 0) {
+ if (fd->type == FDT_NONE) {
bp->bio_error = ENXIO;
bp->bio_flags |= BIO_ERROR;
goto bad;
}
+ if (fd->ft == 0) {
+ bp->bio_error = EAGAIN;
+ bp->bio_flags |= BIO_ERROR;
+ goto bad;
+ }
fdblk = 128 << (fd->ft->secsize);
if (bp->bio_cmd != FDBIO_FORMAT && bp->bio_cmd != FDBIO_RDSECTID) {
if (fd->flags & FD_NONBLOCK) {
@@ -2605,6 +2610,7 @@
{
fdu_t fdu;
fd_p fd;
+ struct fd_type *ft;
struct fdc_status *fsp;
struct fdc_readid *rid;
size_t fdblk;
@@ -2614,6 +2620,14 @@
type = FDTYPE(minor(dev));
fd = devclass_get_softc(fd_devclass, fdu);
+ if (fd->type == FDT_NONE)
+ return (ENXIO);
+ if (fd->ft == 0)
+ /* no type known yet, use the native type */
+ ft = &fd_native_types[fd->type];
+ else
+ ft = fd->ft;
+
/*
* First, handle everything that could be done with
* FD_NONBLOCK still being set.
@@ -2621,11 +2635,11 @@
switch (cmd) {
case DIOCGMEDIASIZE:
- *(off_t *)addr = (128 << (fd->ft->secsize)) * fd->ft->size;
+ *(off_t *)addr = (128 << (ft->secsize)) * ft->size;
return (0);
case DIOCGSECTORSIZE:
- *(u_int *)addr = 128 << (fd->ft->secsize);
+ *(u_int *)addr = 128 << (ft->secsize);
return (0);
case FIONBIO:
@@ -2648,11 +2662,7 @@
return (0);
case FD_GTYPE: /* get drive type */
- if (fd->ft == 0)
- /* no type known yet, return the native type */
- *(struct fd_type *)addr = fd_native_types[fd->type];
- else
- *(struct fd_type *)addr = *fd->ft;
+ *(struct fd_type *)addr = *ft;
return (0);
case FD_STYPE: /* set drive type */
==============================================================================
It is intended to achieve two goals:
- first, to change the buffer error status in fdstrategy() for
the fd->ft==NULL case, so read(2) or write(2) will return EAGAIN,
as per the fdc(4) manpage;
- second, to make fdioctl() return geometry defaults for the current
fd->type if fd->ft is NULL.
Its second part works well, though I'm unsure which way is
better, mine (use a default fd_type) or yours (return ENXIO).
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).
I must admit that my current knowledge of BIO is insufficient to
understand what is actually wrong with the above scheme. Any idea?
--
Yar
More information about the freebsd-bugs
mailing list