Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 17 May 2003 13:10:47 +0400
From:      Yar Tikhiy <yar@comp.chem.msu.su>
To:        Bruce Evans <bde@zeta.org.au>
Cc:        joerg@freebsd.org
Subject:   Re: kern/52338: fd(4) floppy disk driver & non-blocking I/O
Message-ID:  <20030517091047.GA82314@comp.chem.msu.su>
In-Reply-To: <20030517165718.B15076@gamplex.bde.org>
References:  <200305161646.h4GGkdDS000677@stylish.chem.msu.su> <20030517165718.B15076@gamplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help
[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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030517091047.GA82314>